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 
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 
135         // ----------------------------------------------------------------------
136         // Handle report and documents
137         // ----------------------------------------------------------------------
138         if (documents.containsKey(path)) {
139             try {
140                 DocumentRenderer docRenderer = documents.get(path);
141                 logDocumentRenderer(path, localeWanted, docRenderer);
142                 String outputName = docRenderer.getOutputName();
143                 String contentType = MimeTypes.getDefaultMimeByExtension(outputName);
144                 if (contentType != null) {
145                     servletResponse.setContentType(contentType);
146                 }
147                 docRenderer.renderDocument(servletResponse.getWriter(), siteRenderer, context);
148 
149                 if (docRenderer instanceof ReportDocumentRenderer) {
150                     ReportDocumentRenderer reportDocumentRenderer = (ReportDocumentRenderer) docRenderer;
151                     if (reportDocumentRenderer.isExternalReport()) {
152                         Path externalReportFile = outputDirectory.toPath().resolve(outputName);
153                         servletResponse.reset();
154                         if (contentType != null) {
155                             servletResponse.setContentType(contentType);
156                         }
157                         Files.copy(externalReportFile, servletResponse.getOutputStream());
158                     }
159                 }
160 
161                 return;
162             } catch (RendererException e) {
163                 throw new ServletException(e);
164             }
165         }
166 
167         filterChain.doFilter(servletRequest, servletResponse);
168     }
169 
170     private void logDocumentRenderer(String path, String locale, DocumentRenderer docRenderer) {
171         String source;
172         if (docRenderer instanceof DoxiaDocumentRenderer) {
173             source = docRenderer.getRenderingContext().getDoxiaSourcePath();
174         } else if (docRenderer instanceof ReportDocumentRenderer) {
175             source = ((ReportDocumentRenderer) docRenderer).getReportMojoInfo();
176             if (source == null) {
177                 source = "(unknown)";
178             }
179         } else if (docRenderer instanceof SitePluginReportDocumentRenderer) {
180             source = ((SitePluginReportDocumentRenderer) docRenderer).getReportMojoInfo();
181         } else {
182             source = docRenderer.getRenderingContext().getGenerator() != null
183                     ? docRenderer.getRenderingContext().getGenerator()
184                     : docRenderer.getClass().getName();
185         }
186         String localizedPath = !locale.equals(SiteTool.DEFAULT_LOCALE.toString()) ? locale + "/" + path : path;
187         String localizedSource = source
188                 + (!locale.equals(SiteTool.DEFAULT_LOCALE.toString())
189                         ? " (locale '" + locale + "')"
190                         : " (default locale)");
191         servletContext.log(localizedPath + " -> " + buffer().strong(localizedSource));
192     }
193 
194     /**
195      * @see javax.servlet.Filter#destroy()
196      */
197     public void destroy() {}
198 }