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.Renderer;
41  import org.apache.maven.doxia.siterenderer.RendererException;
42  import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
43  import org.apache.maven.plugins.site.render.ReportDocumentRenderer;
44  import org.eclipse.jetty.http.MimeTypes;
45  
46  import static org.apache.maven.shared.utils.logging.MessageUtils.buffer;
47  
48  /**
49   * Render a page as requested.
50   *
51   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
52   */
53  public class DoxiaFilter implements Filter {
54      public static final String OUTPUT_DIRECTORY_KEY = "outputDirectory";
55  
56      public static final String SITE_RENDERER_KEY = "siteRenderer";
57  
58      public static final String I18N_DOXIA_CONTEXTS_KEY = "i18nDoxiaContexts";
59  
60      public static final String LOCALES_LIST_KEY = "localesList";
61  
62      private ServletContext servletContext;
63  
64      private File outputDirectory;
65  
66      private Renderer siteRenderer;
67  
68      private Map<String, DoxiaBean> i18nDoxiaContexts;
69  
70      private List<Locale> localesList;
71  
72      /**
73       * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
74       */
75      public void init(FilterConfig filterConfig) throws ServletException {
76          servletContext = filterConfig.getServletContext();
77  
78          outputDirectory = (File) servletContext.getAttribute(OUTPUT_DIRECTORY_KEY);
79  
80          siteRenderer = (Renderer) servletContext.getAttribute(SITE_RENDERER_KEY);
81  
82          i18nDoxiaContexts = (Map<String, DoxiaBean>) servletContext.getAttribute(I18N_DOXIA_CONTEXTS_KEY);
83  
84          localesList = (List<Locale>) servletContext.getAttribute(LOCALES_LIST_KEY);
85      }
86  
87      /**
88       * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
89       */
90      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
91              throws IOException, ServletException {
92          HttpServletRequest req = (HttpServletRequest) servletRequest;
93  
94          // ----------------------------------------------------------------------
95          // Handle the servlet path
96          // ----------------------------------------------------------------------
97          String path = req.getServletPath();
98          // welcome file
99          if (path.endsWith("/")) {
100             path += "index.html";
101         }
102 
103         // Remove the /
104         path = path.substring(1);
105 
106         // Handle locale request
107         SiteRenderingContext context;
108         Map<String, DocumentRenderer> documents;
109         SiteRenderingContext generatedSiteContext;
110 
111         String localeWanted = null;
112         for (Locale locale : localesList) {
113             if (path.startsWith(locale + "/")) {
114                 localeWanted = locale.toString();
115                 path = path.substring(localeWanted.length() + 1);
116             }
117         }
118 
119         if (localeWanted == null) {
120             DoxiaBean defaultDoxiaBean = i18nDoxiaContexts.get("default");
121             if (defaultDoxiaBean == null) {
122                 throw new ServletException("No doxia bean found for the default locale");
123             }
124             context = defaultDoxiaBean.getContext();
125             documents = defaultDoxiaBean.getDocuments();
126             generatedSiteContext = defaultDoxiaBean.getGeneratedSiteContext();
127         } else {
128             DoxiaBean i18nDoxiaBean = i18nDoxiaContexts.get(localeWanted);
129             if (i18nDoxiaBean == null) {
130                 throw new ServletException("No doxia bean found for locale '" + localeWanted + "'");
131             }
132             context = i18nDoxiaBean.getContext();
133             documents = i18nDoxiaBean.getDocuments();
134             generatedSiteContext = i18nDoxiaBean.getGeneratedSiteContext();
135         }
136 
137         // ----------------------------------------------------------------------
138         // Handle report and documents
139         // ----------------------------------------------------------------------
140         if (documents.containsKey(path)) {
141             try {
142                 DocumentRenderer renderer = documents.get(path);
143                 logDocumentRenderer(path, renderer);
144                 String outputName = renderer.getOutputName();
145                 String contentType = MimeTypes.getDefaultMimeByExtension(outputName);
146                 if (contentType != null) {
147                     servletResponse.setContentType(contentType);
148                 }
149                 renderer.renderDocument(servletResponse.getWriter(), siteRenderer, context);
150 
151                 if (renderer instanceof ReportDocumentRenderer) {
152                     ReportDocumentRenderer reportDocumentRenderer = (ReportDocumentRenderer) renderer;
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 renderer = locateDocuments.get(path);
174                     logDocumentRenderer(path, renderer);
175                     String outputName = renderer.getOutputName();
176                     String contentType = MimeTypes.getDefaultMimeByExtension(outputName);
177                     if (contentType != null) {
178                         servletResponse.setContentType(contentType);
179                     }
180                     renderer.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, DocumentRenderer renderer) {
193         String source;
194         if (renderer instanceof DoxiaDocumentRenderer) {
195             DoxiaDocumentRenderer doxiaDocumentRenderer = (DoxiaDocumentRenderer) renderer;
196             source = doxiaDocumentRenderer.getRenderingContext().getInputName();
197         } else if (renderer instanceof ReportDocumentRenderer) {
198             ReportDocumentRenderer reportDocumentRenderer = (ReportDocumentRenderer) renderer;
199             source = reportDocumentRenderer.getReportMojoInfo();
200         } else {
201             source = renderer.getClass().getName();
202         }
203         servletContext.log(path + " -> " + buffer().strong(source));
204     }
205 
206     /**
207      * @see javax.servlet.Filter#destroy()
208      */
209     public void destroy() {}
210 }