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