You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@velocity.apache.org by nb...@apache.org on 2007/03/22 19:14:08 UTC
svn commit: r521391 [1/2] - in
/velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view:
./ context/ servlet/
Author: nbubna
Date: Thu Mar 22 11:14:06 2007
New Revision: 521391
URL: http://svn.apache.org/viewvc?view=rev&rev=521391
Log:
- extend the new tool managment infrastructure into VelocityView (JEE support)
- start moving JEE stuff into base view package for consistency & simplicity
- change ServletLogger to be a full LogChute implementation
- rename WebappLoader to WebappResourceLoader to be consistent with all other resource loaders
Added:
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletLogChute.java
- copied, changed from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletLogger.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletUtils.java
- copied, changed from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletUtils.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityLayoutServlet.java
- copied, changed from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityLayoutServlet.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityView.java (with props)
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityViewServlet.java
- copied, changed from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityViewServlet.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ViewContext.java
- copied, changed from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/context/ViewContext.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ViewToolContext.java (with props)
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/WebappResourceLoader.java
- copied, changed from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/WebappLoader.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/velocity.properties
- copied unchanged from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/velocity.properties
Removed:
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/context/ViewContext.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletLogger.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletUtils.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityLayoutServlet.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityViewServlet.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/WebappLoader.java
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/velocity.properties
Modified:
velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletToolInfo.java
Copied: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletLogChute.java (from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletLogger.java)
URL: http://svn.apache.org/viewvc/velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletLogChute.java?view=diff&rev=521391&p1=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletLogger.java&r1=521375&p2=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletLogChute.java&r2=521391
==============================================================================
--- velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletLogger.java (original)
+++ velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletLogChute.java Thu Mar 22 11:14:06 2007
@@ -1,4 +1,4 @@
-package org.apache.velocity.tools.view.servlet;
+package org.apache.velocity.tools.view;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,22 +19,31 @@
* under the License.
*/
+import java.io.StringWriter;
+import java.io.PrintWriter;
import javax.servlet.ServletContext;
-
-import org.apache.velocity.runtime.log.LogSystem;
-import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.log.LogChute;
import org.apache.velocity.runtime.RuntimeServices;
-
/**
- * Simple wrapper for the servlet log. This has Velocity log
- * messages to ServletContext.log(String).
+ * Simple wrapper for the servlet log. This passes Velocity log
+ * messages to ServletContext.log(String). You may configure the
+ * level of output in your velocity.properties by adding the
+ * "runtime.log.logsystem.servlet.level" property with one of the
+ * following values: error, warn, info, debug, or trace. The default
+ * is trace.
*
* @author <a href="mailto:geirm@apache.org">Geir Magnusson Jr.</a>
+ * @author Nathan Bubna
* @version $Revision$ $Date$
*/
-public class ServletLogger implements LogSystem
+public class ServletLogChute implements LogChute
{
+ public static final String RUNTIME_LOG_LEVEL_KEY =
+ "runtime.log.logsystem.servlet.level";
+
+ private int enabled = TRACE_ID;
+
protected ServletContext servletContext = null;
public static final String PREFIX = " Velocity ";
@@ -46,7 +55,7 @@
* been placed in the runtime's application attributes
* under its full class name (i.e. "javax.servlet.ServletContext").
*/
- public ServletLogger()
+ public ServletLogChute()
{
}
@@ -56,8 +65,7 @@
* @throws IllegalStateException if the ServletContext is not available
* in the application attributes under the appropriate key.
*/
- public void init( RuntimeServices rs )
- throws Exception
+ public void init(RuntimeServices rs) throws Exception
{
Object obj = rs.getApplicationAttribute(ServletContext.class.getName());
if (obj == null)
@@ -65,31 +73,114 @@
throw new IllegalStateException("Could not retrieve ServletContext from application attributes!");
}
servletContext = (ServletContext)obj;
+
+ // look for a level config property
+ String level = (String)rs.getProperty(RUNTIME_LOG_LEVEL_KEY);
+ if (level != null)
+ {
+ // and set it accordingly
+ setEnabledLevel(toLevel(level));
+ }
+ }
+
+ protected int toLevel(String level) {
+ if (level.equalsIgnoreCase("debug"))
+ {
+ return DEBUG_ID;
+ }
+ else if (level.equalsIgnoreCase("info"))
+ {
+ return INFO_ID;
+ }
+ else if (level.equalsIgnoreCase("warn"))
+ {
+ return WARN_ID;
+ }
+ else if (level.equalsIgnoreCase("error"))
+ {
+ return ERROR_ID;
+ }
+ else
+ {
+ return TRACE_ID;
+ }
+ }
+
+ /**
+ * Set the minimum level at which messages will be printed.
+ */
+ public void setEnabledLevel(int level)
+ {
+ this.enabled = level;
+ }
+
+ /**
+ * Returns the current minimum level at which messages will be printed.
+ */
+ public int getEnabledLevel()
+ {
+ return this.enabled;
+ }
+
+ /**
+ * This will return true if the specified level
+ * is equal to or higher than the level this
+ * LogChute is enabled for.
+ */
+ public boolean isLevelEnabled(int level)
+ {
+ return (level >= this.enabled);
}
/**
* Send a log message from Velocity.
*/
- public void logVelocityMessage(int level, String message)
+ public void log(int level, String message)
{
+ if (!isLevelEnabled(level))
+ {
+ return;
+ }
+
switch (level)
{
- case LogSystem.WARN_ID:
- servletContext.log( PREFIX + RuntimeConstants.WARN_PREFIX + message );
+ case WARN_ID:
+ servletContext.log(PREFIX + WARN_PREFIX + message);
+ break;
+ case INFO_ID:
+ servletContext.log(PREFIX + INFO_PREFIX + message);
break;
- case LogSystem.INFO_ID:
- servletContext.log( PREFIX + RuntimeConstants.INFO_PREFIX + message);
+ case DEBUG_ID:
+ servletContext.log(PREFIX + DEBUG_PREFIX + message);
break;
- case LogSystem.DEBUG_ID:
- servletContext.log( PREFIX + RuntimeConstants.DEBUG_PREFIX + message);
+ case TRACE_ID:
+ servletContext.log(PREFIX + TRACE_PREFIX + message);
break;
- case LogSystem.ERROR_ID:
- servletContext.log( PREFIX + RuntimeConstants.ERROR_PREFIX + message);
+ case ERROR_ID:
+ servletContext.log(PREFIX + ERROR_PREFIX + message);
break;
default:
- servletContext.log( PREFIX + " : " + message);
+ servletContext.log(PREFIX + " : " + message);
break;
}
+ }
+
+ public void log(int level, String message, Throwable t)
+ {
+ if (!isLevelEnabled(level))
+ {
+ return;
+ }
+
+ message += " - "+t.toString();
+ if (level >= ERROR_ID)
+ {
+ StringWriter sw = new StringWriter();
+ t.printStackTrace(new PrintWriter(sw));
+ message += "\n" + sw.toString();
+ }
+
+ log(level, message);
}
}
Copied: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletUtils.java (from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletUtils.java)
URL: http://svn.apache.org/viewvc/velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletUtils.java?view=diff&rev=521391&p1=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletUtils.java&r1=521375&p2=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletUtils.java&r2=521391
==============================================================================
--- velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/ServletUtils.java (original)
+++ velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ServletUtils.java Thu Mar 22 11:14:06 2007
@@ -1,4 +1,4 @@
-package org.apache.velocity.tools.view.servlet;
+package org.apache.velocity.tools.view;
/*
* Licensed to the Apache Software Foundation (ASF) under one
Copied: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityLayoutServlet.java (from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityLayoutServlet.java)
URL: http://svn.apache.org/viewvc/velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityLayoutServlet.java?view=diff&rev=521391&p1=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityLayoutServlet.java&r1=521375&p2=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityLayoutServlet.java&r2=521391
==============================================================================
--- velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityLayoutServlet.java (original)
+++ velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityLayoutServlet.java Thu Mar 22 11:14:06 2007
@@ -1,4 +1,4 @@
-package org.apache.velocity.tools.view.servlet;
+package org.apache.velocity.tools.view;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,20 +21,14 @@
import java.io.IOException;
import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
import org.apache.velocity.Template;
-import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-
/**
* Extension of the VelocityViewServlet to perform "two-pass"
@@ -47,7 +41,6 @@
* @author Nathan Bubna
* @version $Id$
*/
-
public class VelocityLayoutServlet extends VelocityViewServlet
{
@@ -138,9 +131,6 @@
protected String layoutDir;
protected String defaultLayout;
- // keep a local reference for convenience
- private VelocityEngine velocity;
-
/**
* Initializes Velocity, the view servlet and checks for changes to
* the initial layout configuration.
@@ -152,9 +142,6 @@
// first do VVS' init()
super.init(config);
- // grab the initialized engine
- velocity = super.getVelocityEngine();
-
// check for default template path overrides
errorTemplate =
getVelocityProperty(PROPERTY_ERROR_TEMPLATE, DEFAULT_ERROR_TEMPLATE);
@@ -170,9 +157,9 @@
}
// log the current settings
- velocity.info("VelocityLayoutServlet: Error screen is '"+errorTemplate+"'");
- velocity.info("VelocityLayoutServlet: Layout directory is '"+layoutDir+"'");
- velocity.info("VelocityLayoutServlet: Default layout template is '"+defaultLayout+"'");
+ getLog().info("VelocityLayoutServlet: Error screen is '"+errorTemplate+"'");
+ getLog().info("VelocityLayoutServlet: Layout directory is '"+layoutDir+"'");
+ getLog().info("VelocityLayoutServlet: Default layout template is '"+defaultLayout+"'");
// for efficiency's sake, make defaultLayout a full path now
defaultLayout = layoutDir + defaultLayout;
@@ -187,12 +174,8 @@
* @param response client response
* @return the Context to fill
*/
- protected Context createContext(HttpServletRequest request,
- HttpServletResponse response)
+ protected void fillContext(Context ctx, HttpServletRequest request)
{
-
- Context ctx = super.createContext(request, response);
-
// check if an alternate layout has been specified
// by way of the request parameters
String layout = request.getParameter(KEY_LAYOUT);
@@ -201,7 +184,6 @@
// let the template know what its new layout is
ctx.put(KEY_LAYOUT, layout);
}
- return ctx;
}
@@ -209,12 +191,9 @@
* Overrides VelocityViewServlet.mergeTemplate to do a two-pass
* render for handling layouts
*/
- protected void mergeTemplate(Template template,
- Context context,
+ protected void mergeTemplate(Template template, Context context,
HttpServletResponse response)
- throws ResourceNotFoundException, ParseErrorException,
- MethodInvocationException, IOException,
- UnsupportedEncodingException, Exception
+ throws IOException
{
//
// this section is based on Tim Colson's "two pass render"
@@ -250,8 +229,7 @@
}
catch (Exception e)
{
- velocity.error("VelocityLayoutServlet: Can't load layout \"" +
- layout + "\": " + e);
+ getLog().error("Can't load layout \"" + layout + "\"", e);
// if it was an alternate layout we couldn't get...
if (!layout.equals(defaultLayout))
@@ -272,8 +250,7 @@
*/
protected void error(HttpServletRequest request,
HttpServletResponse response,
- Exception e)
- throws ServletException
+ Throwable e)
{
try
{
@@ -307,8 +284,7 @@
catch (Exception e2)
{
// d'oh! log this
- velocity.error("VelocityLayoutServlet: " +
- " Error during error template rendering - " + e2);
+ getLog().error("Error during error template rendering", e2);
// then punt the original to a higher authority
super.error(request, response, e);
}
Added: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityView.java
URL: http://svn.apache.org/viewvc/velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityView.java?view=auto&rev=521391
==============================================================================
--- velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityView.java (added)
+++ velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityView.java Thu Mar 22 11:14:06 2007
@@ -0,0 +1,877 @@
+package org.apache.velocity.tools.view;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+import java.util.Properties;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.apache.commons.collections.ExtendedProperties;
+import org.apache.velocity.Template;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.io.VelocityWriter;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.log.Log;
+import org.apache.velocity.tools.generic.log.LogChuteCommonsLog;
+import org.apache.velocity.tools.Toolbox;
+import org.apache.velocity.tools.ToolboxFactory;
+import org.apache.velocity.tools.config.FactoryConfiguration;
+import org.apache.velocity.tools.config.FileFactoryConfiguration;
+import org.apache.velocity.tools.config.PropertiesFactoryConfiguration;
+import org.apache.velocity.tools.config.XmlFactoryConfiguration;
+import org.apache.velocity.tools.view.ViewToolContext;
+import org.apache.velocity.util.SimplePool;
+
+/**
+ * <p>The class provides the following features:</p>
+ * <ul>
+ * <li>renders Velocity templates</li>
+ * <li>provides support for an auto-loaded, configurable toolbox</li>
+ * <li>provides transparent access to the servlet request attributes,
+ * servlet session attributes and servlet context attributes by
+ * auto-searching them</li>
+ * <li>logs to the logging facility of the servlet API</li>
+ * </ul>
+ *
+ * <p>VelocityView supports the following configuration parameters
+ * in web.xml:</p>
+ * <dl>
+ * <dt>org.apache.velocity.toolbox</dt>
+ * <dd>Path and name of the toolbox configuration file. The path must be
+ * relative to the web application root directory. If this parameter is
+ * not found, the servlet will check for a toolbox file at
+ * '/WEB-INF/tools.xml'.</dd>
+ * <dt>org.apache.velocity.properties</dt>
+ * <dd>Path and name of the Velocity configuration file. The path must be
+ * relative to the web application root directory. If this parameter
+ * is not present, Velocity will check for a properties file at
+ * '/WEB-INF/velocity.properties'. If no file is found there, then
+ * Velocity is initialized with the settings in the classpath at
+ * 'org.apache.velocity.tools.view.velocity.properties'.</dd>
+ * </dl>
+ *
+ * <p>There are methods you may wish to override to access, alter or control
+ * any part of the request processing chain. Please see the javadocs for
+ * more information on :
+ * <ul>
+ * <li> {@link #setContentType} : <br>for changing the content type on a request
+ * by request basis
+ * <li> {@link #requestCleanup} : <br>post rendering resource or other cleanup
+ * <li> {@link #error} : <br>error handling
+ * </ul>
+ * </p>
+ *
+ * @author Dave Bryson
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ * @author <a href="mailto:sidler@teamup.com">Gabe Sidler</a>
+ * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:kjohnson@transparent.com">Kent Johnson</a>
+ * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
+ * @author Nathan Bubna
+ *
+ * @version $Id: VelocityView.java 511959 2007-02-26 19:24:39Z nbubna $
+ */
+
+public class VelocityView
+{
+ /** serial version id */
+ private static final long serialVersionUID = -3329444102562079189L;
+
+ /** The HTTP content type context key. */
+ public static final String CONTENT_TYPE_KEY = "default.contentType";
+
+ /**
+ * Key used to access the ServletContext in
+ * the Velocity application attributes.
+ */
+ public static final String SERVLET_CONTEXT_KEY =
+ ServletContext.class.getName();
+
+ /** The default content type for the response */
+ public static final String DEFAULT_CONTENT_TYPE = "text/html";
+
+ /** Default encoding for the output stream */
+ public static final String DEFAULT_OUTPUT_ENCODING = "ISO-8859-1";
+
+ /**
+ * Key used to access the toolbox configuration file path from the
+ * Servlet or webapp init parameters ("org.apache.velocity.tools").
+ */
+ public static final String TOOLS_KEY =
+ "org.apache.velocity.tools";
+
+ /**
+ * Default toolbox configuration file path. If no alternate value for
+ * this is specified, the servlet will look here.
+ */
+ public static final String USER_TOOLS_PATH =
+ "/WEB-INF/tools.xml";
+
+ /**
+ * Default Runtime properties.
+ */
+ public static final String DEFAULT_PROPERTIES_PATH =
+ "/org/apache/velocity/tools/view/velocity.properties";
+
+ /**
+ * This is the string that is looked for when getInitParameter is
+ * called ("org.apache.velocity.properties").
+ */
+ public static final String PROPERTIES_KEY =
+ "org.apache.velocity.properties";
+
+ /**
+ * Default velocity properties file path. If no alternate value for
+ * this is specified, the servlet will look here.
+ */
+ public static final String USER_PROPERTIES_PATH =
+ "/WEB-INF/velocity.properties";
+
+
+ private static SimplePool writerPool = new SimplePool(40);
+ private ToolboxFactory toolboxFactory = null;
+ private VelocityEngine velocity = null;
+ private ServletContext servletContext;
+ private String defaultContentType = DEFAULT_CONTENT_TYPE;
+
+ public VelocityView(ServletConfig config)
+ {
+ this.servletContext = config.getServletContext();
+ init(config);
+ }
+
+ public VelocityView(ServletContext context)
+ {
+ if (context == null)
+ {
+ throw new NullPointerException("ServletContext cannot be null");
+ }
+ this.servletContext = context;
+ }
+
+
+ /**
+ * Returns the underlying VelocityEngine being used.
+ */
+ protected VelocityEngine getVelocityEngine()
+ {
+ return velocity;
+ }
+
+ protected Log getLog()
+ {
+ return getVelocityEngine().getLog();
+ }
+
+ public String getDefaultContentType()
+ {
+ return this.defaultContentType;
+ }
+
+ /**
+ * Simplifies process of getting a property from VelocityEngine,
+ * because the VelocityEngine interface sucks compared to the singleton's.
+ * Use of this method assumes that {@link #initVelocity(ServletConfig,VelocityEngine)}
+ * has already been called.
+ */
+ protected String getProperty(String key, String alternate)
+ {
+ String prop = (String)velocity.getProperty(key);
+ if (prop == null || prop.length() == 0)
+ {
+ return alternate;
+ }
+ return prop;
+ }
+
+
+ /**
+ * <p>Initializes ToolboxFactory, VelocityEngine, and sets default
+ * encoding for processing requests.</p>
+ *
+ * <p>NOTE: If no charset is specified in the default.contentType
+ * property (in your velocity.properties) and you have specified
+ * an output.encoding property, then that will be used as the
+ * charset for the default content-type of pages served by this
+ * servlet.</p>
+ *
+ * @param config servlet configuation
+ */
+ protected void init(ServletConfig config)
+ {
+ // initialize a new VelocityEngine
+ init(config, new VelocityEngine());
+
+ // initialize a new ToolboxFactory
+ init(config, new ToolboxFactory());
+
+ // set encoding & content-type
+ setEncoding(config);
+ }
+
+ /**
+ * Initializes the Velocity runtime, first calling
+ * loadConfiguration(ServletConfig) to get a
+ * org.apache.commons.collections.ExtendedProperties
+ * of configuration information
+ * and then calling velocityEngine.init(). Override this
+ * to do anything to the environment before the
+ * initialization of the singleton takes place, or to
+ * initialize the singleton in other ways.
+ *
+ * @param config servlet configuration parameters
+ */
+ protected void init(ServletConfig config, final VelocityEngine velocity)
+ {
+ if (velocity == null)
+ {
+ throw new NullPointerException("VelocityEngine cannot be null");
+ }
+ this.velocity = velocity;
+
+ // register this engine to be the default handler of log messages
+ // if the user points commons-logging to the LogSystemCommonsLog
+ LogChuteCommonsLog.setVelocityLog(getLog());
+
+ // put the servlet context into Velocity's application attributes,
+ // where the WebappResourceLoader can find them
+ velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, this.servletContext);
+
+ // configure the engine itself
+ configure(config, velocity);
+
+ // now all is ready - init Velocity
+ try
+ {
+ velocity.init();
+ }
+ catch(Exception e)
+ {
+ String msg = "Could not initialize VelocityEngine";
+ getLog().error(msg, e);
+ throw new RuntimeException(msg, e);
+ }
+ }
+
+
+ /**
+ * Initializes the ToolboxFactory.
+ *
+ * @param config servlet configuation
+ * @param factory the ToolboxFactory to be initialized for this VelocityView
+ */
+ protected void init(ServletConfig config, final ToolboxFactory factory)
+ {
+ if (factory == null)
+ {
+ throw new NullPointerException("ToolboxFactory cannot be null");
+ }
+ this.toolboxFactory = factory;
+
+ configure(config, toolboxFactory);
+
+ // add any application toolbox to the application attributes
+ Toolbox appTools =
+ toolboxFactory.getToolbox(ToolboxFactory.APPLICATION_SCOPE);
+ if (appTools != null)
+ {
+ this.servletContext.setAttribute(Toolbox.class.getName(), appTools);
+ }
+ }
+
+
+ protected void configure(ServletConfig config, VelocityEngine velocity)
+ {
+ // first get the default properties, and bail if we don't find them
+ velocity.setExtendedProperties(getProperties(DEFAULT_PROPERTIES_PATH, true));
+
+ String configMessage = "Configuring Velocity with properties at: ";
+
+ // check for application-wide user props in the context init params
+ String appPropsPath = servletContext.getInitParameter(PROPERTIES_KEY);
+ if (appPropsPath != null)
+ {
+ // since the user said props are there, complain if they aren't!
+ ExtendedProperties appProps = getProperties(appPropsPath, true);
+ getLog().debug(configMessage + appPropsPath);
+
+ // set the props, letting them override framework defaults
+ velocity.setExtendedProperties(appProps);
+ }
+
+ // check for servlet-wide user props in the config init params at the
+ // conventional location, and be silent if they're missing
+ ExtendedProperties servletProps = getProperties(USER_PROPERTIES_PATH);
+ if (servletProps != null)
+ {
+ getLog().debug(configMessage + USER_PROPERTIES_PATH);
+
+ // set them, letting servlet props override app props and defaults
+ velocity.setExtendedProperties(servletProps);
+ }
+
+ // check for a custom location for servlet-wide user props
+ String servletPropsPath = config.getInitParameter(PROPERTIES_KEY);
+ if (servletPropsPath != null)
+ {
+ // since the user said props are there, complain if they aren't!
+ servletProps = getProperties(servletPropsPath, true);
+ getLog().debug(configMessage + servletPropsPath);
+
+ // set them, again, let these specified with most effort override all
+ velocity.setExtendedProperties(servletProps);
+ }
+ }
+
+
+ protected void configure(ServletConfig config, ToolboxFactory factory)
+ {
+ FactoryConfiguration factoryConfig = new FactoryConfiguration();
+
+ String configMessage = "Configuring ToolboxFactory with configuration at: ";
+
+ // check for application-wide user config in the context init params
+ String appToolsPath = servletContext.getInitParameter(TOOLS_KEY);
+ if (appToolsPath != null)
+ {
+ // since the user said a config is there, complain if it isn't!
+ FactoryConfiguration appConfig = getConfiguration(appToolsPath, true);
+ getLog().debug(configMessage + appToolsPath);
+
+ factoryConfig.addConfiguration(appConfig);
+ }
+
+ // check for servlet-wide user props in the config init params at the
+ // conventional location, and be silent if they're missing
+ FactoryConfiguration servletConfig = getConfiguration(USER_TOOLS_PATH);
+ if (servletConfig != null)
+ {
+ getLog().debug(configMessage + USER_TOOLS_PATH);
+
+ factoryConfig.addConfiguration(servletConfig);
+ }
+
+ // check for a custom location for servlet-wide user props
+ String servletToolsPath = config.getInitParameter(TOOLS_KEY);
+ if (servletToolsPath != null)
+ {
+ // since the user said props are there, complain if they aren't!
+ servletConfig = getConfiguration(servletToolsPath, true);
+ getLog().debug(configMessage + servletToolsPath);
+
+ factoryConfig.addConfiguration(servletConfig);
+ }
+
+ // apply this configuration to the specified factory
+ factory.configure(factoryConfig);
+ }
+
+
+ protected InputStream getInputStream(String path, boolean required)
+ {
+ // first, search the classpath
+ InputStream inputStream = getClass().getResourceAsStream(path);
+ if (inputStream == null)
+ {
+ // then, try the servlet context
+ inputStream = this.servletContext.getResourceAsStream(path);
+
+ if (inputStream == null)
+ {
+ // then, try the file system directly
+ File file = new File(path);
+ if (file.exists())
+ {
+ try
+ {
+ inputStream = new FileInputStream(file);
+ }
+ catch (FileNotFoundException fnfe)
+ {
+ // we should not be able to get here
+ // since we already checked whether the file exists
+ throw new IllegalStateException(fnfe);
+ }
+ }
+ }
+ }
+
+ // if we still haven't found one
+ if (inputStream == null)
+ {
+ String msg = "Could not find file at: "+path;
+ getLog().debug(msg);
+ if (required)
+ {
+ throw new ResourceNotFoundException(msg);
+ }
+ return null;
+ }
+ return inputStream;
+ }
+
+
+ protected ExtendedProperties getProperties(String path)
+ {
+ return getProperties(path, false);
+ }
+
+ protected ExtendedProperties getProperties(String path, boolean required)
+ {
+ if (getLog().isTraceEnabled())
+ {
+ getLog().trace("Searching for properties at: "+path);
+ }
+
+ InputStream inputStream = getInputStream(path, required);
+ if (inputStream == null)
+ {
+ return null;
+ }
+
+ ExtendedProperties properties = new ExtendedProperties();
+ try
+ {
+ properties.load(inputStream);
+ }
+ catch (IOException ioe)
+ {
+ String msg = "Failed to load properties at: "+path;
+ getLog().error(msg, ioe);
+ if (required)
+ {
+ throw new RuntimeException(ioe);
+ }
+ }
+ finally
+ {
+ try
+ {
+ if (inputStream != null)
+ {
+ inputStream.close();
+ }
+ }
+ catch (IOException ioe)
+ {
+ getLog().error("Failed to close input stream for "+path, ioe);
+ }
+ }
+ return properties;
+ }
+
+
+ protected FactoryConfiguration getConfiguration(String path)
+ {
+ return getConfiguration(path, false);
+ }
+
+ protected FactoryConfiguration getConfiguration(String path, boolean required)
+ {
+ if (getLog().isTraceEnabled())
+ {
+ getLog().trace("Searching for properties at: "+path);
+ }
+
+ // first make sure we can even get such a file
+ InputStream inputStream = getInputStream(path, required);
+ if (inputStream == null)
+ {
+ return null;
+ }
+
+ // then make sure it's a file type we recognize
+ FileFactoryConfiguration config = null;
+ if (path.endsWith(".xml"))
+ {
+ config = new XmlFactoryConfiguration();
+ }
+ else if (path.endsWith(".properties"))
+ {
+ config = new PropertiesFactoryConfiguration();
+ }
+ else
+ {
+ String msg = "Unknown configuration file type: " + path +
+ "\nOnly .xml and .properties configuration files are supported at this time.";
+ getLog().debug(msg);
+ if (required)
+ {
+ throw new UnsupportedOperationException(msg);
+ }
+ }
+
+ // now, try to read the file
+ try
+ {
+ config.read(inputStream);
+ }
+ catch (IOException ioe)
+ {
+ String msg = "Failed to load configuration at: "+path;
+ getLog().error(msg, ioe);
+ if (required)
+ {
+ throw new RuntimeException(ioe);
+ }
+ }
+ finally
+ {
+ try
+ {
+ if (inputStream != null)
+ {
+ inputStream.close();
+ }
+ }
+ catch (IOException ioe)
+ {
+ getLog().error("Failed to close input stream for "+path, ioe);
+ }
+ }
+ return config;
+ }
+
+
+ protected void setEncoding(ServletConfig config)
+ {
+ // we can get these now that velocity is initialized
+ this.defaultContentType =
+ getProperty(CONTENT_TYPE_KEY, DEFAULT_CONTENT_TYPE);
+
+ String encoding = getProperty(RuntimeConstants.OUTPUT_ENCODING,
+ DEFAULT_OUTPUT_ENCODING);
+
+ // For non Latin-1 encodings, ensure that the charset is
+ // included in the Content-Type header.
+ if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding))
+ {
+ int index = defaultContentType.lastIndexOf("charset");
+ if (index < 0)
+ {
+ // the charset specifier is not yet present in header.
+ // append character encoding to default content-type
+ this.defaultContentType += "; charset=" + encoding;
+ }
+ else
+ {
+ // The user may have configuration issues.
+ getLog().info("Charset was already " +
+ "specified in the Content-Type property. " +
+ "Output encoding property will be ignored.");
+ }
+ }
+
+ getLog().debug("Default content-type is: " + defaultContentType);
+ }
+
+
+
+
+
+ /******************* REQUEST PROCESSING ****************************/
+
+ /**
+ *
+ *
+ * @param request HttpServletRequest object containing client request
+ * @param response HttpServletResponse object for the response
+ * @return the {@link Context} prepared and used to perform the rendering
+ * to allow proper cleanup afterward
+ */
+ public Context render(HttpServletRequest request,
+ HttpServletResponse response) throws IOException
+ {
+ // then get a context
+ Context context = getContext(request, response);
+
+ // get the template
+ Template template = getTemplate(request, response);
+
+ // merge the template and context into the response
+ merge(template, context, response.getWriter());
+
+ return context;
+ }
+
+ public Context render(HttpServletRequest request, Writer out)
+ throws IOException
+ {
+ // then get a context
+ Context context = getContext(request);
+
+ // get the template
+ Template template = getTemplate(request);
+
+ // merge the template and context into the writer
+ merge(template, context, out);
+
+ return context;
+ }
+
+
+ protected void prepareToolboxes(HttpServletRequest request)
+ {
+ // add request toolbox, if any
+ Toolbox reqTools = toolboxFactory.getToolbox(ToolboxFactory.DEFAULT_SCOPE);
+ if (reqTools != null)
+ {
+ request.setAttribute(Toolbox.class.getName(), reqTools);
+ }
+
+ //TODO: move this string constant somewhere static
+ if (toolboxFactory.hasToolbox("session"))
+ {
+ //TODO: move this string constant somewhere static too
+ Boolean createSession =
+ (Boolean)toolboxFactory.getGlobalProperty("createSession");
+ HttpSession session = request.getSession(createSession);
+ if (session != null)
+ {
+ // allow only one thread per session at a time
+ synchronized(getMutex(session))
+ {
+ if (session.getAttribute(Toolbox.class.getName()) == null)
+ {
+ Toolbox sessTools = toolboxFactory.getToolbox("session");
+ session.setAttribute(Toolbox.class.getName(), sessTools);
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Returns a mutex (lock object) unique to the specified session
+ * to allow for reliable synchronization on the session.
+ */
+ protected Object getMutex(HttpSession session)
+ {
+ // yes, this uses double-checked locking, but it is safe here
+ // since partial initialization of the lock is not an issue
+ Object lock = session.getAttribute("session.mutex");
+ if (lock == null)
+ {
+ // one thread per toolbox manager at a time
+ synchronized(this)
+ {
+ // in case another thread already came thru
+ lock = session.getAttribute("session.mutex");
+ if (lock == null)
+ {
+ // use a Boolean because it is serializable and small
+ lock = new Boolean(true);
+ session.setAttribute("session.mutex", lock);
+ }
+ }
+ }
+ return lock;
+ }
+
+
+ /**
+ * <p>Creates and returns an initialized Velocity context.</p>
+ *
+ * A new context of class {@link ViewToolContext} is created and
+ * initialized.
+ *
+ * @param request servlet request from client
+ * @param response servlet reponse to client
+ */
+ protected Context createContext(HttpServletRequest request,
+ HttpServletResponse response)
+ {
+ return new ViewToolContext(velocity, request,
+ response, this.servletContext);
+ }
+
+
+ public Context getContext(HttpServletRequest request)
+ {
+ return getContext(request, null);
+ }
+
+ public Context getContext(HttpServletRequest request,
+ HttpServletResponse response)
+ {
+ // first make sure request and session toolboxes are added
+ prepareToolboxes(request);
+
+ // then create the context
+ return createContext(request, response);
+ }
+
+
+
+ /**
+ * <p>Gets the requested template.</p>
+ *
+ * @param request client request
+ * @return Velocity Template object or null
+ */
+ protected Template getTemplate(HttpServletRequest request)
+ {
+ return getTemplate(ServletUtils.getPath(request));
+ }
+
+ protected Template getTemplate(HttpServletRequest request,
+ HttpServletResponse response)
+ {
+ String path = ServletUtils.getPath(request);
+ if (response == null)
+ {
+ return getTemplate(path);
+ }
+ else
+ {
+ return getTemplate(path, response.getCharacterEncoding());
+ }
+ }
+
+
+ /**
+ * Retrieves the requested template.
+ *
+ * @param name The file name of the template to retrieve relative to the
+ * template root.
+ * @return The requested template.
+ * @throws ResourceNotFoundException if template not found
+ * from any available source.
+ * @throws ParseErrorException if template cannot be parsed due
+ * to syntax (or other) error.
+ */
+ public Template getTemplate(String name)
+ {
+ return getTemplate(name, null);
+ }
+
+
+ /**
+ * Retrieves the requested template with the specified character encoding.
+ *
+ * @param name The file name of the template to retrieve relative to the
+ * template root.
+ * @param encoding the character encoding of the template
+ * @return The requested template.
+ * @throws ResourceNotFoundException if template not found
+ * from any available source.
+ * @throws ParseErrorException if template cannot be parsed due
+ * to syntax (or other) error.
+ */
+ public Template getTemplate(String name, String encoding)
+ {
+ try
+ {
+ if (encoding == null)
+ {
+ return getVelocityEngine().getTemplate(name);
+ }
+ else
+ {
+ return getVelocityEngine().getTemplate(name, encoding);
+ }
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ /**
+ * Merges the template with the context. Only override this if you really, really
+ * really need to. (And don't call us with questions if it breaks :)
+ *
+ * @param template template being rendered
+ * @param context Context created by the {@link #createContext}
+ * @param writer into which the content is rendered
+ */
+ protected void merge(Template template, Context context, Writer writer)
+ throws IOException
+ {
+ VelocityWriter vw = null;
+ try
+ {
+ vw = (VelocityWriter)writerPool.get();
+ if (vw == null)
+ {
+ vw = new VelocityWriter(writer, 4 * 1024, true);
+ }
+ else
+ {
+ vw.recycle(writer);
+ }
+ performMerge(template, context, vw);
+ }
+ finally
+ {
+ if (vw != null)
+ {
+ try
+ {
+ // flush and put back into the pool
+ // don't close to allow us to play
+ // nicely with others.
+ vw.flush();
+ /* This hack sets the VelocityWriter's internal ref to the
+ * PrintWriter to null to keep memory free while
+ * the writer is pooled. See bug report #18951 */
+ vw.recycle(null);
+ writerPool.put(vw);
+ }
+ catch (Exception e)
+ {
+ getLog().debug("Trouble releasing VelocityWriter: " +
+ e.getMessage(), e);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * This is here so developers may override it and gain access to the
+ * Writer which the template will be merged into. See
+ * <a href="http://issues.apache.org/jira/browse/VELTOOLS-7">VELTOOLS-7</a>
+ * for discussion of this.
+ *
+ * @param template template object returned by the handleRequest() method
+ * @param context Context created by the {@link #createContext}
+ * @param writer a VelocityWriter that the template is merged into
+ */
+ protected void performMerge(Template template, Context context, Writer writer)
+ throws IOException
+ {
+ template.merge(context, writer);
+ }
+
+}
Propchange: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityView.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityView.java
------------------------------------------------------------------------------
svn:keywords = Revision
Copied: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityViewServlet.java (from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityViewServlet.java)
URL: http://svn.apache.org/viewvc/velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityViewServlet.java?view=diff&rev=521391&p1=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityViewServlet.java&r1=521375&p2=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityViewServlet.java&r2=521391
==============================================================================
--- velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/servlet/VelocityViewServlet.java (original)
+++ velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/VelocityViewServlet.java Thu Mar 22 11:14:06 2007
@@ -1,4 +1,4 @@
-package org.apache.velocity.tools.view.servlet;
+package org.apache.velocity.tools.view;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,36 +19,19 @@
* under the License.
*/
-import java.io.InputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
-import java.io.UnsupportedEncodingException;
-import java.io.Writer;
-import java.util.Properties;
+import java.io.IOException;
import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.collections.ExtendedProperties;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.velocity.Template;
-import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.exception.MethodInvocationException;
-import org.apache.velocity.exception.ParseErrorException;
-import org.apache.velocity.exception.ResourceNotFoundException;
-import org.apache.velocity.io.VelocityWriter;
-import org.apache.velocity.runtime.RuntimeConstants;
-import org.apache.velocity.tools.generic.log.LogSystemCommonsLog;
-import org.apache.velocity.tools.view.ToolboxManager;
-import org.apache.velocity.tools.view.context.ChainedContext;
-import org.apache.velocity.util.SimplePool;
-
+import org.apache.velocity.runtime.log.Log;
/**
* <p>A servlet to process Velocity templates. This is comparable to the
@@ -81,423 +64,53 @@
* 'org.apache.velocity.tools.view.servlet.velocity.properties'.</dd>
* </dl>
*
- * <p>There are methods you may wish to override to access, alter or control
- * any part of the request processing chain. Please see the javadocs for
- * more information on :
- * <ul>
- * <li> {@link #loadConfiguration} : <br>for loading Velocity properties and
- * configuring the Velocity runtime
- * <li> {@link #setContentType} : <br>for changing the content type on a request
- * by request basis
- * <li> {@link #requestCleanup} : <br>post rendering resource or other cleanup
- * <li> {@link #error} : <br>error handling
- * </ul>
- * </p>
- *
- * @author Dave Bryson
- * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
- * @author <a href="mailto:sidler@teamup.com">Gabe Sidler</a>
- * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
- * @author <a href="mailto:kjohnson@transparent.com">Kent Johnson</a>
- * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
- * @author Nathan Bubna
- *
* @version $Id$
*/
public class VelocityViewServlet extends HttpServlet
{
-
/** serial version id */
private static final long serialVersionUID = -3329444102562079189L;
+ private VelocityView view;
- /** The HTTP content type context key. */
- public static final String CONTENT_TYPE = "default.contentType";
-
- /** The default content type for the response */
- public static final String DEFAULT_CONTENT_TYPE = "text/html";
-
- /** Default encoding for the output stream */
- public static final String DEFAULT_OUTPUT_ENCODING = "ISO-8859-1";
/**
- * Key used to access the ServletContext in
- * the Velocity application attributes.
- */
- public static final String SERVLET_CONTEXT_KEY =
- ServletContext.class.getName();
-
- /**
- * Default Runtime properties.
- */
- public static final String DEFAULT_TOOLS_PROPERTIES =
- "/org/apache/velocity/tools/view/servlet/velocity.properties";
-
-
- /**
- * Key used to access the toolbox configuration file path from the
- * Servlet or webapp init parameters ("org.apache.velocity.toolbox").
- */
- protected static final String TOOLBOX_KEY =
- "org.apache.velocity.toolbox";
-
- /**
- * This is the string that is looked for when getInitParameter is
- * called ("org.apache.velocity.properties").
- */
- protected static final String INIT_PROPS_KEY =
- "org.apache.velocity.properties";
-
- /**
- * Default toolbox configuration file path. If no alternate value for
- * this is specified, the servlet will look here.
- */
- protected static final String DEFAULT_TOOLBOX_PATH =
- "/WEB-INF/toolbox.xml";
-
- /**
- * Default velocity properties file path. If no alternate value for
- * this is specified, the servlet will look here.
- */
- protected static final String DEFAULT_PROPERTIES_PATH =
- "/WEB-INF/velocity.properties";
-
- /** A reference to the toolbox manager. */
- protected ToolboxManager toolboxManager = null;
-
-
- /** Cache of writers */
- private static SimplePool writerPool = new SimplePool(40);
-
- /* The engine used to process templates. */
- private VelocityEngine velocity = null;
-
- /**
- * The default content type. When necessary, includes the
- * character set to use when encoding textual output.
- */
- private String defaultContentType;
-
- /**
- * Whether we've logged a deprecation warning for
- * ServletResponse's <code>getOutputStream()</code>.
- * @since VelocityTools 1.1
- */
- private boolean warnOfOutputStreamDeprecation = true;
-
-
-
- /**
- * <p>Initializes servlet, toolbox and Velocity template engine.
+ * <p>Initializes servlet and VelocityView used to process requests.
* Called by the servlet container on loading.</p>
*
- * <p>NOTE: If no charset is specified in the default.contentType
- * property (in your velocity.properties) and you have specified
- * an output.encoding property, then that will be used as the
- * charset for the default content-type of pages served by this
- * servlet.</p>
- *
* @param config servlet configuation
*/
public void init(ServletConfig config) throws ServletException
{
super.init(config);
- // do whatever we have to do to init Velocity
- initVelocity(config);
-
- // init this servlet's toolbox (if any)
- initToolbox(config);
-
- // we can get these now that velocity is initialized
- defaultContentType =
- (String)getVelocityProperty(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
-
- String encoding =
- (String)getVelocityProperty(RuntimeConstants.OUTPUT_ENCODING,
- DEFAULT_OUTPUT_ENCODING);
-
- // For non Latin-1 encodings, ensure that the charset is
- // included in the Content-Type header.
- if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding))
- {
- int index = defaultContentType.lastIndexOf("charset");
- if (index < 0)
- {
- // the charset specifier is not yet present in header.
- // append character encoding to default content-type
- defaultContentType += "; charset=" + encoding;
- }
- else
- {
- // The user may have configuration issues.
- velocity.warn("VelocityViewServlet: Charset was already " +
- "specified in the Content-Type property. " +
- "Output encoding property will be ignored.");
- }
- }
-
- velocity.info("VelocityViewServlet: Default content-type is: " +
- defaultContentType);
- }
-
-
- /**
- * Looks up an init parameter with the specified key in either the
- * ServletConfig or, failing that, in the ServletContext.
- */
- protected String findInitParameter(ServletConfig config, String key)
- {
- // check the servlet config
- String param = config.getInitParameter(key);
-
- if (param == null || param.length() == 0)
- {
- // check the servlet context
- ServletContext servletContext = config.getServletContext();
- param = servletContext.getInitParameter(key);
- }
- return param;
+ setVelocityView(new VelocityView(config));
}
-
- /**
- * Simplifies process of getting a property from VelocityEngine,
- * because the VelocityEngine interface sucks compared to the singleton's.
- * Use of this method assumes that {@link #initVelocity(ServletConfig)}
- * has already been called.
- */
- protected String getVelocityProperty(String key, String alternate)
+ protected void setVelocityView(VelocityView view)
{
- String prop = (String)velocity.getProperty(key);
- if (prop == null || prop.length() == 0)
+ if (view == null)
{
- return alternate;
+ throw new NullPointerException("VelocityView cannot be null");
}
- return prop;
+ this.view = view;
}
-
- /**
- * Returns the underlying VelocityEngine being used.
- */
- protected VelocityEngine getVelocityEngine()
+ protected VelocityView getVelocityView()
{
- return velocity;
+ return this.view;
}
- /**
- * Sets the underlying VelocityEngine
- */
- protected void setVelocityEngine(VelocityEngine ve)
+ protected String getVelocityProperty(String name, String alternate)
{
- if (ve == null)
- {
- throw new NullPointerException("Cannot set the VelocityEngine to null");
- }
- this.velocity = ve;
- }
-
-
- /**
- * Initializes the ServletToolboxManager for this servlet's
- * toolbox (if any).
- *
- * @param config servlet configuation
- */
- protected void initToolbox(ServletConfig config) throws ServletException
- {
- /* check the servlet config and context for a toolbox param */
- String file = findInitParameter(config, TOOLBOX_KEY);
- if (file == null)
- {
- // ok, look in the default location
- file = DEFAULT_TOOLBOX_PATH;
- velocity.debug("VelocityViewServlet: No toolbox entry in configuration."
- + " Looking for '" + DEFAULT_TOOLBOX_PATH + "'");
- }
-
- /* try to get a manager for this toolbox file */
- toolboxManager =
- ServletToolboxManager.getInstance(getServletContext(), file);
- }
-
-
- /**
- * Initializes the Velocity runtime, first calling
- * loadConfiguration(ServletConfig) to get a
- * org.apache.commons.collections.ExtendedProperties
- * of configuration information
- * and then calling velocityEngine.init(). Override this
- * to do anything to the environment before the
- * initialization of the singleton takes place, or to
- * initialize the singleton in other ways.
- *
- * @param config servlet configuration parameters
- */
- protected void initVelocity(ServletConfig config) throws ServletException
- {
- velocity = new VelocityEngine();
- setVelocityEngine(velocity);
-
- // register this engine to be the default handler of log messages
- // if the user points commons-logging to the LogSystemCommonsLog
- LogSystemCommonsLog.setVelocityEngine(velocity);
-
- velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext());
-
- // Try reading the VelocityTools default configuration
- try
- {
- ExtendedProperties defaultProperties = loadDefaultProperties();
- velocity.setExtendedProperties(defaultProperties);
- }
- catch(Exception e)
- {
- log("VelocityViewServlet: Unable to read Velocity Servlet configuration file: ", e);
-
- // This is a fatal error...
- throw new ServletException(e);
- }
-
- // Try reading an overriding user Velocity configuration
- try
- {
- ExtendedProperties p = loadConfiguration(config);
- velocity.setExtendedProperties(p);
- }
- catch(Exception e)
- {
- log("VelocityViewServlet: Unable to read Velocity configuration file: ", e);
- log("VelocityViewServlet: Using default Velocity configuration.");
- }
-
- // now all is ready - init Velocity
- try
- {
- velocity.init();
- }
- catch(Exception e)
- {
- log("VelocityViewServlet: PANIC! unable to init()", e);
- throw new ServletException(e);
- }
- }
-
- private ExtendedProperties loadDefaultProperties()
- {
- InputStream inputStream = null;
- ExtendedProperties defaultProperties = new ExtendedProperties();
-
- try
- {
- inputStream = getClass()
- .getResourceAsStream(DEFAULT_TOOLS_PROPERTIES);
- if (inputStream != null)
- {
- defaultProperties.load(inputStream);
- }
- }
- catch (IOException ioe)
- {
- log("Cannot load default extendedProperties!", ioe);
- }
- finally
- {
- try
- {
- if (inputStream != null)
- {
- inputStream.close();
- }
- }
- catch (IOException ioe)
- {
- log("Cannot close default extendedProperties!", ioe);
- }
- }
- return defaultProperties;
+ return this.view.getProperty(name, alternate);
}
-
- /**
- * Loads the configuration information and returns that
- * information as an ExtendedProperties, which will be used to
- * initialize the Velocity runtime.
- * <br><br>
- * Currently, this method gets the initialization parameter
- * VelocityServlet.INIT_PROPS_KEY, which should be a file containing
- * the configuration information.
- * <br><br>
- * To configure your Servlet Spec 2.2 compliant servlet runner to pass
- * this to you, put the following in your WEB-INF/web.xml file
- * <br>
- * <pre>
- * <servlet>
- * <servlet-name> YourServlet </servlet-name>
- * <servlet-class> your.package.YourServlet </servlet-class>
- * <init-param>
- * <param-name> org.apache.velocity.properties </param-name>
- * <param-value> velocity.properties </param-value>
- * </init-param>
- * </servlet>
- * </pre>
- *
- * Alternately, if you wish to configure an entire context in this
- * fashion, you may use the following:
- * <br>
- * <pre>
- * <context-param>
- * <param-name> org.apache.velocity.properties </param-name>
- * <param-value> velocity.properties </param-value>
- * <description> Path to Velocity configuration </description>
- * </context-param>
- * </pre>
- *
- * Derived classes may do the same, or take advantage of this code to do the loading for them via :
- * <pre>
- * ExtendedProperties p = super.loadConfiguration(config);
- * </pre>
- * and then add or modify the configuration values from the file.
- * <br>
- *
- * @param config ServletConfig passed to the servlets init() function
- * Can be used to access the real path via ServletContext (hint)
- * @return ExtendedProperties loaded with configuration values to be used
- * to initialize the Velocity runtime.
- * @throws IOException I/O problem accessing the specified file, if specified.
- */
- protected ExtendedProperties loadConfiguration(ServletConfig config)
- throws IOException
+ protected Log getLog()
{
- // grab the path to the custom props file (if any)
- String propsFile = findInitParameter(config, INIT_PROPS_KEY);
- if (propsFile == null)
- {
- // ok, look in the default location for custom props
- propsFile = DEFAULT_PROPERTIES_PATH;
- velocity.debug("VelocityViewServlet: Looking for custom properties at '"
- + DEFAULT_PROPERTIES_PATH + "'");
- }
-
- ExtendedProperties p = new ExtendedProperties();
- InputStream is = getServletContext().getResourceAsStream(propsFile);
- if (is != null)
- {
- // load the properties from the input stream
- p.load(is);
- velocity.info("VelocityViewServlet: Using custom properties at '"
- + propsFile + "'");
- }
- else
- {
- velocity.debug("VelocityViewServlet: No custom properties found. " +
- "Using default Velocity configuration.");
- }
- return p;
+ return this.view.getLog();
}
-
/**
* Handles GET - calls doRequest()
*/
@@ -524,81 +137,44 @@
* @param request HttpServletRequest object containing client request
* @param response HttpServletResponse object for the response
*/
- protected void doRequest(HttpServletRequest request,
- HttpServletResponse response)
- throws ServletException, IOException
+ protected void doRequest(HttpServletRequest request, HttpServletResponse response)
{
Context context = null;
try
{
- // first, get a context
+ // then get a context
context = createContext(request, response);
- // set the content type
+ // call standard extension point
+ fillContext(context, request);
+
setContentType(request, response);
// get the template
- Template template = handleRequest(request, response, context);
-
- // bail if we can't find the template
- if (template == null)
- {
- velocity.warn("VelocityViewServlet: couldn't find template to match request.");
- return;
- }
+ Template template = getTemplate(request, response);
- // merge the template and context
+ // merge the template and context into the response
mergeTemplate(template, context, response);
}
- catch (Exception e)
+ catch (Throwable e)
{
- // log the exception
- velocity.error("VelocityViewServlet: Exception processing the template: "+e);
-
- // call the error handler to let the derived class
- // do something useful with this failure.
error(request, response, e);
}
finally
{
- // call cleanup routine to let a derived class do some cleanup
- requestCleanup(request, response, context);
+ cleanup(request, response, context);
}
}
-
- /**
- * Cleanup routine called at the end of the request processing sequence
- * allows a derived class to do resource cleanup or other end of
- * process cycle tasks. This default implementation does nothing.
- *
- * @param request servlet request from client
- * @param response servlet reponse
- * @param context Context created by the {@link #createContext}
- */
- protected void requestCleanup(HttpServletRequest request,
- HttpServletResponse response,
- Context context)
+ protected Context createContext(HttpServletRequest request,
+ HttpServletResponse response)
{
+ return view.getContext(request, response);
}
-
- /**
- * <p>Handle the template processing request.</p>
- *
- * @param request client request
- * @param response client response
- * @param ctx VelocityContext to fill
- *
- * @return Velocity Template object or null
- */
- protected Template handleRequest(HttpServletRequest request,
- HttpServletResponse response,
- Context ctx)
- throws Exception
+ protected void fillContext(Context context, HttpServletRequest request)
{
- String path = ServletUtils.getPath(request);
- return getTemplate(path);
+ // this implementation does nothing
}
@@ -607,13 +183,12 @@
* by a derived class.
*
* <p>The default implementation is :
- * <pre>
- *
- * response.setContentType(defaultContentType);
- *
- * </pre>
+ * <code>
+ * response.setContentType(view.getDefaultContentType());
+ * </code>
* where defaultContentType is set to the value of the default.contentType
- * property, or "text/html" if that is not set.</p>
+ * property, or "text/html" if that was not set for the {@link VelocityView}.
+ * </p>
*
* @param request servlet request from client
* @param response servlet reponse to client
@@ -621,145 +196,25 @@
protected void setContentType(HttpServletRequest request,
HttpServletResponse response)
{
- response.setContentType(defaultContentType);
- }
-
-
- /**
- * <p>Creates and returns an initialized Velocity context.</p>
- *
- * A new context of class {@link ChainedContext} is created and
- * initialized.
- *
- * @param request servlet request from client
- * @param response servlet reponse to client
- */
- protected Context createContext(HttpServletRequest request,
- HttpServletResponse response)
- {
- ChainedContext ctx =
- new ChainedContext(velocity, request, response, getServletContext());
-
- /* if we have a toolbox manager, get a toolbox from it */
- if (toolboxManager != null)
- {
- ctx.setToolbox(toolboxManager.getToolbox(ctx));
- }
- return ctx;
+ response.setContentType(view.getDefaultContentType());
}
-
- /**
- * Retrieves the requested template.
- *
- * @param name The file name of the template to retrieve relative to the
- * template root.
- * @return The requested template.
- * @throws ResourceNotFoundException if template not found
- * from any available source.
- * @throws ParseErrorException if template cannot be parsed due
- * to syntax (or other) error.
- * @throws Exception if an error occurs in template initialization
- */
- public Template getTemplate(String name)
- throws ResourceNotFoundException, ParseErrorException, Exception
+ protected Template getTemplate(HttpServletRequest request,
+ HttpServletResponse response)
{
- return velocity.getTemplate(name);
+ return view.getTemplate(request, response);
}
-
- /**
- * Retrieves the requested template with the specified character encoding.
- *
- * @param name The file name of the template to retrieve relative to the
- * template root.
- * @param encoding the character encoding of the template
- * @return The requested template.
- * @throws ResourceNotFoundException if template not found
- * from any available source.
- * @throws ParseErrorException if template cannot be parsed due
- * to syntax (or other) error.
- * @throws Exception if an error occurs in template initialization
- */
- public Template getTemplate(String name, String encoding)
- throws ResourceNotFoundException, ParseErrorException, Exception
+ protected Template getTemplate(String name)
{
- return velocity.getTemplate(name, encoding);
+ return view.getTemplate(name);
}
-
- /**
- * Merges the template with the context. Only override this if you really, really
- * really need to. (And don't call us with questions if it breaks :)
- *
- * @param template template object returned by the handleRequest() method
- * @param context Context created by the {@link #createContext}
- * @param response servlet reponse (used to get a Writer)
- */
- protected void mergeTemplate(Template template,
- Context context,
+ protected void mergeTemplate(Template template, Context context,
HttpServletResponse response)
- throws ResourceNotFoundException, ParseErrorException,
- MethodInvocationException, IOException,
- UnsupportedEncodingException, Exception
- {
- VelocityWriter vw = null;
- Writer writer = getResponseWriter(response);
- try
- {
- vw = (VelocityWriter)writerPool.get();
- if (vw == null)
- {
- vw = new VelocityWriter(writer, 4 * 1024, true);
- }
- else
- {
- vw.recycle(writer);
- }
- performMerge(template, context, vw);
- }
- finally
- {
- if (vw != null)
- {
- try
- {
- // flush and put back into the pool
- // don't close to allow us to play
- // nicely with others.
- vw.flush();
- /* This hack sets the VelocityWriter's internal ref to the
- * PrintWriter to null to keep memory free while
- * the writer is pooled. See bug report #18951 */
- vw.recycle(null);
- writerPool.put(vw);
- }
- catch (Exception e)
- {
- velocity.debug("VelocityViewServlet: " +
- "Trouble releasing VelocityWriter: " +
- e.getMessage());
- }
- }
- }
- }
-
-
- /**
- * This is here so developers may override it and gain access to the
- * Writer which the template will be merged into. See
- * <a href="http://issues.apache.org/jira/browse/VELTOOLS-7">VELTOOLS-7</a>
- * for discussion of this.
- *
- * @param template template object returned by the handleRequest() method
- * @param context Context created by the {@link #createContext}
- * @param writer a VelocityWriter that the template is merged into
- */
- protected void performMerge(Template template, Context context, Writer writer)
- throws ResourceNotFoundException, ParseErrorException,
- MethodInvocationException, Exception
+ throws IOException
{
- template.merge(context, writer);
+ view.merge(template, context, response.getWriter());
}
@@ -774,8 +229,7 @@
*/
protected void error(HttpServletRequest request,
HttpServletResponse response,
- Exception e)
- throws ServletException
+ Throwable e)
{
try
{
@@ -783,7 +237,7 @@
html.append("<html>\n");
html.append("<head><title>Error</title></head>\n");
html.append("<body>\n");
- html.append("<h2>VelocityViewServlet : Error processing a template for path '");
+ html.append("<h2>VelocityView : Error processing a template for path '");
html.append(ServletUtils.getPath(request));
html.append("'</h2>\n");
@@ -796,6 +250,8 @@
html.append("\n<br>\n");
}
+ //TODO: add line/column/template info for parse errors et al
+
// if it's an MIE, i want the real stack trace!
if (cause instanceof MethodInvocationException)
{
@@ -811,63 +267,33 @@
html.append("</pre>\n");
html.append("</body>\n");
html.append("</html>");
- getResponseWriter(response).write(html.toString());
+ response.getWriter().write(html.toString());
}
catch (Exception e2)
{
// clearly something is quite wrong.
// let's log the new exception then give up and
- // throw a servlet exception that wraps the first one
- velocity.error("VelocityViewServlet: Exception while printing error screen: "+e2);
- throw new ServletException(e);
+ // throw a runtime exception that wraps the first one
+ String msg = "Exception while printing error screen";
+ view.getLog().error(msg, e2);
+ throw new RuntimeException(msg, e);
}
}
+
/**
- * <p>Procure a Writer with correct encoding which can be used
- * even if HttpServletResponse's <code>getOutputStream()</code> method
- * has already been called.</p>
- *
- * <p>This is a transitional method which will be removed in a
- * future version of Velocity. It is not recommended that you
- * override this method.</p>
+ * Cleanup routine called at the end of the request processing sequence
+ * allows a derived class to do resource cleanup or other end of
+ * process cycle tasks. This default implementation does nothing.
*
- * @param response The response.
- * @return A <code>Writer</code>, possibly created using the
- * <code>getOutputStream()</code>.
+ * @param request servlet request from client
+ * @param response servlet response
+ * @param context Context that was merged with the requested template
*/
- protected Writer getResponseWriter(HttpServletResponse response)
- throws UnsupportedEncodingException, IOException
+ protected void cleanup(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context)
{
- Writer writer = null;
- try
- {
- writer = response.getWriter();
- }
- catch (IllegalStateException e)
- {
- // ASSUMPTION: We already called getOutputStream(), so
- // calls to getWriter() fail. Use of OutputStreamWriter
- // assures our desired character set
- if (this.warnOfOutputStreamDeprecation)
- {
- this.warnOfOutputStreamDeprecation = false;
- velocity.warn("VelocityViewServlet: " +
- "Use of ServletResponse's getOutputStream() " +
- "method with VelocityViewServlet is " +
- "deprecated -- support will be removed in " +
- "an upcoming release");
- }
- // Assume the encoding has been set via setContentType().
- String encoding = response.getCharacterEncoding();
- if (encoding == null)
- {
- encoding = DEFAULT_OUTPUT_ENCODING;
- }
- writer = new OutputStreamWriter(response.getOutputStream(),
- encoding);
- }
- return writer;
}
}
Copied: velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ViewContext.java (from r521375, velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/context/ViewContext.java)
URL: http://svn.apache.org/viewvc/velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ViewContext.java?view=diff&rev=521391&p1=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/context/ViewContext.java&r1=521375&p2=velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ViewContext.java&r2=521391
==============================================================================
--- velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/context/ViewContext.java (original)
+++ velocity/tools/branches/2.x/src/main/java/org/apache/velocity/tools/view/ViewContext.java Thu Mar 22 11:14:06 2007
@@ -1,4 +1,4 @@
-package org.apache.velocity.tools.view.context;
+package org.apache.velocity.tools.view;
/*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,13 +19,12 @@
* under the License.
*/
-import org.apache.velocity.app.VelocityEngine;
-import org.apache.velocity.context.Context;
-
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.ServletContext;
-
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.context.Context;
+import org.apache.velocity.tools.Toolbox;
/**
* <p>Objects implementing this interface are passed to view tools
@@ -38,6 +37,7 @@
*
* @author <a href="mailto:sidler@teamup.com">Gabe Sidler</a>
* @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
+ * @author Nathan Bubna
*
* @version $Id$
*/
@@ -55,8 +55,8 @@
/** Key used for the servlet context object. */
public static final String APPLICATION = "application";
- /** Key used for XHTML setting (tells tools and macros to output XHTML). */
- public static final String XHTML = "XHTML";
+ /** Key used to store a toolbox in request/session/application attributes. */
+ public static final String TOOLBOX_KEY = Toolbox.class.getName();
/**