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      @Override
78      public void init(FilterConfig filterConfig) throws ServletException {
79          servletContext = filterConfig.getServletContext();
80  
81          outputDirectory = (File) servletContext.getAttribute(OUTPUT_DIRECTORY_KEY);
82  
83          siteRenderer = (SiteRenderer) servletContext.getAttribute(SITE_RENDERER_KEY);
84  
85          i18nDoxiaContexts = (Map<String, DoxiaBean>) servletContext.getAttribute(I18N_DOXIA_CONTEXTS_KEY);
86  
87          localesList = (List<Locale>) servletContext.getAttribute(LOCALES_LIST_KEY);
88      }
89  
90      /**
91       * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
92       */
93      @Override
94      public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
95              throws IOException, ServletException {
96          HttpServletRequest req = (HttpServletRequest) servletRequest;
97  
98          // ----------------------------------------------------------------------
99          // Handle the servlet path
100         // ----------------------------------------------------------------------
101         String path = req.getServletPath();
102         // welcome file
103         if (path.endsWith("/")) {
104             path += "index.html";
105         }
106 
107         // Remove the /
108         path = path.substring(1);
109 
110         // Handle locale request
111         SiteRenderingContext context;
112         Map<String, DocumentRenderer> documents;
113 
114         String localeWanted = "";
115         for (Locale locale : localesList) {
116             if (path.startsWith(locale + "/")) {
117                 localeWanted = locale.toString();
118                 path = path.substring(localeWanted.length() + 1);
119             }
120         }
121 
122         DoxiaBean doxiaBean;
123         if (!localeWanted.equals(SiteTool.DEFAULT_LOCALE.toString())) {
124             doxiaBean = i18nDoxiaContexts.get(localeWanted);
125             if (doxiaBean == null) {
126                 throw new ServletException("No Doxia bean found for locale '" + localeWanted + "'");
127             }
128         } else {
129             doxiaBean = i18nDoxiaContexts.get("default");
130             if (doxiaBean == null) {
131                 throw new ServletException("No Doxia bean found for the default locale");
132             }
133         }
134         context = doxiaBean.getContext();
135         documents = doxiaBean.getDocuments();
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         }
168 
169         filterChain.doFilter(servletRequest, servletResponse);
170     }
171 
172     private void logDocumentRenderer(String path, String locale, DocumentRenderer docRenderer) {
173         String source;
174         if (docRenderer instanceof DoxiaDocumentRenderer) {
175             source = docRenderer.getRenderingContext().getDoxiaSourcePath();
176         } else if (docRenderer instanceof ReportDocumentRenderer) {
177             source = ((ReportDocumentRenderer) docRenderer).getReportMojoInfo();
178             if (source == null) {
179                 source = "(unknown)";
180             }
181         } else if (docRenderer instanceof SitePluginReportDocumentRenderer) {
182             source = ((SitePluginReportDocumentRenderer) docRenderer).getReportMojoInfo();
183         } else {
184             source = docRenderer.getRenderingContext().getGenerator() != null
185                     ? docRenderer.getRenderingContext().getGenerator()
186                     : docRenderer.getClass().getName();
187         }
188         String localizedPath = !locale.equals(SiteTool.DEFAULT_LOCALE.toString()) ? locale + "/" + path : path;
189         String localizedSource = source
190                 + (!locale.equals(SiteTool.DEFAULT_LOCALE.toString())
191                         ? " (locale '" + locale + "')"
192                         : " (default locale)");
193         servletContext.log(localizedPath + " -> " + buffer().strong(localizedSource));
194     }
195 
196     /**
197      * @see javax.servlet.Filter#destroy()
198      */
199     @Override
200     public void destroy() {}
201 }