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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 package com.macvu.tiles.taglib;
63
64 import com.macvu.tiles.CacheComponentDefinition;
65 import com.macvu.tiles.CacheInformation;
66 import com.macvu.tiles.cache.CacheObjectWrapper;
67 import com.macvu.tiles.capture.CacheHttpServletResponse;
68 import com.macvu.tiles.capture.CacheablesCaptureWrapper;
69 import org.apache.commons.logging.Log;
70 import org.apache.commons.logging.LogFactory;
71 import org.apache.struts.taglib.tiles.ComponentConstants;
72 import org.apache.struts.taglib.tiles.InsertTag;
73 import org.apache.struts.tiles.ComponentContext;
74 import org.apache.struts.tiles.ComponentDefinition;
75 import org.apache.struts.tiles.Controller;
76 import org.apache.struts.tiles.TilesUtil;
77 import org.apache.struts.util.ResponseUtils;
78
79 import javax.servlet.ServletContext;
80 import javax.servlet.ServletException;
81 import javax.servlet.http.HttpServletRequest;
82 import javax.servlet.http.HttpServletResponse;
83 import javax.servlet.jsp.JspException;
84 import javax.servlet.jsp.PageContext;
85 import java.io.IOException;
86 import java.io.PrintWriter;
87
88 public class CacheInsertTag extends InsertTag {
89
90 protected static Log log = LogFactory.getLog(CacheInsertTag.class);
91
92 /***
93 * Get current component context.
94 */
95 private ComponentContext getCurrentContext() {
96 if (cachedCurrentContext == null) {
97 cachedCurrentContext =
98 (ComponentContext) pageContext.getAttribute(ComponentConstants.COMPONENT_CONTEXT,
99 PageContext.REQUEST_SCOPE);
100 }
101 return cachedCurrentContext;
102 }
103
104 /***
105 * End of Process tag attribute "definition".
106 * Overload definition with tag attributes "template" and "role".
107 * Then, create appropriate tag handler.
108 *
109 * @param definition Definition to process.
110 * @return Appropriate TagHandler.
111 * @throws JspException InstantiationException Can't create requested controller
112 */
113 protected TagHandler processDefinition(ComponentDefinition definition)
114 throws JspException {
115
116 String role = this.role;
117 String page = this.page;
118 Controller controller = null;
119
120 if (log.isDebugEnabled()) {
121 log.debug("Process Definition: " + definition.getName());
122 }
123 try {
124 controller = definition.getOrCreateController();
125
126
127 if (role == null) {
128 role = definition.getRole();
129 }
130 if (page == null) {
131 page = definition.getTemplate();
132 }
133 if (controllerName != null) {
134 controller =
135 ComponentDefinition.createController(controllerName,
136 controllerType);
137 }
138
139 if (definition instanceof CacheComponentDefinition) {
140
141 return new CacheInsertHandler((CacheComponentDefinition) definition,
142 page,
143 role,
144 controller);
145 } else {
146
147 return new InsertHandler(definition.getAttributes(),
148 page,
149 role,
150 controller);
151 }
152 } catch (InstantiationException ex) {
153 throw new JspException(ex.getMessage());
154 }
155 }
156
157 /***
158 * Do an include of specified page.
159 * This method is used internally to do all includes from this class. It delegates
160 * the include call to the TilesUtil.doInclude().
161 *
162 * @param page The page that will be included
163 * @throws ServletException - Thrown by call to pageContext.include()
164 * @throws IOException - Thrown by call to pageContext.include()
165 */
166 protected void doInclude(String page, HttpServletRequest request, HttpServletResponse response, ServletContext servletContext) throws ServletException, IOException {
167
168
169
170
171
172
173 TilesUtil.doInclude(page, request, response, servletContext);
174 }
175
176 protected class CacheInsertHandler implements TagHandler {
177 protected CacheComponentDefinition definition;
178 protected String page;
179 protected ComponentContext currentContext;
180 protected ComponentContext subCompContext;
181 protected String role;
182 protected Controller controller;
183
184 /***
185 * Constructor.
186 * Create insert handler using Component definition.
187 */
188 public CacheInsertHandler(CacheComponentDefinition definition,
189 String page,
190 String role,
191 Controller controller) {
192 this.definition = definition;
193 this.page = page;
194 this.role = role;
195 this.controller = controller;
196 subCompContext = new ComponentContext(definition.getAttributes());
197 }
198
199 /***
200 * Create a new empty context.
201 */
202 public int doStartTag() throws JspException {
203
204 if (role != null
205 && !((HttpServletRequest) pageContext.getRequest()).isUserInRole(role)) {
206 return SKIP_BODY;
207 }
208
209
210 this.currentContext = getCurrentContext();
211 return EVAL_BODY_INCLUDE;
212 }
213
214 /***
215 * Add attribute to sub context.
216 * Do nothing.
217 */
218 public void putAttribute(String name, Object value) {
219 subCompContext.putAttribute(name, value);
220 }
221
222 /***
223 * Include requested page.
224 */
225 public int doEndTag() throws JspException {
226
227 if (role != null
228 && !((HttpServletRequest) pageContext.getRequest()).isUserInRole(role)) {
229 return EVAL_PAGE;
230 }
231
232 try {
233 if (log.isDebugEnabled()) {
234 log.debug("insert page='" + page + "'.");
235 }
236
237 HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
238 HttpServletResponse response = (HttpServletResponse) pageContext.getResponse();
239 ServletContext servletContext = pageContext.getServletContext();
240
241
242 CacheablesCaptureWrapper cacheables = new CacheablesCaptureWrapper(servletContext);
243 if (cacheables.isEnableCapture()) {
244 cacheables.captureCacheablesForTile((CacheComponentDefinition) definition, pageContext);
245 }
246
247 CacheObjectWrapper cacheController = new CacheObjectWrapper();
248 CacheInformation info = ((CacheComponentDefinition) definition).getCacheInformation();
249 cacheController.initiateCacheInformation(pageContext.getServletContext(), info);
250 if (cacheController.isCacheEnabled()) {
251 String key = cacheController.getCacheKey((HttpServletRequest) pageContext.getRequest());
252 if (log.isDebugEnabled()) {
253 log.debug("Cache is enable. Looking for key: " + key);
254 }
255 String cache = (String) cacheController.getCache(key);
256 if (cache == null) {
257 CacheHttpServletResponse cacheResponse = new CacheHttpServletResponse(response);
258 performTileSection(request, cacheResponse, servletContext);
259 cacheController.putCache(key, cacheResponse.getCache());
260 } else {
261 ResponseUtils.write(pageContext, cache);
262 }
263 } else {
264 performTileSection(request, response, servletContext);
265 }
266 } catch (IOException ex) {
267 processException(ex,
268 "Can't insert page '" + page + "' : " + ex.getMessage());
269
270 } catch (IllegalArgumentException ex) {
271
272 if (!(page == null && isErrorIgnored)) {
273
274 processException(ex,
275 "Tag 'insert' can't insert page '"
276 + page
277 + "'. Check if it exists.\n"
278 + ex.getMessage());
279 }
280
281 } catch (ServletException ex) {
282 Throwable realEx = ex;
283 if (ex.getRootCause() != null) {
284 realEx = ex.getRootCause();
285 }
286 processException(realEx,
287 "[ServletException in:"
288 + page
289 + "] "
290 + realEx.getMessage()
291 + "'");
292
293 } catch (Exception ex) {
294 processException(ex,
295 "[Exception in:" + page + "] " + ex.getMessage());
296
297 } finally {
298
299
300 if (currentContext != null) {
301 pageContext.setAttribute(ComponentConstants.COMPONENT_CONTEXT,
302 currentContext,
303 PageContext.REQUEST_SCOPE);
304 }
305 }
306 return EVAL_PAGE;
307 }
308
309 private void performTileSection(HttpServletRequest request, HttpServletResponse response, ServletContext context) throws ServletException, IOException {
310 if (log.isDebugEnabled()) {
311 log.debug("performTileSection: Enter");
312 }
313
314 pageContext.setAttribute(ComponentConstants.COMPONENT_CONTEXT,
315 subCompContext,
316 PageContext.REQUEST_SCOPE);
317
318
319 if (controller != null) {
320 controller.perform(subCompContext,
321 request,
322 response,
323 context);
324 }
325
326
327 if (flush) {
328 pageContext.getOut().flush();
329 }
330
331 if (log.isDebugEnabled()) {
332 log.debug("Do Include Page: " + page);
333 }
334 doInclude(page,
335 request,
336 response,
337 context);
338 }
339
340 /***
341 * Process an exception.
342 * Depending of debug attribute, print full exception trace or only
343 * its message in output page.
344 *
345 * @param ex Exception
346 * @param msg An additional message to show in console and to propagate if we can't output exception.
347 */
348 protected void processException(Throwable ex, String msg)
349 throws JspException {
350 try {
351 if (msg == null) {
352 msg = ex.getMessage();
353 }
354 if (log.isDebugEnabled()) {
355 log.debug(msg, ex);
356 pageContext.getOut().println(msg);
357 ex.printStackTrace(new PrintWriter(pageContext.getOut(), true));
358 } else {
359 pageContext.getOut().println(msg);
360 }
361 } catch (IOException ioex) {
362 pageContext.setAttribute(ComponentConstants.EXCEPTION_KEY,
363 ex,
364 PageContext.REQUEST_SCOPE);
365 throw new JspException(msg);
366 }
367 }
368 }
369
370 }