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>
  +     *    &lt;servlet&gt;
  +     *      &lt;servlet-name&gt; YourServlet &lt/servlet-name&gt;
  +     *      &lt;servlet-class&gt; your.package.YourServlet &lt;/servlet-class&gt;
  +     *      &lt;init-param&gt;
  +     *         &lt;param-name&gt; org.apache.velocity.properties &lt;/param-name&gt;
  +     *         &lt;param-value&gt; velocity.properties &lt;/param-value&gt;
  +     *      &lt;/init-param&gt;
  +     *    &lt;/servlet&gt;
  +     *   </pre>
  +     *
  +     * Alternately, if you wish to configure an entire context in this
  +     * fashion, you may use the following:
  +     *  <br>
  +     *  <pre>
  +     *    &lt;context-param&gt;
  +     *       &lt;param-name&gt; org.apache.velocity.properties &lt;/param-name&gt;
  +     *       &lt;param-value&gt; velocity.properties &lt;/param-value&gt;
  +     *       &lt;description&gt; Path to Velocity configuration &lt;/description&gt;
  +     *    &lt;/context-param&gt;
  +     *   </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]

Reply via email to