1 package org.apache.fulcrum.template.jsp; 2 3 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one 6 * or more contributor license agreements. See the NOTICE file 7 * distributed with this work for additional information 8 * regarding copyright ownership. The ASF licenses this file 9 * to you under the Apache License, Version 2.0 (the 10 * "License"); you may not use this file except in compliance 11 * with the License. You may obtain a copy of the License at 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 15 * Unless required by applicable law or agreed to in writing, 16 * software distributed under the License is distributed on an 17 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 18 * KIND, either express or implied. See the License for the 19 * specific language governing permissions and limitations 20 * under the License. 21 */ 22 23 24 import java.io.OutputStream; 25 import java.io.Writer; 26 import java.util.ArrayList; 27 import java.util.List; 28 29 import org.apache.avalon.framework.configuration.Configuration; 30 import org.apache.avalon.framework.configuration.ConfigurationException; 31 import org.apache.avalon.framework.context.Context; 32 import org.apache.avalon.framework.service.ServiceException; 33 import org.apache.avalon.framework.service.ServiceManager; 34 import org.apache.fulcrum.template.BaseTemplateEngineService; 35 import org.apache.fulcrum.template.TemplateContext; 36 import org.apache.fulcrum.template.TemplateException; 37 import org.apache.fulcrum.template.TemplateService; 38 39 /** 40 * This is a Service that can process JSP templates from within a Turbine 41 * screen. 42 * 43 * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a> 44 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> 45 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> 46 */ 47 public class TurbineJspService 48 extends BaseTemplateEngineService 49 implements JspService 50 { 51 /** paths as given in the configuration file */ 52 private String[] rawPaths; 53 54 /** The base path[s] prepended to filenames given in arguments */ 55 private String[] templatePaths; 56 57 /** The relative path[s] prepended to filenames */ 58 private String[] relativeTemplatePaths; 59 60 /** The buffer size for the output stream. */ 61 private int bufferSize; 62 63 /** The class to handle looking up template names */ 64 private TemplateService templateService; 65 /** 66 * Adds some convenience objects to the request. For example an instance 67 * of JspLink which can be used to generate links to other templates. 68 * 69 * @param RunData the turbine rundata object 70 */ 71 72 /* 73 * public void addDefaultObjects(RunData data) 74 * { 75 * HttpServletRequest req = data.getRequest(); 76 * //req.setAttribute(LINK, new JspLink(data)); 77 * req.setAttribute(RUNDATA, data); 78 * } 79 */ 80 81 /** 82 * The buffer size 83 * 84 */ 85 public int getDefaultBufferSize() 86 { 87 return bufferSize; 88 } 89 90 /** 91 * Process the request 92 * 93 * @param RunData 94 * @param String the filename of the template. 95 * @throws ServiceException Any exception trown while processing will be 96 * wrapped into a ServiceException and rethrown. 97 */ 98 /* 99 * public void handleRequest(RunData data, String filename) 100 * throws ServiceException 101 * { 102 * handleRequest(data, filename, false); 103 * } 104 */ 105 106 /** 107 * Process the request 108 * 109 * @param RunData 110 * @param String the filename of the template. 111 * @param boolean whether to perform a forward or include. 112 * @throws ServiceException Any exception trown while processing will be 113 * wrapped into a ServiceException and rethrown. 114 */ 115 /* 116 * public void handleRequest(RunData data, String filename, boolean isForward) 117 * throws ServiceException 118 * { 119 * // template name with relative path 120 * String relativeTemplateName = getRelativeTemplateName(filename); 121 * 122 * if (relativeTemplateName == null) 123 * { 124 * throw new ServiceException( 125 * "Template " + filename + " not found in template paths"); 126 * } 127 * 128 * // get the RequestDispatcher for the JSP 129 * RequestDispatcher dispatcher = data.getServletContext() 130 * .getRequestDispatcher(relativeTemplateName); 131 * 132 * try 133 * { 134 * if (isForward) 135 * { 136 * // forward the request to the JSP 137 * dispatcher.forward( data.getRequest(), data.getResponse() ); 138 * } 139 * else 140 * { 141 * data.getOut().flush(); 142 * // include the JSP 143 * dispatcher.include( data.getRequest(), data.getResponse() ); 144 * } 145 * } 146 * catch(Exception e) 147 * { 148 * // as JSP service is in Alpha stage, let's try hard to send the error 149 * // message to the browser, to speed up debugging 150 * try 151 * { 152 * data.getOut().print("Error encountered processing a template: "+filename); 153 * e.printStackTrace(data.getOut()); 154 * } 155 * catch(IOException ignored) 156 * { 157 * } 158 * 159 * // pass the exception to the caller according to the general 160 * // contract for tamplating services in Turbine 161 * throw new ServiceException( 162 * "Error encountered processing a template:" + filename, e); 163 * } 164 * } 165 */ 166 167 /** 168 * Currently a no-op. This method must be implemented so that the 169 * the JSP service comformith to the TemplateEngineService 170 * interface. 171 */ 172 public String handleRequest(TemplateContext context, String template) 173 throws TemplateException 174 { 175 // TODO: Implement me! 176 return ""; 177 } 178 179 /** 180 * Currently a no-op. This method must be implemented so that the 181 * the JSP service comformith to the TemplateEngineService 182 * interface. 183 */ 184 public void handleRequest( 185 TemplateContext context, 186 String template, 187 OutputStream outputStream) 188 throws TemplateException 189 { 190 // TODO: Implement me! 191 } 192 193 /** 194 * @see org.apache.fulcrum.template.TemplateEngineService#handleRequest( 195 * Context, String, Writer) 196 */ 197 public void handleRequest( 198 TemplateContext context, 199 String template, 200 Writer writer) 201 throws TemplateException 202 { 203 // TODO: Implement me! 204 } 205 206 /** 207 * Determine whether a given template exists. This service 208 * currently only supports file base template hierarchies 209 * so we will use the utility methods provided by 210 * the template service to do the searching. 211 * 212 * @param String template 213 * @return boolean 214 */ 215 public boolean templateExists(String template) 216 { 217 return templateService.templateExists(template, templatePaths); 218 } 219 /** 220 * Searchs for a template in the default.template path[s] and 221 * returns the template name with a relative path which is 222 * required by <a href="http://java.sun.com/products/servlet/2.3/javadoc/javax/servlet/ServletContext.html#getRequestDispatcher(java.lang.String)"> 223 * javax.servlet.RequestDispatcher</a> 224 * 225 * @param String template 226 * @return String 227 */ 228 229 public String getRelativeTemplateName(String template) 230 { 231 /* 232 * A dummy String[] object used to pass a String to 233 * TurbineTemplate.templateExists 234 */ 235 String[] testTemplatePath = new String[1]; 236 237 /** 238 * Find which template path the template is in 239 */ 240 for (int i = 0; i < relativeTemplatePaths.length; i++) 241 { 242 testTemplatePath[0] = getRealPath(relativeTemplatePaths[i]); 243 if (templateService.templateExists(template, testTemplatePath)) 244 { 245 return relativeTemplatePaths[i] + template; 246 } 247 } 248 249 return null; 250 } 251 252 /* 253 * public void doBuildBeforeAction(RunData data) 254 * { 255 * addDefaultObjects(data); 256 * 257 * try 258 * { 259 * //We try to set the buffer size from defaults 260 * data.getResponse().setBufferSize(getDefaultBufferSize()); 261 * } 262 * catch (IllegalStateException ise ) 263 * { 264 * //If the response was already commited, we die silently 265 * //No logger here? 266 * } 267 * } 268 * 269 * public void doBuildAfterAction(RunData data) 270 * { 271 * // do nothing 272 * } 273 * 274 * public void doPostBuild(RunData data) 275 * { 276 * // do nothing 277 * } 278 */ 279 280 // ---------------- Avalon Lifecycle Methods --------------------- 281 282 /** 283 * Avalon component lifecycle method 284 */ 285 public void configure(Configuration conf) throws ConfigurationException 286 { 287 288 List pathList = new ArrayList(); 289 final Configuration[] paths = conf.getChildren("template-path"); 290 if (paths != null) 291 { 292 for (int i = 0; i < paths.length; i++) 293 { 294 pathList.add(paths[i].getValue()); 295 } 296 } 297 rawPaths = (String[]) pathList.toArray(new String[pathList.size()]); 298 299 bufferSize = conf.getAttributeAsInteger("buffer-size", 8192); 300 301 // Register with the template service. 302 registerConfiguration(conf, "jsp"); 303 304 // Use the turbine template service to translate the template paths. 305 templatePaths = templateService.translateTemplatePaths(rawPaths); 306 307 // Set relative paths from config. 308 // Needed for javax.servlet.RequestDispatcher 309 relativeTemplatePaths = rawPaths; 310 // Make sure that the relative paths begin with / 311 for (int i = 0; i < relativeTemplatePaths.length; i++) 312 { 313 if (!relativeTemplatePaths[i].startsWith("/")) 314 { 315 relativeTemplatePaths[i] = "/" + relativeTemplatePaths[i]; 316 } 317 } 318 } 319 320 // ---------------- Avalon Lifecycle Methods --------------------- 321 /** 322 * Avalon component lifecycle method 323 */ 324 public void service(ServiceManager manager) throws ServiceException 325 { 326 super.service(manager); 327 templateService = (TemplateService)manager.lookup(TemplateService.ROLE); 328 329 } 330 }