1 16 17 package org.apache.velocity.tools.view.servlet; 18 19 20 import java.io.IOException ; 21 import java.io.OutputStreamWriter ; 22 import java.io.PrintWriter ; 23 import java.io.StringWriter ; 24 import java.io.UnsupportedEncodingException ; 25 import java.io.Writer ; 26 27 import javax.servlet.ServletConfig ; 28 import javax.servlet.ServletContext ; 29 import javax.servlet.ServletException ; 30 import javax.servlet.http.HttpServlet ; 31 import javax.servlet.http.HttpServletRequest ; 32 import javax.servlet.http.HttpServletResponse ; 33 34 import org.apache.commons.collections.ExtendedProperties; 35 36 import org.apache.velocity.Template; 37 import org.apache.velocity.app.Velocity; 38 import org.apache.velocity.context.Context; 39 import org.apache.velocity.exception.ResourceNotFoundException; 40 import org.apache.velocity.exception.ParseErrorException; 41 import org.apache.velocity.exception.MethodInvocationException; 42 import org.apache.velocity.io.VelocityWriter; 43 import org.apache.velocity.runtime.RuntimeConstants; 44 import org.apache.velocity.runtime.RuntimeSingleton; 45 import org.apache.velocity.util.SimplePool; 46 47 import org.apache.velocity.tools.view.ToolboxManager; 48 import org.apache.velocity.tools.view.context.ToolboxContext; 49 import org.apache.velocity.tools.view.context.ChainedContext; 50 import org.apache.velocity.tools.view.servlet.ServletToolboxManager; 51 import org.apache.velocity.tools.view.servlet.WebappLoader; 52 53 54 104 105 public class VelocityViewServlet extends HttpServlet 106 { 107 108 109 public static final String CONTENT_TYPE = "default.contentType"; 110 111 112 public static final String DEFAULT_CONTENT_TYPE = "text/html"; 113 114 115 public static final String DEFAULT_OUTPUT_ENCODING = "ISO-8859-1"; 116 117 121 public static final String SERVLET_CONTEXT_KEY = 122 ServletContext .class.getName(); 123 124 125 129 protected static final String TOOLBOX_KEY = 130 "org.apache.velocity.toolbox"; 131 132 136 protected static final String INIT_PROPS_KEY = 137 "org.apache.velocity.properties"; 138 139 140 protected ToolboxManager toolboxManager = null; 141 142 143 144 private static SimplePool writerPool = new SimplePool(40); 145 146 150 private String defaultContentType; 151 152 157 private boolean warnOfOutputStreamDeprecation = true; 158 159 160 166 public void init(ServletConfig config) throws ServletException 167 { 168 super.init(config); 169 170 initVelocity(config); 172 173 initToolbox(config); 175 176 defaultContentType = 178 RuntimeSingleton.getString(CONTENT_TYPE, DEFAULT_CONTENT_TYPE); 179 180 String encoding = 181 RuntimeSingleton.getString(RuntimeSingleton.OUTPUT_ENCODING, 182 DEFAULT_OUTPUT_ENCODING); 183 184 if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding)) 187 { 188 int index = defaultContentType.lastIndexOf("charset"); 189 if (index < 0) 190 { 191 defaultContentType += "; charset=" + encoding; 194 } 195 else 196 { 197 Velocity.warn("VelocityViewServlet: Charset was already " + 199 "specified in the Content-Type property. " + 200 "Output encoding property will be ignored."); 201 } 202 } 203 204 Velocity.info("VelocityViewServlet: Default content-type is: " + 205 defaultContentType); 206 } 207 208 209 215 protected void initToolbox(ServletConfig config) throws ServletException 216 { 217 ServletContext servletContext = config.getServletContext(); 218 219 220 String file = config.getInitParameter(TOOLBOX_KEY); 221 222 223 if (file == null || file.length() == 0) 224 { 225 file = servletContext.getInitParameter(TOOLBOX_KEY); 226 } 227 228 229 if (file != null) 230 { 231 toolboxManager = 232 ServletToolboxManager.getInstance(servletContext, file); 233 } 234 else 235 { 236 Velocity.info("VelocityViewServlet: No toolbox entry in configuration."); 237 } 238 } 239 240 241 253 protected void initVelocity(ServletConfig config) throws ServletException 254 { 255 Velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext()); 256 257 Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, 259 ServletLogger.class.getName()); 260 261 Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "webapp"); 263 Velocity.setProperty("webapp.resource.loader.class", 264 WebappLoader.class.getName()); 265 266 try 268 { 269 ExtendedProperties p = loadConfiguration(config); 270 Velocity.setExtendedProperties(p); 271 } 272 catch(Exception e) 273 { 274 getServletContext().log("VelocityViewServlet: Unable to read Velocity configuration file: "+e); 275 getServletContext().log("VelocityViewServlet: Using default Velocity configuration."); 276 } 277 278 try 280 { 281 Velocity.init(); 282 } 283 catch(Exception e) 284 { 285 getServletContext().log("VelocityViewServlet: PANIC! unable to init() - "+e); 286 throw new ServletException (e); 287 } 288 } 289 290 291 338 protected ExtendedProperties loadConfiguration(ServletConfig config) 339 throws IOException 340 { 341 ServletContext servletContext = config.getServletContext(); 342 343 String propsFile = config.getInitParameter(INIT_PROPS_KEY); 345 if (propsFile == null || propsFile.length() == 0) 346 { 347 propsFile = servletContext.getInitParameter(INIT_PROPS_KEY); 348 } 349 350 ExtendedProperties p = new ExtendedProperties(); 351 if (propsFile != null) 352 { 353 p.load(servletContext.getResourceAsStream(propsFile)); 354 355 Velocity.info("VelocityViewServlet: Custom Properties File: "+propsFile); 356 } 357 else 358 { 359 Velocity.info("VelocityViewServlet: No custom properties found. " + 360 "Using default Velocity configuration."); 361 } 362 363 return p; 364 } 365 366 367 370 public void doGet(HttpServletRequest request, HttpServletResponse response) 371 throws ServletException , IOException 372 { 373 doRequest(request, response); 374 } 375 376 377 380 public void doPost(HttpServletRequest request, HttpServletResponse response) 381 throws ServletException , IOException 382 { 383 doRequest(request, response); 384 } 385 386 387 393 protected void doRequest(HttpServletRequest request, 394 HttpServletResponse response) 395 throws ServletException , IOException 396 { 397 Context context = null; 398 try 399 { 400 context = createContext(request, response); 402 403 setContentType(request, response); 405 406 Template template = handleRequest(request, response, context); 408 409 if (template == null) 411 { 412 Velocity.warn("VelocityViewServlet: couldn't find template to match request."); 413 return; 414 } 415 416 mergeTemplate(template, context, response); 418 } 419 catch (Exception e) 420 { 421 Velocity.error("VelocityViewServlet: Exception processing the template: "+e); 423 424 error(request, response, e); 427 } 428 finally 429 { 430 requestCleanup(request, response, context); 432 } 433 } 434 435 436 445 protected void requestCleanup(HttpServletRequest request, 446 HttpServletResponse response, 447 Context context) 448 { 449 } 450 451 452 461 protected Template handleRequest(HttpServletRequest request, 462 HttpServletResponse response, 463 Context ctx) 464 throws Exception 465 { 466 String path = (String )request.getAttribute("javax.servlet.include.servlet_path"); 471 if (path == null) 472 { 473 path = request.getServletPath(); 474 } 475 return getTemplate(path); 476 } 477 478 479 495 protected void setContentType(HttpServletRequest request, 496 HttpServletResponse response) 497 { 498 response.setContentType(defaultContentType); 499 } 500 501 502 511 protected Context createContext(HttpServletRequest request, 512 HttpServletResponse response) 513 { 514 ChainedContext ctx = new ChainedContext(null, request, response, getServletContext()); 515 516 517 if (toolboxManager != null) 518 { 519 ctx.setToolbox(toolboxManager.getToolboxContext(ctx)); 520 } 521 return ctx; 522 } 523 524 525 537 public Template getTemplate(String name) 538 throws ResourceNotFoundException, ParseErrorException, Exception 539 { 540 return RuntimeSingleton.getTemplate(name); 541 } 542 543 544 557 public Template getTemplate(String name, String encoding) 558 throws ResourceNotFoundException, ParseErrorException, Exception 559 { 560 return RuntimeSingleton.getTemplate(name, encoding); 561 } 562 563 564 572 protected void mergeTemplate(Template template, 573 Context context, 574 HttpServletResponse response) 575 throws ResourceNotFoundException, ParseErrorException, 576 MethodInvocationException, IOException , 577 UnsupportedEncodingException , Exception 578 { 579 VelocityWriter vw = null; 580 Writer writer = getResponseWriter(response); 581 try 582 { 583 vw = (VelocityWriter)writerPool.get(); 584 if (vw == null) 585 { 586 vw = new VelocityWriter(writer, 4 * 1024, true); 587 } 588 else 589 { 590 vw.recycle(writer); 591 } 592 template.merge(context, vw); 593 } 594 finally 595 { 596 if (vw != null) 597 { 598 try 599 { 600 vw.flush(); 604 607 vw.recycle(null); 608 writerPool.put(vw); 609 } 610 catch (Exception e) 611 { 612 Velocity.debug("VelocityViewServlet: " + 613 "Trouble releasing VelocityWriter: " + 614 e.getMessage()); 615 } 616 } 617 } 618 } 619 620 621 630 protected void error(HttpServletRequest request, 631 HttpServletResponse response, 632 Exception e) 633 throws ServletException 634 { 635 try 636 { 637 StringBuffer html = new StringBuffer (); 638 html.append("<html>\n"); 639 html.append("<head><title>Error</title></head>\n"); 640 html.append("<body>\n"); 641 html.append("<h2>VelocityViewServlet : Error processing the template</h2>\n"); 642 643 Throwable cause = e; 644 645 String why = cause.getMessage(); 646 if (why != null && why.trim().length() > 0) 647 { 648 html.append(why); 649 html.append("\n<br>\n"); 650 } 651 652 if (cause instanceof MethodInvocationException) 654 { 655 cause = ((MethodInvocationException)cause).getWrappedThrowable(); 657 } 658 659 StringWriter sw = new StringWriter (); 660 cause.printStackTrace(new PrintWriter (sw)); 661 662 html.append("<pre>\n"); 663 html.append(sw.toString()); 664 html.append("</pre>\n"); 665 html.append("</body>\n"); 666 html.append("</html>"); 667 getResponseWriter(response).write(html.toString()); 668 } 669 catch (Exception e2) 670 { 671 Velocity.error("VelocityViewServlet: Exception while printing error screen: "+e2); 675 throw new ServletException (e); 676 } 677 } 678 679 692 protected Writer getResponseWriter(HttpServletResponse response) 693 throws UnsupportedEncodingException , IOException 694 { 695 Writer writer = null; 696 try 697 { 698 writer = response.getWriter(); 699 } 700 catch (IllegalStateException e) 701 { 702 if (this.warnOfOutputStreamDeprecation) 706 { 707 this.warnOfOutputStreamDeprecation = false; 708 Velocity.warn("VelocityViewServlet: " + 709 "Use of ServletResponse's getOutputStream() " + 710 "method with VelocityViewServlet is " + 711 "deprecated -- support will be removed in " + 712 "an upcoming release"); 713 } 714 String encoding = response.getCharacterEncoding(); 716 if (encoding == null) 717 { 718 encoding = DEFAULT_OUTPUT_ENCODING; 719 } 720 writer = new OutputStreamWriter (response.getOutputStream(), 721 encoding); 722 } 723 return writer; 724 } 725 726 } 727 | Popular Tags |