001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.server.view;
018
019import java.io.*;
020
021import org.apache.juneau.http.*;
022import org.apache.juneau.rest.server.*;
023import org.apache.juneau.rest.server.servlet.*;
024
025/**
026 * Abstract base for the standalone view-servlet companions of the view mixin resources.
027 *
028 * <p>
029 * Each per-engine bridge module ({@code juneau-rest-server-view-jsp},
030 * {@code juneau-rest-server-view-freemarker}, {@code juneau-rest-server-view-mustache},
031 * {@code juneau-rest-server-view-thymeleaf}) ships a thin {@code Basic*Servlet} subclass that:
032 *
033 * <ol class='spaced-list'>
034 *    <li>Declares its own sibling top-level mount via {@link Rest#paths() @Rest(paths)} (e.g.
035 *       {@code "/jsp/*"}), so the servlet is registered as a sibling of the host application's other
036 *       servlets ({@code /rest/*}, {@code /jsp/*}, ...) rather than composed under a host root.
037 *    <li>Supplies the per-engine {@link RawTemplateDispatcher} (the matching flavor-neutral
038 *       {@code <Engine>Dispatcher} worker) via {@link #dispatcher()}.
039 * </ol>
040 *
041 * <p>
042 * The single greedy op declared here ({@code @RestGet(path="/*")}) captures the trailing remainder
043 * under the servlet's mount and delegates straight to the shared {@link RawTemplateDispatcher}.
044 * Because the mixin and standalone forms both route through the same {@code RawTemplateDispatcher}
045 * implementation, their raw file-serving behavior cannot drift.
046 *
047 * <h5 class='section'>Standalone vs mixin:</h5>
048 *
049 * <p>
050 * The mixin {@code Basic*Resource} keeps its op pinned at {@code /<token>/*} for composition into a
051 * host at {@code /}; the standalone {@code Basic*Servlet} moves the mount to the class level
052 * ({@code @Rest(paths="/<token>/*")}) and pins the op at {@code /*}, eliminating the path-doubling
053 * that a mixin-shaped op would otherwise produce when the servlet itself is mounted at
054 * {@code /<token>/*}.
055 *
056 * <h5 class='section'>See Also:</h5><ul>
057 *    <li class='jic'>{@link RawTemplateDispatcher}
058 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/RestServerComposition">REST Server — Mixins and Multi-Mount Paths</a>
059 * </ul>
060 *
061 * @serial exclude
062 * @since 10.0.0
063 */
064@Rest
065public abstract class ViewServlet extends RestServlet {
066
067   private static final long serialVersionUID = 1L;
068
069   /**
070    * Returns the per-engine {@link RawTemplateDispatcher} this servlet delegates raw template
071    * dispatch to.
072    *
073    * <p>
074    * Typically the matching flavor-neutral {@code <Engine>Dispatcher} worker (which implements
075    * {@link RawTemplateDispatcher}).  Never {@code null}.
076    *
077    * @return The raw-template dispatcher. Never {@code null}.
078    */
079   protected abstract RawTemplateDispatcher dispatcher();
080
081   /**
082    * [GET /*] &mdash; render the raw template identified by the trailing path under this servlet's
083    * sibling top-level mount.
084    *
085    * <p>
086    * The {@code @Path("/*") String path} captures the multi-segment remainder after the mount
087    * prefix (e.g. a request for {@code /jsp/admin/dashboard.jsp} on a servlet mounted at
088    * {@code /jsp/*} matches with {@code path = "admin/dashboard.jsp"}).  Delegates verbatim to the
089    * shared {@link RawTemplateDispatcher}.
090    *
091    * @param path The trailing path segment after the mount prefix.
092    * @param req The current REST request.
093    * @param res The current REST response.
094    * @throws IOException If the underlying response writer fails.
095    */
096   @RestGet(
097      path="/*",
098      summary="View",
099      description="Render a raw template under this servlet's sibling top-level mount.",
100      swagger=@OpSwagger(ignore=true)
101   )
102   public void render(@Path("/*") String path, RestRequest req, RestResponse res) throws IOException {
103      dispatcher().render(path, req, res);
104   }
105}