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