1 package org.apache.turbine.services.jsp;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24
25 import javax.servlet.RequestDispatcher;
26 import javax.servlet.ServletConfig;
27 import javax.servlet.http.HttpServletRequest;
28
29 import org.apache.commons.configuration.Configuration;
30
31 import org.apache.commons.lang.StringUtils;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35
36 import org.apache.turbine.Turbine;
37 import org.apache.turbine.services.InitializationException;
38 import org.apache.turbine.services.pull.ApplicationTool;
39 import org.apache.turbine.services.pull.tools.TemplateLink;
40 import org.apache.turbine.services.template.BaseTemplateEngineService;
41 import org.apache.turbine.util.RunData;
42 import org.apache.turbine.util.TurbineException;
43
44 /***
45 * This is a Service that can process JSP templates from within a Turbine
46 * screen.
47 *
48 * @author <a href="mailto:john.mcnally@clearink.com">John D. McNally</a>
49 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
50 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
51 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
52 * @version $Id: TurbineJspService.java 534527 2007-05-02 16:10:59Z tv $
53 */
54 public class TurbineJspService
55 extends BaseTemplateEngineService
56 implements JspService
57 {
58 /*** The base path[s] prepended to filenames given in arguments */
59 private String[] templatePaths;
60
61 /*** The relative path[s] prepended to filenames */
62 private String[] relativeTemplatePaths;
63
64 /*** The buffer size for the output stream. */
65 private int bufferSize;
66
67 /*** Logging */
68 private static Log log = LogFactory.getLog(TurbineJspService.class);
69
70 /***
71 * Load all configured components and initialize them. This is
72 * a zero parameter variant which queries the Turbine Servlet
73 * for its config.
74 *
75 * @throws InitializationException Something went wrong in the init
76 * stage
77 */
78 public void init()
79 throws InitializationException
80 {
81 try
82 {
83 initJsp();
84 registerConfiguration(JspService.JSP_EXTENSION);
85 setInit(true);
86 }
87 catch (Exception e)
88 {
89 throw new InitializationException(
90 "TurbineJspService failed to initialize", e);
91 }
92 }
93
94 /***
95 * Performs early initialization of this Turbine service.
96 *
97 * @param config The ServletConfiguration from Turbine
98 *
99 * @throws InitializationException Something went wrong when starting up.
100 * @deprecated use init() instead.
101 */
102 public void init(ServletConfig config)
103 throws InitializationException
104 {
105 init();
106 }
107
108 /***
109 * Adds some convenience objects to the request. For example an instance
110 * of TemplateLink which can be used to generate links to other templates.
111 *
112 * @param data the turbine rundata object
113 */
114 public void addDefaultObjects(RunData data)
115 {
116 HttpServletRequest req = data.getRequest();
117
118
119
120
121
122
123 ApplicationTool templateLink = new TemplateLink();
124 templateLink.init(data);
125
126 req.setAttribute(LINK, templateLink);
127 req.setAttribute(RUNDATA, data);
128 }
129
130 /***
131 * Returns the default buffer size of the JspService
132 *
133 * @return The default buffer size.
134 */
135 public int getDefaultBufferSize()
136 {
137 return bufferSize;
138 }
139
140 /***
141 * executes the JSP given by templateName.
142 *
143 * @param data A RunData Object
144 * @param templateName the filename of the template.
145 * @throws TurbineException Any exception thrown while processing will be
146 * wrapped into a TurbineException and rethrown.
147 */
148 public void handleRequest(RunData data, String templateName)
149 throws TurbineException
150 {
151 handleRequest(data, templateName, false);
152 }
153
154 /***
155 * executes the JSP given by templateName.
156 *
157 * @param data A RunData Object
158 * @param templateName the filename of the template.
159 * @param isForward whether to perform a forward or include.
160 * @throws TurbineException Any exception trown while processing will be
161 * wrapped into a TurbineException and rethrown.
162 */
163 public void handleRequest(RunData data, String templateName, boolean isForward)
164 throws TurbineException
165 {
166 /*** template name with relative path */
167 String relativeTemplateName = getRelativeTemplateName(templateName);
168
169 if (StringUtils.isEmpty(relativeTemplateName))
170 {
171 throw new TurbineException(
172 "Template " + templateName + " not found in template paths");
173 }
174
175
176 RequestDispatcher dispatcher = data.getServletContext()
177 .getRequestDispatcher(relativeTemplateName);
178
179 try
180 {
181 if (isForward)
182 {
183
184 dispatcher.forward(data.getRequest(), data.getResponse());
185 }
186 else
187 {
188 data.getOut().flush();
189
190 dispatcher.include(data.getRequest(), data.getResponse());
191 }
192 }
193 catch (Exception e)
194 {
195
196
197 try
198 {
199 data.getOut().print("Error encountered processing a template: "
200 + templateName);
201 e.printStackTrace(data.getOut());
202 }
203 catch (IOException ignored)
204 {
205 }
206
207
208
209 throw new TurbineException(
210 "Error encountered processing a template: " + templateName, e);
211 }
212 }
213
214 /***
215 * This method sets up the template cache.
216 */
217 private void initJsp()
218 throws Exception
219 {
220 Configuration config = getConfiguration();
221
222
223
224 relativeTemplatePaths = config.getStringArray(TEMPLATE_PATH_KEY);
225
226
227 templatePaths = new String [relativeTemplatePaths.length];
228 for (int i=0; i < relativeTemplatePaths.length; i++)
229 {
230 relativeTemplatePaths[i] = warnAbsolute(relativeTemplatePaths[i]);
231
232 templatePaths[i] = Turbine.getRealPath(relativeTemplatePaths[i]);
233 }
234
235 bufferSize = config.getInt(JspService.BUFFER_SIZE_KEY,
236 JspService.BUFFER_SIZE_DEFAULT);
237 }
238
239 /***
240 * Determine whether a given template is available on the
241 * configured template pathes.
242 *
243 * @param template The name of the requested Template
244 * @return True if the template is available.
245 */
246 public boolean templateExists(String template)
247 {
248 for (int i = 0; i < templatePaths.length; i++)
249 {
250 if (templateExists(templatePaths[i], template))
251 {
252 return true;
253 }
254 }
255 return false;
256 }
257
258 /***
259 * Determine whether a given template exists on the supplied
260 * template path. This service ATM only supports file based
261 * templates so it simply checks for file existence.
262 *
263 * @param path The absolute (file system) template path
264 * @param template The name of the requested Template
265 * @return True if the template is available.
266 */
267 private boolean templateExists(String path, String template)
268 {
269 return new File(path, template).exists();
270 }
271
272 /***
273 * Searchs for a template in the default.template path[s] and
274 * returns the template name with a relative path which is
275 * required by <a href="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletContext.html#getRequestDispatcher(java.lang.String)">
276 * javax.servlet.RequestDispatcher</a>
277 *
278 * @param template
279 * @return String
280 */
281 public String getRelativeTemplateName(String template)
282 {
283 template = warnAbsolute(template);
284
285
286
287
288 for (int i = 0; i < templatePaths.length; i++)
289 {
290 if (templateExists(templatePaths[i], template))
291 {
292 return relativeTemplatePaths[i] + "/" + template;
293 }
294 }
295 return null;
296 }
297
298 /***
299 * Warn if a template name or path starts with "/".
300 *
301 * @param template The template to test
302 * @return The template name with a leading / stripped off
303 */
304 private String warnAbsolute(String template)
305 {
306 if (template.startsWith("/"))
307 {
308 log.warn("Template " + template
309 + " has a leading /, which is wrong!");
310 return template.substring(1);
311 }
312 return template;
313 }
314 }