Clover Coverage Report - magnolia-module-templating 4.4.5
Coverage timestamp: Mon Sep 12 2011 16:32:30 CEST
../../../../img/srcFileCovDistChart0.png 54% of files have more coverage
64   250   24   12.8
22   141   0.38   5
5     4.8  
1    
 
  RenderingFilter       Line # 73 64 0% 24 91 0% 0.0
 
No Tests
 
1    /**
2    * This file Copyright (c) 2003-2011 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.module.templating;
35   
36    import info.magnolia.cms.core.AggregationState;
37    import info.magnolia.cms.core.Content;
38    import info.magnolia.cms.core.HierarchyManager;
39    import info.magnolia.cms.core.NodeData;
40    import info.magnolia.cms.filters.AbstractMgnlFilter;
41    import info.magnolia.cms.util.LazyInitPrintWriter;
42    import info.magnolia.context.MgnlContext;
43    import info.magnolia.module.templating.engine.RenderingEngine;
44    import info.magnolia.objectfactory.Components;
45   
46    import java.io.IOException;
47    import java.io.InputStream;
48   
49    import javax.jcr.PathNotFoundException;
50    import javax.jcr.PropertyType;
51    import javax.jcr.RepositoryException;
52    import javax.jcr.Value;
53    import javax.servlet.FilterChain;
54    import javax.servlet.ServletException;
55    import javax.servlet.ServletOutputStream;
56    import javax.servlet.http.HttpServletRequest;
57    import javax.servlet.http.HttpServletResponse;
58   
59    import org.apache.commons.io.IOUtils;
60    import org.apache.commons.lang.StringUtils;
61    import org.apache.commons.lang.math.NumberUtils;
62    import org.slf4j.Logger;
63    import org.slf4j.LoggerFactory;
64   
65    /**
66    * Filter responsible for rendering the current aggregation state,
67    * by delegating to the appropriate TemplateRenderer or by serving
68    * binary content.
69    *
70    * @author Philipp Bracher
71    * @version $Revision: 41137 $ ($Author: gjoseph $)
72    */
 
73    public class RenderingFilter extends AbstractMgnlFilter {
74    private static final Logger log = LoggerFactory.getLogger(RenderingFilter.class);
75   
76    protected RenderingEngine renderingEngine = Components.getSingleton(RenderingEngine.class);
77   
 
78  0 toggle public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException{
79  0 final AggregationState aggregationState = MgnlContext.getAggregationState();
80   
81  0 String templateName = aggregationState.getTemplateName();
82  0 if (StringUtils.isNotEmpty(templateName)) {
83  0 try {
84    // don't reset any existing status code, see MAGNOLIA-2005
85    // response.setStatus(HttpServletResponse.SC_OK);
86  0 if (response != MgnlContext.getWebContext().getResponse()) {
87  0 log.warn("Context response not synced. This may lead to discrepancies in rendering.");
88    }
89   
90  0 Content content = aggregationState.getMainContent();
91   
92  0 render(content, templateName, response);
93   
94  0 try {
95  0 response.flushBuffer();
96    }
97    catch (IOException e) {
98    // don't log at error level since tomcat typically throws a
99    // org.apache.catalina.connector.ClientAbortException if the user stops loading the page
100  0 log.debug("Exception flushing response " + e.getClass().getName() + ": " + e.getMessage(), e); //$NON-NLS-1$ //$NON-NLS-2$
101    }
102   
103    }
104    catch (IOException e) {
105  0 log.error(e.getMessage(), e);
106  0 throw e;
107    }
108    catch (RenderException e) {
109  0 log.error(e.getMessage(), e);
110  0 throw new ServletException(e);
111    }
112    catch (Exception e) {
113    // @todo better handling of rendering exception
114  0 log.error(e.getMessage(), e);
115  0 if (!response.isCommitted()) {
116  0 response.setContentType("text/html");
117    }
118  0 throw new RuntimeException(e);
119    }
120    }
121    else {
122    // direct request
123  0 handleResourceRequest(aggregationState, request, response);
124    }
125   
126    // TODO don't make it a dead end
127    // currently we can't process the chain because there is no content/nop servlet
128    // chain.doFilter(request, response);
129    }
130   
 
131  0 toggle protected void render(Content content, String templateName, HttpServletResponse response) throws IOException, RenderException {
132   
133    // This lazy print writer will only acquire the writer from response if it is going to be used. This allows
134    // templates to use the output stream if they wish. See MAGNOLIA-3014.
135  0 LazyInitPrintWriter out = new LazyInitPrintWriter(response);
136   
137  0 renderingEngine.render(content, templateName, out);
138    }
139   
140   
141    /**
142    * Get the requested resource and copy it to the ServletOutputStream, bit by bit.
143    * @param request HttpServletRequest as given by the servlet container
144    * @param response HttpServletResponse as given by the servlet container
145    * @throws IOException standard servlet exception
146    */
 
147  0 toggle protected void handleResourceRequest(AggregationState aggregationState, HttpServletRequest request, HttpServletResponse response) throws IOException {
148   
149  0 final String resourceHandle = aggregationState.getHandle();
150   
151  0 log.debug("handleResourceRequest, resourceHandle=\"{}\"", resourceHandle); //$NON-NLS-1$
152   
153  0 if (StringUtils.isNotEmpty(resourceHandle)) {
154   
155  0 HierarchyManager hm = MgnlContext.getHierarchyManager(aggregationState.getRepository());
156   
157  0 InputStream is = null;
158  0 try {
159  0 is = getNodedataAstream(resourceHandle, hm, response);
160  0 if (null != is) {
161    // don't reset any existing status code, see MAGNOLIA-2005
162    // response.setStatus(HttpServletResponse.SC_OK);
163  0 sendUnCompressed(is, response);
164  0 IOUtils.closeQuietly(is);
165  0 return;
166    }
167    }
168    catch (IOException e) {
169    // don't log at error level since tomcat tipically throws a
170    // org.apache.catalina.connector.ClientAbortException if the user stops loading the page
171  0 log.debug("Exception while dispatching resource " + e.getClass().getName() + ": " + e.getMessage(), e); //$NON-NLS-1$ //$NON-NLS-2$
172  0 return;
173    }
174    catch (Exception e) {
175  0 log.error("Exception while dispatching resource " + e.getClass().getName() + ": " + e.getMessage(), e); //$NON-NLS-1$ //$NON-NLS-2$
176  0 return;
177    }
178    finally {
179  0 IOUtils.closeQuietly(is);
180    }
181    }
182  0 log.debug("Resource not found, redirecting request for [{}] to 404 URI", request.getRequestURI()); //$NON-NLS-1$
183   
184  0 if (!response.isCommitted()) {
185  0 response.sendError(HttpServletResponse.SC_NOT_FOUND);
186    }
187    else {
188  0 log.info("Unable to redirect to 404 page for {}, response is already committed", request.getRequestURI()); //$NON-NLS-1$
189    }
190   
191    }
192   
193    /**
194    * Send data as is.
195    * @param is Input stream for the resource
196    * @param response HttpServletResponse as received by the service method
197    * @throws IOException standard servlet exception
198    */
 
199  0 toggle private void sendUnCompressed(InputStream is, HttpServletResponse response) throws IOException {
200  0 ServletOutputStream os = response.getOutputStream();
201  0 byte[] buffer = new byte[8192];
202  0 int read;
203  0 while ((read = is.read(buffer)) > 0) {
204  0 os.write(buffer, 0, read);
205    }
206  0 os.flush();
207  0 IOUtils.closeQuietly(os);
208    }
209   
210    /**
211    * @param path path for nodedata in jcr repository
212    * @param hm Hierarchy manager
213    * @param res HttpServletResponse
214    * @return InputStream or <code>null</code> if nodeData is not found
215    */
 
216  0 toggle private InputStream getNodedataAstream(String path, HierarchyManager hm, HttpServletResponse res) {
217   
218  0 log.debug("getNodedataAstream for path \"{}\"", path); //$NON-NLS-1$
219   
220  0 try {
221  0 NodeData atom = hm.getNodeData(path);
222  0 if (atom != null) {
223  0 if (atom.getType() == PropertyType.BINARY) {
224   
225  0 String sizeString = atom.getAttribute("size"); //$NON-NLS-1$
226  0 if (NumberUtils.isNumber(sizeString)) {
227  0 res.setContentLength(Integer.parseInt(sizeString));
228    }
229    }
230   
231  0 Value value = atom.getValue();
232  0 if (value != null) {
233  0 return value.getStream();
234    }
235    }
236   
237  0 log.warn("Resource not found: [{}]", path); //$NON-NLS-1$
238   
239    }
240    catch (PathNotFoundException e) {
241  0 log.warn("Resource not found: [{}]", path); //$NON-NLS-1$
242    }
243    catch (RepositoryException e) {
244  0 log.error("RepositoryException while reading Resource [" + path + "]", e); //$NON-NLS-1$ //$NON-NLS-2$
245    }
246  0 return null;
247    }
248   
249   
250    }