View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.site.run;
20  
21  import javax.servlet.Filter;
22  import javax.servlet.FilterChain;
23  import javax.servlet.FilterConfig;
24  import javax.servlet.ServletContext;
25  import javax.servlet.ServletException;
26  import javax.servlet.ServletRequest;
27  import javax.servlet.ServletResponse;
28  import javax.servlet.http.HttpServletRequest;
29  
30  import java.io.File;
31  import java.io.IOException;
32  import java.nio.file.Files;
33  import java.nio.file.Path;
34  import java.util.List;
35  import java.util.Locale;
36  import java.util.Map;
37  
38  import org.apache.maven.doxia.siterenderer.DocumentRenderer;
39  import org.apache.maven.doxia.siterenderer.DoxiaDocumentRenderer;
40  import org.apache.maven.doxia.siterenderer.RendererException;
41  import org.apache.maven.doxia.siterenderer.SiteRenderer;
42  import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
43  import org.apache.maven.doxia.tools.SiteTool;
44  import org.apache.maven.plugins.site.render.ReportDocumentRenderer;
45  import org.eclipse.jetty.http.MimeTypes;
46  
47  import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
48  
49  /**
50   * Render a page as requested.
51   *
52   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
53   */
54  public class DoxiaFilter implements Filter {
55      public static final String OUTPUT_DIRECTORY_KEY = "outputDirectory";
56  
57      public static final String SITE_RENDERER_KEY = "siteRenderer";
58  
59      public static final String I18N_DOXIA_CONTEXTS_KEY = "i18nDoxiaContexts";
60  
61      public static final String LOCALES_LIST_KEY = "localesList";
62  
63      private ServletContext servletContext;
64  
65      private File outputDirectory;
66  
67      private SiteRenderer siteRenderer;
68  
69      private Map<String, DoxiaBean> i18nDoxiaContexts;
70  
71      private List<Locale> localesList;
72  
73      /**
74       * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
75       */
76      public void init(FilterConfig filterConfig) throws ServletException {
77          servletContext = filterConfig.getServletContext();
78  
79          outputDirectory = (File) servletContext.getAttribute(OUTPUT_DIRECTORY_KEY);
80  
81          siteRenderer = (SiteRenderer) servletContext.getAttribute(SITE_RENDERER_KEY);
82  
83          i18nDoxiaContexts = (Map<String, DoxiaBean>) servletContext.getAttribute(I18N_DOXIA_CONTEXTS_KEY);
84  
85          localesList = (List<Locale>) servletContext.getAttribute(LOCALES_LIST_KEY);
86      }
87  
88      /**
89       * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
90       */
91      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
92              throws IOException, ServletException {
93          HttpServletRequest req = (HttpServletRequest) servletRequest;
94  
95          // ----------------------------------------------------------------------
96          // Handle the servlet path
97          // ----------------------------------------------------------------------
98          String path = req.getServletPath();
99          // welcome file
100         if (path.endsWith("/")) {
101             path += "index.html";
102         }
103 
104         // Remove the /
105         path = path.substring(1);
106 
107         // Handle locale request
108         SiteRenderingContext context;
109         Map<String, DocumentRenderer> documents;
110         SiteRenderingContext generatedSiteContext;
111 
112         String localeWanted = "";
113         for (Locale locale : localesList) {
114             if (path.startsWith(locale + "/")) {
115                 localeWanted = locale.toString();
116                 path = path.substring(localeWanted.length() + 1);
117             }
118         }
119 
120         DoxiaBean doxiaBean;
121         if (!localeWanted.equals(SiteTool.DEFAULT_LOCALE.toString())) {
122             doxiaBean = i18nDoxiaContexts.get(localeWanted);
123             if (doxiaBean == null) {
124                 throw new ServletException("No Doxia bean found for locale '" + localeWanted + "'");
125             }
126         } else {
127             doxiaBean = i18nDoxiaContexts.get("default");
128             if (doxiaBean == null) {
129                 throw new ServletException("No Doxia bean found for the default locale");
130             }
131         }
132         context = doxiaBean.getContext();
133         documents = doxiaBean.getDocuments();
134         generatedSiteContext = doxiaBean.getGeneratedSiteContext();
135 
136         // ----------------------------------------------------------------------
137         // Handle report and documents
138         // ----------------------------------------------------------------------
139         if (documents.containsKey(path)) {
140             try {
141                 DocumentRenderer docRenderer = documents.get(path);
142                 logDocumentRenderer(path, localeWanted, docRenderer);
143                 String outputName = docRenderer.getOutputName();
144                 String contentType = MimeTypes.getDefaultMimeByExtension(outputName);
145                 if (contentType != null) {
146                     servletResponse.setContentType(contentType);
147                 }
148                 docRenderer.renderDocument(servletResponse.getWriter(), siteRenderer, context);
149 
150                 if (docRenderer instanceof ReportDocumentRenderer) {
151                     ReportDocumentRenderer reportDocumentRenderer = (ReportDocumentRenderer) docRenderer;
152                     if (reportDocumentRenderer.isExternalReport()) {
153                         Path externalReportFile = outputDirectory.toPath().resolve(outputName);
154                         servletResponse.reset();
155                         if (contentType != null) {
156                             servletResponse.setContentType(contentType);
157                         }
158                         Files.copy(externalReportFile, servletResponse.getOutputStream());
159                     }
160                 }
161 
162                 return;
163             } catch (RendererException e) {
164                 throw new ServletException(e);
165             }
166         } else if (generatedSiteContext != null) {
167             try {
168                 Map<String, DocumentRenderer> locateDocuments =
169                         siteRenderer.locateDocumentFiles(generatedSiteContext, false);
170 
171                 if (locateDocuments.containsKey(path)) {
172                     DocumentRenderer docRenderer = locateDocuments.get(path);
173                     logDocumentRenderer(path, localeWanted, docRenderer);
174                     String outputName = docRenderer.getOutputName();
175                     String contentType = MimeTypes.getDefaultMimeByExtension(outputName);
176                     if (contentType != null) {
177                         servletResponse.setContentType(contentType);
178                     }
179                     docRenderer.renderDocument(servletResponse.getWriter(), siteRenderer, generatedSiteContext);
180 
181                     return;
182                 }
183             } catch (RendererException e) {
184                 throw new ServletException(e);
185             }
186         }
187 
188         filterChain.doFilter(servletRequest, servletResponse);
189     }
190 
191     private void logDocumentRenderer(String path, String locale, DocumentRenderer docRenderer) {
192         String source;
193         if (docRenderer instanceof DoxiaDocumentRenderer) {
194             DoxiaDocumentRenderer doxiaDocumentRenderer = (DoxiaDocumentRenderer) docRenderer;
195             source = doxiaDocumentRenderer.getRenderingContext().getInputName();
196         } else if (docRenderer instanceof ReportDocumentRenderer) {
197             ReportDocumentRenderer reportDocumentRenderer = (ReportDocumentRenderer) docRenderer;
198             source = reportDocumentRenderer.getReportMojoInfo();
199         } else {
200             source = docRenderer.getClass().getName();
201         }
202         String localizedPath = !locale.equals(SiteTool.DEFAULT_LOCALE.toString()) ? locale + "/" + path : path;
203         String localizedSource = source
204                 + (!locale.equals(SiteTool.DEFAULT_LOCALE.toString())
205                         ? " (locale '" + locale + "')"
206                         : " (default locale)");
207         servletContext.log(localizedPath + " -> " + buffer().strong(localizedSource));
208     }
209 
210     /**
211      * @see javax.servlet.Filter#destroy()
212      */
213     public void destroy() {}
214 }