Clover icon

Magnolia Resources Module 2.4.2

  1. Project Clover database Fri Nov 6 2015 16:15:26 CET
  2. Package info.magnolia.module.resources.renderers

File ResourcesTextTemplateRenderer.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart8.png
32% of files have more coverage

Code metrics

18
61
6
1
231
142
21
0.34
10.17
6
3.5

Classes

Class Line # Actions
ResourcesTextTemplateRenderer 84 61 0% 21 18
0.788235378.8%
 

Contributing tests

This file is covered by 8 tests. .

Source view

1    /**
2    * This file Copyright (c) 2008-2015 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.resources.renderers;
35   
36    import info.magnolia.cms.beans.config.MIMEMapping;
37    import info.magnolia.context.MgnlContext;
38    import info.magnolia.freemarker.FreemarkerHelper;
39    import info.magnolia.jcr.util.NodeUtil;
40    import info.magnolia.jcr.util.PropertyUtil;
41    import info.magnolia.jcr.wrapper.HTMLEscapingNodeWrapper;
42    import info.magnolia.module.resources.ResourcesModule;
43    import info.magnolia.module.resources.loaders.ResourceLoader;
44    import info.magnolia.module.resources.templates.ResourceTemplate;
45    import info.magnolia.objectfactory.Classes;
46    import info.magnolia.objectfactory.guice.GuiceUtils;
47    import info.magnolia.rendering.context.RenderingContext;
48    import info.magnolia.rendering.engine.RenderException;
49    import info.magnolia.rendering.engine.RenderingEngine;
50    import info.magnolia.rendering.model.RenderingModel;
51    import info.magnolia.rendering.renderer.FreemarkerRenderer;
52    import info.magnolia.rendering.template.RenderableDefinition;
53    import info.magnolia.rendering.util.AppendableWriter;
54   
55    import java.io.IOException;
56    import java.io.InputStream;
57    import java.io.Reader;
58    import java.io.StringReader;
59    import java.util.List;
60    import java.util.Map;
61   
62    import javax.inject.Inject;
63    import javax.inject.Provider;
64    import javax.jcr.Node;
65    import javax.jcr.RepositoryException;
66    import javax.servlet.http.HttpServletResponse;
67   
68    import org.apache.commons.io.IOUtils;
69    import org.apache.commons.lang3.StringUtils;
70    import org.slf4j.Logger;
71    import org.slf4j.LoggerFactory;
72   
73    import freemarker.template.TemplateException;
74   
75    /**
76    * This renderer uses the content and its subnodes as a Freemarker template
77    * source. Subnodes are appended to the content of the current node. Note that
78    * this doesn't work recursively. This can be useful for css or javascript
79    * resources, and the post-processing by Freemarker makes these dynamic,
80    * allowing one to use all of Freemarker's niceness right in their css or
81    * javascript (thus getting hold of Magnolia content and configuration, or
82    * simply using variables, etc...)
83    */
 
84    public class ResourcesTextTemplateRenderer extends FreemarkerRenderer {
85   
86    private static final Logger log = LoggerFactory.getLogger(ResourcesTextTemplateRenderer.class);
87    private final Provider<ResourcesModule> resourcesModule;
88   
89    /**
90    * @deprecated since 2.4, use {@link #ResourcesTextTemplateRenderer(FreemarkerHelper, RenderingEngine, Provider)}.
91    */
 
92  0 toggle @Deprecated
93    public ResourcesTextTemplateRenderer(FreemarkerHelper fmRenderer, RenderingEngine renderingEngine) {
94  0 this(fmRenderer, renderingEngine, GuiceUtils.providerForInstance(ResourcesModule.getInstance()));
95    }
96   
 
97  8 toggle @Inject
98    public ResourcesTextTemplateRenderer(FreemarkerHelper fmRenderer, RenderingEngine renderingEngine, Provider<ResourcesModule> resourcesModule) {
99  8 super(fmRenderer, renderingEngine);
100  8 this.resourcesModule = resourcesModule;
101    }
102   
 
103  8 toggle @Override
104    protected void onRender(Node content, RenderableDefinition definition, RenderingContext renderingCtx, Map<String, Object> ctx, String templateScript) throws RenderException {
105    // Get template from Definition
106  8 ResourceTemplate resourceTemplate = (ResourceTemplate) definition;
107    // Get HTTP Response
108  8 final HttpServletResponse response = MgnlContext.getWebContext().getResponse();
109  8 final String contentType = resourceTemplate.getContentType();
110  8 final boolean processed = resourceTemplate.isProcessed();
111   
112  8 response.setContentType(contentType);
113   
114  8 content = NodeUtil.deepUnwrap(content, HTMLEscapingNodeWrapper.class);
115   
116  8 StringBuffer text;
117  8 if (shouldBypass(content)) {
118    // fall back on the normal template loading mechanism
119    // the same path as in the workspace is used
120  4 if (processed) {
121  1 super.onRender(content, definition, renderingCtx, ctx, templateScript);
122  1 return;
123    }
124   
125  3 InputStream in = null;
126  3 List<ResourceLoader> loaders = resourcesModule.get().getResourceLoaders();
127   
128  3 for (ResourceLoader loader : loaders) {
129  4 try {
130  4 in = loader.getStream(templateScript);
131  3 if (in != null) {
132  3 break;
133    }
134    } catch (IOException e) {
135  1 log.debug("Can't load resource '{}' with ResourceLoader '{}'", templateScript, loader.getClass());
136    }
137    }
138   
139  3 if (in == null) {
140  0 throw new RenderException(String.format("Template '%s' not found.", templateScript));
141    }
142   
143  3 try {
144  3 text = new StringBuffer();
145  3 text.append(IOUtils.toString(in));
146    } catch (IOException e) {
147  0 throw new RenderException(String.format("Can't render resource '%s'.", templateScript), e);
148    } finally {
149  3 IOUtils.closeQuietly(in);
150    }
151   
152    } else {
153  4 text = new StringBuffer();
154  4 text.append(PropertyUtil.getString(content, "text"));
155    }
156   
157  7 try {
158    // Get Output
159  7 AppendableWriter out = renderingCtx.getAppendable();
160   
161  7 if (processed) {
162  1 Reader reader = new StringReader(text.toString());
163  1 try {
164  1 this.getFmHelper().render(reader, ctx, out);
165    } catch (TemplateException e) {
166  0 throw new RenderException(e);
167    }
168    } else {
169  6 out.write(text.toString());
170    }
171    } catch (IOException e) {
172  0 throw new RenderException("Can't render resource", e);
173    }
174    }
175   
176    /**
177    * The template is stored in the content node. So we don't need a
178    * templatePath.
179    */
 
180  8 toggle @Override
181    protected String resolveTemplateScript(Node content, RenderableDefinition definition, RenderingModel<?> model, final String actionResult) {
182  8 if (shouldBypass(content)) {
183  4 try {
184  4 String path;
185  4 if (StringUtils.isNotBlank(MIMEMapping.getMIMEType(StringUtils.substringAfterLast(content.getPath(), ".")))) {
186  0 return content.getPath();
187    }
188  4 String extension = PropertyUtil.getString(content, "extension");
189  4 path = content.getPath();
190  4 if (extension != null) {
191  4 path += "." + extension;
192    }
193  4 return path;
194    } catch (RepositoryException re) {
195  0 log.error("Not able to determineTemplatePath ", re);
196    }
197    }
198    // Return an empty object due to the check of AbstractRenderer.render(.
199    // that throw an Exception if the templatePath is null. In our case
200    // we don't have a templatePath because the script is coming from
201    // the content node.
202  4 return "";
203    }
204   
205    /**
206    * Creates the model for this rendering process. Will set the properties.
207    */
 
208  8 toggle @Override
209    public RenderingModel<?> newModel(Node content, RenderableDefinition definition, RenderingModel<?> parentModel) throws RenderException {
210   
211  8 String modelClass = PropertyUtil.getString(content, "modelClass");
212   
213  8 if (StringUtils.isEmpty(modelClass)) {
214  8 return super.newModel(content, definition, parentModel);
215    }
216   
217  0 Class<? extends RenderingModel<?>> clazz;
218  0 try {
219  0 clazz = Classes.getClassFactory().forName(modelClass);
220    } catch (ClassNotFoundException e) {
221  0 throw new RenderException("Could not create model.", e);
222    }
223   
224  0 return super.newModel(clazz, content, definition, parentModel);
225    }
226   
 
227  16 toggle protected boolean shouldBypass(Node content) {
228  16 return PropertyUtil.getBoolean(content, "bypass", false);
229    }
230   
231    }