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.apache.maven.plugins.site.render.SitePluginReportDocumentRenderer;
46  import org.eclipse.jetty.http.MimeTypes;
47  
48  import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
49  
50  /**
51   * Render a page as requested.
52   *
53   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
54   */
55  public class DoxiaFilter implements Filter {
56      public static final String OUTPUT_DIRECTORY_KEY = "outputDirectory";
57  
58      public static final String SITE_RENDERER_KEY = "siteRenderer";
59  
60      public static final String I18N_DOXIA_CONTEXTS_KEY = "i18nDoxiaContexts";
61  
62      public static final String LOCALES_LIST_KEY = "localesList";
63  
64      private ServletContext servletContext;
65  
66      private File outputDirectory;
67  
68      private SiteRenderer siteRenderer;
69  
70      private Map<String, DoxiaBean> i18nDoxiaContexts;
71  
72      private List<Locale> localesList;
73  
74      /**
75       * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
76       */
77      public void init(FilterConfig filterConfig) throws ServletException {
78          servletContext = filterConfig.getServletContext();
79  
80          outputDirectory = (File) servletContext.getAttribute(OUTPUT_DIRECTORY_KEY);
81  
82          siteRenderer = (SiteRenderer) servletContext.getAttribute(SITE_RENDERER_KEY);
83  
84          i18nDoxiaContexts = (Map<String, DoxiaBean>) servletContext.getAttribute(I18N_DOXIA_CONTEXTS_KEY);
85  
86          localesList = (List<Locale>) servletContext.getAttribute(LOCALES_LIST_KEY);
87      }
88  
89      /**
90       * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
91       */
92      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
93              throws IOException, ServletException {
94          HttpServletRequest req = (HttpServletRequest) servletRequest;
95  
96          // ----------------------------------------------------------------------
97          // Handle the servlet path
98          // ----------------------------------------------------------------------
99          String path = req.getServletPath();
100         // welcome file
101         if (path.endsWith("/")) {
102             path += "index.html";
103         }
104 
105         // Remove the /
106         path = path.substring(1);
107 
108         // Handle locale request
109         SiteRenderingContext context;
110         Map<String, DocumentRenderer> documents;
111         SiteRenderingContext generatedSiteContext;
112 
113         String localeWanted = "";
114         for (Locale locale : localesList) {
115             if (path.startsWith(locale + "/")) {
116                 localeWanted = locale.toString();
117                 path = path.substring(localeWanted.length() + 1);
118             }
119         }
120 
121         DoxiaBean doxiaBean;
122         if (!localeWanted.equals(SiteTool.DEFAULT_LOCALE.toString())) {
123             doxiaBean = i18nDoxiaContexts.get(localeWanted);
124             if (doxiaBean == null) {
125                 throw new ServletException("No Doxia bean found for locale '" + localeWanted + "'");
126             }
127         } else {
128             doxiaBean = i18nDoxiaContexts.get("default");
129             if (doxiaBean == null) {
130                 throw new ServletException("No Doxia bean found for the default locale");
131             }
132         }
133         context = doxiaBean.getContext();
134         documents = doxiaBean.getDocuments();
135         generatedSiteContext = doxiaBean.getGeneratedSiteContext();
136 
137         // ----------------------------------------------------------------------
138         // Handle report and documents
139         // ----------------------------------------------------------------------
140         if (documents.containsKey(path)) {
141             try {
142                 DocumentRenderer docRenderer = documents.get(path);
143                 logDocumentRenderer(path, localeWanted, docRenderer);
144                 String outputName = docRenderer.getOutputName();
145                 String contentType = MimeTypes.getDefaultMimeByExtension(outputName);
146                 if (contentType != null) {
147                     servletResponse.setContentType(contentType);
148                 }
149                 docRenderer.renderDocument(servletResponse.getWriter(), siteRenderer, context);
150 
151                 if (docRenderer instanceof ReportDocumentRenderer) {
152                     ReportDocumentRenderer reportDocumentRenderer = (ReportDocumentRenderer) docRenderer;
153                     if (reportDocumentRenderer.isExternalReport()) {
154                         Path externalReportFile = outputDirectory.toPath().resolve(outputName);
155                         servletResponse.reset();
156                         if (contentType != null) {
157                             servletResponse.setContentType(contentType);
158                         }
159                         Files.copy(externalReportFile, servletResponse.getOutputStream());
160                     }
161                 }
162 
163                 return;
164             } catch (RendererException e) {
165                 throw new ServletException(e);
166             }
167         } else if (generatedSiteContext != null) {
168             try {
169                 Map<String, DocumentRenderer> locateDocuments =
170                         siteRenderer.locateDocumentFiles(generatedSiteContext, false);
171 
172                 if (locateDocuments.containsKey(path)) {
173                     DocumentRenderer docRenderer = locateDocuments.get(path);
174                     logDocumentRenderer(path, localeWanted, docRenderer);
175                     String outputName = docRenderer.getOutputName();
176                     String contentType = MimeTypes.getDefaultMimeByExtension(outputName);
177                     if (contentType != null) {
178                         servletResponse.setContentType(contentType);
179                     }
180                     docRenderer.renderDocument(servletResponse.getWriter(), siteRenderer, generatedSiteContext);
181 
182                     return;
183                 }
184             } catch (RendererException e) {
185                 throw new ServletException(e);
186             }
187         }
188 
189         filterChain.doFilter(servletRequest, servletResponse);
190     }
191 
192     private void logDocumentRenderer(String path, String locale, DocumentRenderer docRenderer) {
193         String source;
194         if (docRenderer instanceof DoxiaDocumentRenderer) {
195             source = docRenderer.getRenderingContext().getDoxiaSourcePath();
196         } else if (docRenderer instanceof ReportDocumentRenderer) {
197             source = ((ReportDocumentRenderer) docRenderer).getReportMojoInfo();
198             if (source == null) {
199                 source = "(unknown)";
200             }
201         } else if (docRenderer instanceof SitePluginReportDocumentRenderer) {
202             source = ((SitePluginReportDocumentRenderer) docRenderer).getReportMojoInfo();
203         } else {
204             source = docRenderer.getRenderingContext().getGenerator() != null
205                     ? docRenderer.getRenderingContext().getGenerator()
206                     : docRenderer.getClass().getName();
207         }
208         String localizedPath = !locale.equals(SiteTool.DEFAULT_LOCALE.toString()) ? locale + "/" + path : path;
209         String localizedSource = source
210                 + (!locale.equals(SiteTool.DEFAULT_LOCALE.toString())
211                         ? " (locale '" + locale + "')"
212                         : " (default locale)");
213         servletContext.log(localizedPath + " -> " + buffer().strong(localizedSource));
214     }
215 
216     /**
217      * @see javax.servlet.Filter#destroy()
218      */
219     public void destroy() {}
220 }