1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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
67
68
69
70
71
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 public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException{
79 final AggregationState aggregationState = MgnlContext.getAggregationState();
80
81 String templateName = aggregationState.getTemplateName();
82 if (StringUtils.isNotEmpty(templateName)) {
83 try {
84
85
86 if (response != MgnlContext.getWebContext().getResponse()) {
87 log.warn("Context response not synced. This may lead to discrepancies in rendering.");
88 }
89
90 Content content = aggregationState.getMainContent();
91
92 render(content, templateName, response);
93
94 try {
95 response.flushBuffer();
96 }
97 catch (IOException e) {
98
99
100 log.debug("Exception flushing response " + e.getClass().getName() + ": " + e.getMessage(), e);
101 }
102
103 }
104 catch (IOException e) {
105 log.error(e.getMessage(), e);
106 throw e;
107 }
108 catch (RenderException e) {
109 log.error(e.getMessage(), e);
110 throw new ServletException(e);
111 }
112 catch (Exception e) {
113
114 log.error(e.getMessage(), e);
115 if (!response.isCommitted()) {
116 response.setContentType("text/html");
117 }
118 throw new RuntimeException(e);
119 }
120 }
121 else {
122
123 handleResourceRequest(aggregationState, request, response);
124 }
125
126
127
128
129 }
130
131 protected void render(Content content, String templateName, HttpServletResponse response) throws IOException, RenderException {
132
133
134
135 LazyInitPrintWriter out = new LazyInitPrintWriter(response);
136
137 renderingEngine.render(content, templateName, out);
138 }
139
140
141
142
143
144
145
146
147 protected void handleResourceRequest(AggregationState aggregationState, HttpServletRequest request, HttpServletResponse response) throws IOException {
148
149 final String resourceHandle = aggregationState.getHandle();
150
151 log.debug("handleResourceRequest, resourceHandle=\"{}\"", resourceHandle);
152
153 if (StringUtils.isNotEmpty(resourceHandle)) {
154
155 HierarchyManager hm = MgnlContext.getHierarchyManager(aggregationState.getRepository());
156
157 InputStream is = null;
158 try {
159 is = getNodedataAstream(resourceHandle, hm, response);
160 if (null != is) {
161
162
163 sendUnCompressed(is, response);
164 IOUtils.closeQuietly(is);
165 return;
166 }
167 }
168 catch (IOException e) {
169
170
171 log.debug("Exception while dispatching resource " + e.getClass().getName() + ": " + e.getMessage(), e);
172 return;
173 }
174 catch (Exception e) {
175 log.error("Exception while dispatching resource " + e.getClass().getName() + ": " + e.getMessage(), e);
176 return;
177 }
178 finally {
179 IOUtils.closeQuietly(is);
180 }
181 }
182 log.debug("Resource not found, redirecting request for [{}] to 404 URI", request.getRequestURI());
183
184 if (!response.isCommitted()) {
185 response.sendError(HttpServletResponse.SC_NOT_FOUND);
186 }
187 else {
188 log.info("Unable to redirect to 404 page for {}, response is already committed", request.getRequestURI());
189 }
190
191 }
192
193
194
195
196
197
198
199 private void sendUnCompressed(InputStream is, HttpServletResponse response) throws IOException {
200 ServletOutputStream os = response.getOutputStream();
201 byte[] buffer = new byte[8192];
202 int read;
203 while ((read = is.read(buffer)) > 0) {
204 os.write(buffer, 0, read);
205 }
206 os.flush();
207 IOUtils.closeQuietly(os);
208 }
209
210
211
212
213
214
215
216 private InputStream getNodedataAstream(String path, HierarchyManager hm, HttpServletResponse res) {
217
218 log.debug("getNodedataAstream for path \"{}\"", path);
219
220 try {
221 NodeData atom = hm.getNodeData(path);
222 if (atom != null) {
223 if (atom.getType() == PropertyType.BINARY) {
224
225 String sizeString = atom.getAttribute("size");
226 if (NumberUtils.isNumber(sizeString)) {
227 res.setContentLength(Integer.parseInt(sizeString));
228 }
229 }
230
231 Value value = atom.getValue();
232 if (value != null) {
233 return value.getStream();
234 }
235 }
236
237 log.warn("Resource not found: [{}]", path);
238
239 }
240 catch (PathNotFoundException e) {
241 log.warn("Resource not found: [{}]", path);
242 }
243 catch (RepositoryException e) {
244 log.error("RepositoryException while reading Resource [" + path + "]", e);
245 }
246 return null;
247 }
248
249
250 }