nbubna 2003/03/06 19:24:39
Modified: src/java/org/apache/velocity/tools/view/servlet
VelocityViewServlet.java
Log:
Pull all relevant VelocityServlet code up into VVS and make it extend HttpServlet
directly
pull toolbox setup out of init() into its own initToolbox()
remove support for deprecated OLD_INIT_PROPS_KEY
(in other words, the only accepted param-name for your velocity.properties is
'org.apache.velocity.properties')
oh, and i pulled up the relevant javadoc from VelocityServlet as well
Revision Changes Path
1.2 +457 -33
jakarta-velocity-tools/src/java/org/apache/velocity/tools/view/servlet/VelocityViewServlet.java
Index: VelocityViewServlet.java
===================================================================
RCS file:
/home/cvs/jakarta-velocity-tools/src/java/org/apache/velocity/tools/view/servlet/VelocityViewServlet.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- VelocityViewServlet.java 5 Mar 2003 06:13:03 -0000 1.1
+++ VelocityViewServlet.java 7 Mar 2003 03:24:39 -0000 1.2
@@ -55,29 +55,37 @@
package org.apache.velocity.tools.view.servlet;
-import javax.servlet.ServletContext;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.OutputStreamWriter;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.UnsupportedEncodingException;
+import java.util.Properties;
+
import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import java.util.Enumeration;
-import java.util.Properties;
-import java.util.HashMap;
-import java.util.Properties;
-
import org.apache.commons.collections.ExtendedProperties;
-import org.apache.velocity.servlet.VelocityServlet;
-import org.apache.velocity.app.Velocity;
import org.apache.velocity.Template;
+import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
+import org.apache.velocity.exception.ResourceNotFoundException;
+import org.apache.velocity.exception.ParseErrorException;
+import org.apache.velocity.exception.MethodInvocationException;
+import org.apache.velocity.io.VelocityWriter;
import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.RuntimeSingleton;
+import org.apache.velocity.util.SimplePool;
import org.apache.velocity.tools.view.context.ToolboxContext;
-import org.apache.velocity.tools.view.context.ViewContext;
import org.apache.velocity.tools.view.context.ChainedContext;
import org.apache.velocity.tools.view.servlet.ServletToolboxManager;
import org.apache.velocity.tools.view.servlet.WebappLoader;
@@ -109,22 +117,55 @@
* relative to the web application root directory. If this parameter
* is not present, Velocity is initialized with default settings.</dd>
* </dl>
+ *
+ * <p>There are methods you can override to access, alter or control
+ * any part of the request processing chain. Please see the javadocs for
+ * more information on :
+ * <ul>
+ * <li> loadConfiguration() : for setting up the Velocity runtime
+ * <li> createContext() : for creating and loading the Context
+ * <li> setContentType() : for changing the content type on a request
+ * by request basis
+ * <li> handleRequest() : you <b>must</b> implement this
+ * <li> mergeTemplate() : the template rendering process
+ * <li> requestCleanup() : post rendering resource or other cleanup
+ * <li> error() : error handling
+ * </ul>
+ * <br>
+ * If you put a contentType object into the context within either your
+ * serlvet or within your template, then that will be used to override
+ * the default content type specified in the properties file.
+ *
+ * "contentType" - The value for the Content-Type: header
*
+ * @author Dave Bryson
+ * @author <a href="mailto:[EMAIL PROTECTED]">Jon S. Stevens</a>
* @author <a href="mailto:[EMAIL PROTECTED]">Gabe Sidler</a>
- * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
+ * @author <a href="mailto:[EMAIL PROTECTED]">Geir Magnusson Jr.</a>
+ * @author <a href="[EMAIL PROTECTED]">Kent Johnson</a>
+ * @author <a href="[EMAIL PROTECTED]">Daniel Rall</a>
+ * @author <a href="[EMAIL PROTECTED]">Nathan Bubna</a>
*
* @version $Id$
*/
-public class VelocityViewServlet extends VelocityServlet
+public class VelocityViewServlet extends HttpServlet
{
/**
- * Key used to access the toolbox configuration file path from the
- * Servlet init parameters.
+ * The HTTP content type context key.
*/
- public static final String TOOLBOX_PARAM = "toolbox";
+ public static final String CONTENT_TYPE = "default.contentType";
+ /**
+ * The default content type for the response
+ */
+ public static final String DEFAULT_CONTENT_TYPE = "text/html";
+
+ /**
+ * Encoding for the output stream
+ */
+ public static final String DEFAULT_OUTPUT_ENCODING = "ISO-8859-1";
/**
* Key used to access the ServletContext in the Velocity
@@ -133,37 +174,89 @@
/**
+ * Key used to access the toolbox configuration file path from the
+ * Servlet or webapp init parameters.
+ */
+ protected static final String TOOLBOX_KEY = "toolbox";
+
+ /**
+ * This is the string that is looked for when getInitParameter is
+ * called (<code>org.apache.velocity.properties</code>).
+ */
+ protected static final String INIT_PROPS_KEY =
+ "org.apache.velocity.properties";
+
+
+ /**
+ * Cache of writers
+ */
+ private static SimplePool writerPool = new SimplePool(40);
+
+ /**
+ * The encoding to use when generating outputing.
+ */
+ private String encoding = null;
+
+ /**
+ * The default content type.
+ */
+ private String defaultContentType;
+
+ /**
* A reference to the toolbox manager.
*/
- protected ServletToolboxManager toolboxManager = null;
+ private ServletToolboxManager toolboxManager = null;
/**
- * <p>Initializes servlet, toolbox and Velocity template engine.</p>
+ * <p>Initializes servlet, toolbox and Velocity template engine.
+ * Called by the servlet container on loading.</p>
*
* @param config servlet configuation
*/
- public void init( ServletConfig config )
- throws ServletException
+ public void init(ServletConfig config) throws ServletException
{
- super.init( config );
+ 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 =
+ RuntimeSingleton.getString(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
+ encoding =
+ RuntimeSingleton.getString(RuntimeSingleton.OUTPUT_ENCODING,
+ DEFAULT_OUTPUT_ENCODING);
+ }
+
+ /**
+ * Initializes the ServletToolboxManager for this servlet's
+ * toolbox (if any).
+ *
+ * @param config servlet configuation
+ */
+ protected void initToolbox(ServletConfig config) throws ServletException
+ {
ServletContext servletContext = config.getServletContext();
/* check the servlet config for a toolbox */
- String key = config.getInitParameter(TOOLBOX_PARAM);
+ String file = config.getInitParameter(TOOLBOX_KEY);
/* check the servlet context for a toolbox */
- if (key == null || key.length() == 0)
+ if (file == null || file.length() == 0)
{
- key = servletContext.getInitParameter(TOOLBOX_PARAM);
+ file = servletContext.getInitParameter(TOOLBOX_KEY);
}
/* if we have a toolbox, get a manager for it */
- if (key != null)
+ if (file != null)
{
toolboxManager =
- ServletToolboxManager.getInstance(servletContext, key);
+ ServletToolboxManager.getInstance(servletContext, file);
}
else
{
@@ -173,26 +266,32 @@
/**
- * Initializes Velocity.
+ * Initializes the Velocity runtime, first calling
+ * loadConfiguration(ServletConfig) to get a
+ * java.util.Properties of configuration information
+ * and then calling Velocity.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
+ protected void initVelocity(ServletConfig config) throws ServletException
{
+ Velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext());
+
// default to servletlogger, which logs to the servlet engines log
Velocity.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
ServletLogger.class.getName());
// by default, load resources with webapp resource loader
- Velocity.setApplicationAttribute(SERVLET_CONTEXT_KEY, getServletContext());
Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "webapp");
Velocity.setProperty("webapp.resource.loader.class",
WebappLoader.class.getName());
// Try reading an overriding Velocity configuration
try
{
- Properties p = super.loadConfiguration(config);
+ Properties p = loadConfiguration(config);
Velocity.setExtendedProperties(ExtendedProperties.convertProperties(p));
}
catch(Exception e)
@@ -213,6 +312,176 @@
}
}
+
+ /**
+ * Loads the configuration information and returns that
+ * information as a Properties, 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>
+ * Properties 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 java.util.Properties loaded with configuration values to be used
+ * to initialize the Velocity runtime.
+ * @throws FileNotFoundException if a specified file is not found.
+ * @throws IOException I/O problem accessing the specified file, if specified.
+ */
+ protected Properties loadConfiguration(ServletConfig config)
+ throws IOException, FileNotFoundException
+ {
+ ServletContext servletContext = config.getServletContext();
+
+ // grab the path to the custom props file (if any)
+ String propsFile = config.getInitParameter(INIT_PROPS_KEY);
+ if (propsFile == null || propsFile.length() == 0)
+ {
+ propsFile = servletContext.getInitParameter(INIT_PROPS_KEY);
+ }
+
+ /*
+ * This will attempt to find the location of the properties
+ * file from the relative path to the WAR archive (ie:
+ * docroot). Since JServ returns null for getRealPath()
+ * because it was never implemented correctly, then we know we
+ * will not have an issue with using it this way. I don't know
+ * if this will break other servlet engines, but it probably
+ * shouldn't since WAR files are the future anyways.
+ */
+ Properties p = new Properties();
+
+ if (propsFile != null)
+ {
+ String realPath = servletContext.getRealPath(propsFile);
+
+ if (realPath != null)
+ {
+ propsFile = realPath;
+ }
+
+ p.load(new FileInputStream(propsFile));
+ }
+ else
+ {
+ Velocity.warn("Hey!! Where's the velocity.properties??");
+ }
+
+ return p;
+ }
+
+
+ /**
+ * Handles GET - calls doRequest()
+ */
+ public void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ doRequest(request, response);
+ }
+
+
+ /**
+ * Handle a POST request - calls doRequest()
+ */
+ public void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ doRequest(request, response);
+ }
+
+
+ /**
+ * Handles with both GET and POST requests
+ *
+ * @param request HttpServletRequest object containing client request
+ * @param response HttpServletResponse object for the response
+ */
+ protected void doRequest(HttpServletRequest request,
+ HttpServletResponse response)
+ throws ServletException, IOException
+ {
+ try
+ {
+ // first, get a context
+ Context context = createContext(request, response);
+
+ // set the content type
+ setContentType(request, response);
+
+ // get the template
+ Template template = handleRequest(request, response, context);
+
+ // bail if we can't find the template
+ if (template == null)
+ {
+ return;
+ }
+
+ // merge the template and context
+ mergeTemplate(template, context, response);
+
+ // call cleanup routine to let a derived class do some cleanup
+ requestCleanup(request, response, context);
+ }
+ catch (Exception e)
+ {
+ // call the error handler to let the derived class
+ // do something useful with this failure.
+ error(request, response, e);
+ }
+ }
+
+
+ /**
+ * 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
+ *
+ * @param request servlet request from client
+ * @param response servlet reponse
+ * @param context context created by the createContext() method
+ */
+ protected void requestCleanup(HttpServletRequest request,
+ HttpServletResponse response,
+ Context context)
+ {
+ return;
+ }
+
/**
* <p>Handle the template processing request.</p>
@@ -243,6 +512,29 @@
/**
+ * Sets the content type of the response. This is available to be overriden
+ * by a derived class.
+ *
+ * <p>The default implementation is :
+ * <pre>
+ *
+ * response.setContentType(defaultContentType);
+ *
+ * </pre>
+ * where defaultContentType is set to the value of the default.contentType
+ * property, or "text/html" if that is not set.</p>
+ *
+ * @param request servlet request from client
+ * @param response servlet reponse to client
+ */
+ protected void setContentType(HttpServletRequest request,
+ HttpServletResponse response)
+ {
+ response.setContentType(defaultContentType);
+ }
+
+
+ /**
* <p>Creates and returns an initialized Velocity context.</p>
*
* A new context of class [EMAIL PROTECTED] ChainedContext} is created and
@@ -267,11 +559,143 @@
if (toolboxManager != null)
{
- ToolboxContext tc = toolboxManager.getToolboxContext( ctx );
- ctx.setToolbox( tc);
+ ctx.setToolbox(toolboxManager.getToolboxContext(ctx));
}
return ctx;
+ }
+
+
+ /**
+ * 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
+ {
+ return RuntimeSingleton.getTemplate(name);
+ }
+
+
+ /**
+ * 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
+ {
+ return RuntimeSingleton.getTemplate(name, encoding);
+ }
+
+
+ /**
+ * 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 createContext() method
+ * @param response servlet reponse (use this to get the output stream or Writer
+ */
+ protected void mergeTemplate(Template template,
+ Context context,
+ HttpServletResponse response)
+ throws ResourceNotFoundException, ParseErrorException,
+ MethodInvocationException, IOException,
+ UnsupportedEncodingException, Exception
+ {
+ ServletOutputStream output = response.getOutputStream();
+ VelocityWriter vw = null;
+
+ try
+ {
+ vw = (VelocityWriter) writerPool.get();
+
+ if (vw == null)
+ {
+ vw = new VelocityWriter(new OutputStreamWriter(output, encoding),
4*1024, true);
+ }
+ else
+ {
+ vw.recycle(new OutputStreamWriter(output, encoding));
+ }
+
+ template.merge(context, vw);
+ }
+ finally
+ {
+ try
+ {
+ if (vw != null)
+ {
+ // flush and put back into the pool
+ // don't close to allow us to play
+ // nicely with others.
+ vw.flush();
+ writerPool.put(vw);
+ }
+ }
+ catch (Exception e)
+ {
+ // do nothing
+ }
+ }
+ }
+
+
+ /**
+ * Invoked when there is an error thrown in any part of doRequest() processing.
+ * <br><br>
+ * Default will send a simple HTML response indicating there was a problem.
+ *
+ * @param request original HttpServletRequest from servlet container.
+ * @param response HttpServletResponse object from servlet container.
+ * @param cause Exception that was thrown by some other part of process.
+ */
+ protected void error(HttpServletRequest request,
+ HttpServletResponse response,
+ Exception cause)
+ throws ServletException, IOException
+ {
+ StringBuffer html = new StringBuffer();
+ html.append("<html>");
+ html.append("<title>Error</title>");
+ html.append("<body bgcolor=\"#ffffff\">");
+ html.append("<h2>VelocityServlet : Error processing the template</h2>");
+ html.append("<pre>");
+ String why = cause.getMessage();
+ if (why != null && why.trim().length() > 0)
+ {
+ html.append(why);
+ html.append("<br>");
+ }
+
+ StringWriter sw = new StringWriter();
+ cause.printStackTrace(new PrintWriter(sw));
+
+ html.append(sw.toString());
+ html.append("</pre>");
+ html.append("</body>");
+ html.append("</html>");
+ response.getOutputStream().print(html.toString());
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]