1 package org.apache.velocity.tools.view;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.IOException;
23 import java.io.StringWriter;
24 import javax.servlet.ServletConfig;
25 import javax.servlet.ServletException;
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28 import org.apache.velocity.Template;
29 import org.apache.velocity.context.Context;
30 import org.apache.velocity.exception.MethodInvocationException;
31
32
33
34
35
36
37
38
39 public class VelocityLayoutServlet extends VelocityViewServlet
40 {
41
42
43 private static final long serialVersionUID = -4521817395157483487L;
44
45
46
47
48
49 public static final String PROPERTY_ERROR_TEMPLATE =
50 "tools.view.servlet.error.template";
51
52
53
54
55
56 public static final String PROPERTY_LAYOUT_DIR =
57 "tools.view.servlet.layout.directory";
58
59
60
61
62
63 public static final String PROPERTY_DEFAULT_LAYOUT =
64 "tools.view.servlet.layout.default.template";
65
66
67
68
69
70 public static final String DEFAULT_ERROR_TEMPLATE = "Error.vm";
71
72
73
74
75 public static final String DEFAULT_LAYOUT_DIR = "layout/";
76
77
78
79
80 public static final String DEFAULT_DEFAULT_LAYOUT = "Default.vm";
81
82
83
84
85
86
87
88
89 public static final String KEY_SCREEN_CONTENT = "screen_content";
90
91
92
93
94
95 public static final String KEY_LAYOUT = "layout";
96
97
98
99
100
101
102 public static final String KEY_ERROR_CAUSE = "error_cause";
103
104
105
106
107
108 public static final String KEY_ERROR_STACKTRACE = "stack_trace";
109
110
111
112
113
114
115
116
117 public static final String KEY_ERROR_INVOCATION_EXCEPTION = "invocation_exception";
118
119
120 protected String errorTemplate;
121 protected String layoutDir;
122 protected String defaultLayout;
123
124
125
126
127
128
129
130 public void init(ServletConfig config) throws ServletException
131 {
132
133 super.init(config);
134
135
136 errorTemplate =
137 getVelocityProperty(PROPERTY_ERROR_TEMPLATE, DEFAULT_ERROR_TEMPLATE);
138 layoutDir =
139 getVelocityProperty(PROPERTY_LAYOUT_DIR, DEFAULT_LAYOUT_DIR);
140 defaultLayout =
141 getVelocityProperty(PROPERTY_DEFAULT_LAYOUT, DEFAULT_DEFAULT_LAYOUT);
142
143
144 if (!layoutDir.endsWith("/"))
145 {
146 layoutDir += '/';
147 }
148
149
150 getLog().info("VelocityLayoutServlet: Error screen is '"+errorTemplate+"'");
151 getLog().info("VelocityLayoutServlet: Layout directory is '"+layoutDir+"'");
152 getLog().info("VelocityLayoutServlet: Default layout template is '"+defaultLayout+"'");
153
154
155 defaultLayout = layoutDir + defaultLayout;
156 }
157
158
159
160
161
162
163
164
165
166 protected void fillContext(Context ctx, HttpServletRequest request)
167 {
168 String layout = findLayout(request);
169 if (layout != null)
170 {
171
172 ctx.put(KEY_LAYOUT, layout);
173 }
174 }
175
176
177
178
179
180 protected String findLayout(HttpServletRequest request)
181 {
182
183
184 String layout = request.getParameter(KEY_LAYOUT);
185
186 if (layout == null)
187 {
188 layout = (String)request.getAttribute(KEY_LAYOUT);
189 }
190 return layout;
191 }
192
193
194
195
196
197 protected void mergeTemplate(Template template, Context context,
198 HttpServletResponse response)
199 throws IOException
200 {
201
202
203
204
205 StringWriter sw = new StringWriter();
206 template.merge(context, sw);
207
208 context.put(KEY_SCREEN_CONTENT, sw.toString());
209
210
211
212
213
214
215 Object obj = context.get(KEY_LAYOUT);
216 String layout = (obj == null) ? null : obj.toString();
217 if (layout == null)
218 {
219
220 layout = defaultLayout;
221 }
222 else
223 {
224
225 layout = layoutDir + layout;
226 }
227
228 try
229 {
230
231 template = getTemplate(layout);
232 }
233 catch (Exception e)
234 {
235 getLog().error("Can't load layout \"" + layout + "\"", e);
236
237
238 if (!layout.equals(defaultLayout))
239 {
240
241
242 template = getTemplate(defaultLayout);
243 }
244 }
245
246
247 super.mergeTemplate(template, context, response);
248 }
249
250
251
252
253
254 protected void error(HttpServletRequest request,
255 HttpServletResponse response,
256 Throwable e)
257 {
258 try
259 {
260
261 Context ctx = createContext(request, response);
262
263 Throwable cause = e;
264
265
266 if (cause instanceof MethodInvocationException)
267 {
268
269 ctx.put(KEY_ERROR_INVOCATION_EXCEPTION, e);
270
271 cause = ((MethodInvocationException)e).getWrappedThrowable();
272 }
273
274
275 ctx.put(KEY_ERROR_CAUSE, cause);
276
277
278 StringWriter sw = new StringWriter();
279 cause.printStackTrace(new java.io.PrintWriter(sw));
280 ctx.put(KEY_ERROR_STACKTRACE, sw.toString());
281
282
283 Template et = getTemplate(errorTemplate);
284 mergeTemplate(et, ctx, response);
285
286 }
287 catch (Exception e2)
288 {
289
290 getLog().error("Error during error template rendering", e2);
291
292 super.error(request, response, e);
293 }
294 }
295
296
297 }