dlr 2003/08/31 11:09:59
Modified: src/java/org/apache/velocity/servlet VelocityServlet.java
build testcases.xml
xdocs changes.xml
Added: src/java/org/apache/velocity/test VelocityServletTest.java
Log:
* src/java/org/apache/velocity/servlet/VelocityServlet.java
REQUEST, RESPONSE, doGet(), doPost(): Improved JavaDoc.
encoding: Removed unnecessary class field.
defaultContentType: Added a touch more JavaDoc.
init(): No longer set encoding field.
doRequest(): Moved call to requestCleanup() down into a finally
block. This is a minor change in behavior to supply a much more
useful cleanup hook for cases where unexpected exceptions are
thrown.
mergeTemplate(): Get the character encoding from the
HttpServletResponse object. The assumption is that it has already
been set via a charset= parameter on the Content-Type header.
setContentType(), chooseCharacterEncoding(): Added support for
dynamic selection of response character encoding.
error(): Output tweak.
* build/testcases.xml
test-all, test-servlet: Added new test-servlet target.
* src/java/org/apache/velocity/test/VelocityServletTest.java
A test case for VelocityServlet, currently covering only its newly
improved encoding behavior. There is a lot of mocked-up Servlet API
implementation in this class which should be replaced by a
supporting library which already does this sort of thing.
* xdocs/changes.xml
Noted addition of support for dynamic selection of output character
encoding in VelocityServlet.
Revision Changes Path
1.51 +76 -41
jakarta-velocity/src/java/org/apache/velocity/servlet/VelocityServlet.java
Index: VelocityServlet.java
===================================================================
RCS file:
/home/cvs/jakarta-velocity/src/java/org/apache/velocity/servlet/VelocityServlet.java,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -u -r1.50 -r1.51
--- VelocityServlet.java 22 Aug 2003 23:23:47 -0000 1.50
+++ VelocityServlet.java 31 Aug 2003 18:09:58 -0000 1.51
@@ -74,6 +74,7 @@
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
+import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.RuntimeSingleton;
import org.apache.velocity.io.VelocityWriter;
import org.apache.velocity.util.SimplePool;
@@ -130,12 +131,12 @@
public abstract class VelocityServlet extends HttpServlet
{
/**
- * The HTTP request object context key.
+ * The context key for the HTTP request object.
*/
public static final String REQUEST = "req";
/**
- * The HTTP response object context key.
+ * The context key for the HTTP response object.
*/
public static final String RESPONSE = "res";
@@ -154,14 +155,10 @@
* Encoding for the output stream
*/
public static final String DEFAULT_OUTPUT_ENCODING = "ISO-8859-1";
-
- /**
- * The encoding to use when generating outputing.
- */
- private static String encoding = null;
/**
- * The default content type.
+ * The default content type, itself defaulting to [EMAIL PROTECTED]
+ * #DEFAULT_CONTENT_TYPE} if not configured.
*/
private static String defaultContentType;
@@ -203,11 +200,10 @@
initVelocity( config );
/*
- * we can get these now that velocity is initialized
+ * Now that Velocity is initialized, cache some config.
*/
- defaultContentType = RuntimeSingleton.getString( CONTENT_TYPE,
DEFAULT_CONTENT_TYPE);
- encoding = RuntimeSingleton.getString( RuntimeSingleton.OUTPUT_ENCODING,
- DEFAULT_OUTPUT_ENCODING);
+ defaultContentType = RuntimeSingleton.getString(CONTENT_TYPE,
+ DEFAULT_CONTENT_TYPE);
}
/**
@@ -350,7 +346,8 @@
}
/**
- * Handles GET - calls doRequest()
+ * Handles HTTP <code>GET</code> requests by calling [EMAIL PROTECTED]
+ * #doRequest()}.
*/
public void doGet( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
@@ -359,7 +356,8 @@
}
/**
- * Handle a POST request - calls doRequest()
+ * Handles HTTP <code>POST</code> requests by calling [EMAIL PROTECTED]
+ * #doRequest()}.
*/
public void doPost( HttpServletRequest request, HttpServletResponse response )
throws ServletException, IOException
@@ -368,7 +366,7 @@
}
/**
- * Handles all requests
+ * Handles all requests (by default).
*
* @param request HttpServletRequest object containing client request
* @param response HttpServletResponse object for the response
@@ -376,13 +374,14 @@
protected void doRequest(HttpServletRequest request, HttpServletResponse
response )
throws ServletException, IOException
{
+ Context context = null;
try
{
/*
* first, get a context
*/
- Context context = createContext( request, response );
+ context = createContext( request, response );
/*
* set the content type
@@ -409,12 +408,6 @@
*/
mergeTemplate( template, context, response );
-
- /*
- * call cleanup routine to let a derived class do some cleanup
- */
-
- requestCleanup( request, response, context );
}
catch (Exception e)
{
@@ -425,12 +418,21 @@
error( request, response, e);
}
+ finally
+ {
+ /*
+ * call cleanup routine to let a derived class do some cleanup
+ */
+
+ requestCleanup( 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
+ * A cleanup routine which is called at the end of the [EMAIL PROTECTED]
+ * #doRequest(HttpServletRequest, HttpServletResponse)}
+ * processing sequence, allowing a derived class to do resource
+ * cleanup or other end of process cycle tasks.
*
* @param request servlet request from client
* @param response servlet reponse
@@ -455,6 +457,8 @@
{
ServletOutputStream output = response.getOutputStream();
VelocityWriter vw = null;
+ // ASSUMPTION: response.setContentType() has been called.
+ String encoding = response.getCharacterEncoding();
try
{
@@ -462,14 +466,16 @@
if (vw == null)
{
- vw = new VelocityWriter( new OutputStreamWriter(output, encoding),
4*1024, true);
+ vw = new VelocityWriter(new OutputStreamWriter(output,
+ encoding),
+ 4 * 1024, true);
}
else
{
vw.recycle(new OutputStreamWriter(output, encoding));
}
- template.merge( context, vw);
+ template.merge(context, vw);
}
finally
{
@@ -502,22 +508,51 @@
}
/**
- * Sets the content type of the response. This is available to be overriden
- * by a derived class.
- *
- * The default implementation is :
- *
- * response.setContentType( defaultContentType );
- *
- * where defaultContentType is set to the value of the default.contentType
- * property, or "text/html" if that is not set.
+ * Sets the content type of the response, defaulting to [EMAIL PROTECTED]
+ * #defaultContentType} if not overriden. Delegates to [EMAIL PROTECTED]
+ * #chooseCharacterEncoding(HttpServletRequest)} to select the
+ * appropriate character encoding.
+ *
+ * @param request The servlet request from the client.
+ * @param response The servlet reponse to the client.
+ */
+ protected void setContentType(HttpServletRequest request,
+ HttpServletResponse response)
+ {
+ String contentType = defaultContentType;
+ int index = contentType.lastIndexOf(';') + 1;
+ if (0 <= index || (index < contentType.length() &&
+ contentType.indexOf("charset", index) == -1))
+ {
+ // Append the character encoding which we'd like to use.
+ String encoding = chooseCharacterEncoding(request);
+ //System.out.println("Chose output encoding of '" +
+ // encoding + '\'');
+ if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding))
+ {
+ contentType += "; charset=" + encoding;
+ }
+ }
+ response.setContentType(contentType);
+ //System.out.println("Response Content-Type set to '" +
+ // contentType + '\'');
+ }
+
+ /**
+ * Chooses the output character encoding to be used as the value
+ * for the "charset=" portion of the HTTP Content-Type header (and
+ * thus returned by <code>response.getCharacterEncoding()</code>).
+ * Called by [EMAIL PROTECTED] #setContentType(HttpServletRequest,
+ * HttpServletResponse)} if an encoding isn't already specified by
+ * Content-Type. By default, chooses the value of
+ * RuntimeSingleton's <code>output.encoding</code> property.
*
- * @param request servlet request from client
- * @param response servlet reponse to client
+ * @param request The servlet request from the client.
*/
- protected void setContentType( HttpServletRequest request, HttpServletResponse
response )
+ protected String chooseCharacterEncoding(HttpServletRequest request)
{
- response.setContentType( defaultContentType );
+ return RuntimeSingleton.getString(RuntimeConstants.OUTPUT_ENCODING,
+ DEFAULT_OUTPUT_ENCODING);
}
/**
@@ -673,7 +708,7 @@
html.append("<html>");
html.append("<title>Error</title>");
html.append("<body bgcolor=\"#ffffff\">");
- html.append("<h2>VelocityServlet : Error processing the template</h2>");
+ html.append("<h2>VelocityServlet: Error processing the template</h2>");
html.append("<pre>");
String why = cause.getMessage();
if (why != null && why.trim().length() > 0)
1.29 +12 -0 jakarta-velocity/build/testcases.xml
Index: testcases.xml
===================================================================
RCS file: /home/cvs/jakarta-velocity/build/testcases.xml,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -u -r1.28 -r1.29
--- testcases.xml 25 Mar 2002 00:49:22 -0000 1.28
+++ testcases.xml 31 Aug 2003 18:09:58 -0000 1.29
@@ -72,6 +72,7 @@
test-texen,
test-texen-classpath,
test-misc,
+ test-servlet,
test-parser
"/>
@@ -282,6 +283,17 @@
</classpath>
</java>
</target>
+
+ <target name="test-servlet">
+ <echo message="Running VelocityServlet tests..."/>
+
+ <java classname="${velocity.test.runner}" fork="yes"
failonerror="${testbed.failonerror}">
+ <arg value="org.apache.velocity.test.VelocityServletTest"/>
+ <classpath>
+ <path refid="classpath"/>
+ </classpath>
+ </java>
+ </target>
<!-- ================================================================ -->
<!-- T E X E N T E S T -->
1.1
jakarta-velocity/src/java/org/apache/velocity/test/VelocityServletTest.java
Index: VelocityServletTest.java
===================================================================
package org.apache.velocity.test;
/*
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution, if
* any, must include the following acknowlegement:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowlegement may appear in the software itself,
* if and wherever such third-party acknowlegements normally appear.
*
* 4. The names "The Jakarta Project", "Velocity", and "Apache Software
* Foundation" must not be used to endorse or promote products derived
* from this software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache"
* nor may "Apache" appear in their names without prior written
* permission of the Apache Group.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import java.io.InputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.Properties;
import javax.servlet.RequestDispatcher;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.RuntimeSingleton;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.servlet.VelocityServlet;
import junit.framework.TestCase;
/**
* Tests our VelocityServlet implementation.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Daniel Rall</a>
*/
public class VelocityServletTest extends TestCase
{
/**
* Default constructor.
*/
public VelocityServletTest()
{
super("VelocityServletTest");
}
public static junit.framework.Test suite ()
{
return new VelocityServletTest();
}
/**
* Runs the test.
*/
public void runTest()
{
/*
* Assure we have the encoding we think we should.
*/
MockVelocityServlet servlet = new MockVelocityServlet();
try
{
servlet.init(new MockServletConfig());
}
catch (ServletException e)
{
e.printStackTrace();
}
System.out.println(RuntimeConstants.OUTPUT_ENCODING + "=" +
RuntimeSingleton.getProperty
(RuntimeConstants.OUTPUT_ENCODING));
HttpServletResponse res = new MockHttpServletResponse();
servlet.visibleSetContentType(null, res);
assertEquals("Character encoding not set to UTF-8",
"UTF-8", res.getCharacterEncoding());
}
class MockVelocityServlet extends VelocityServlet
{
void visibleSetContentType(HttpServletRequest req,
HttpServletResponse res)
{
setContentType(req, res);
}
protected Properties loadConfiguration(ServletConfig config)
throws IOException
{
Properties p = new Properties();
p.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
return p;
}
public ServletConfig getServletConfig()
{
return new MockServletConfig();
}
}
static class MockServletConfig implements ServletConfig
{
public String getInitParameter(String ignored)
{
return null;
}
public Enumeration getInitParameterNames()
{
return null;
}
public ServletContext getServletContext()
{
return new MockServletContext();
}
public String getServletName()
{
return "VelocityServlet";
}
}
static class MockServletContext implements ServletContext
{
public Object getAttribute(String ignored)
{
return null;
}
public Enumeration getAttributeNames()
{
return null;
}
public ServletContext getContext(String ignored)
{
return this;
}
public String getInitParameter(String ignored)
{
return null;
}
public Enumeration getInitParameterNames()
{
return null;
}
public int getMajorVersion()
{
return -1;
}
public String getMimeType(String ignored)
{
return null;
}
public int getMinorVersion()
{
return -1;
}
public RequestDispatcher getNamedDispatcher(String ignored)
{
return null;
}
public String getRealPath(String ignored)
{
return null;
}
public RequestDispatcher getRequestDispatcher(String ignored)
{
return null;
}
public URL getResource(String ignored)
throws MalformedURLException
{
return null;
}
public InputStream getResourceAsStream(String ignored)
{
return null;
}
public String getServerInfo()
{
return "Velocity Test Suite";
}
public Servlet getServlet(String ignored)
throws ServletException
{
return null;
}
public Enumeration getServletNames()
{
return null;
}
public Enumeration getServlets()
{
return null;
}
public void log(Exception e, String msg)
{
}
public void log(String msg)
{
}
public void log(String msg, Throwable t)
{
}
public void removeAttribute(String name)
{
}
public void setAttribute(String name, Object value)
{
}
}
static class MockHttpServletResponse implements HttpServletResponse
{
private String encoding;
// ---- ServletResponse implementation -----------------------------
public void flushBuffer() throws IOException
{
}
public int getBufferSize()
{
return -1;
}
public String getCharacterEncoding()
{
return (encoding != null ? encoding : "ISO-8859-1");
}
public java.util.Locale getLocale()
{
return null;
}
public javax.servlet.ServletOutputStream getOutputStream()
throws IOException
{
return null;
}
public java.io.PrintWriter getWriter() throws IOException
{
return null;
}
public boolean isCommitted()
{
return false;
}
public void reset()
{
}
public void setBufferSize(int i)
{
}
public void setContentLength(int i)
{
}
/**
* Records the character encoding.
*/
public void setContentType(String contentType)
{
if (contentType != null)
{
int index = contentType.lastIndexOf(';') + 1;
if (0 <= index || index < contentType.length())
{
index = contentType.indexOf("charset=", index);
if (index != -1)
{
index += 8;
this.encoding = contentType.substring(index).trim();
}
}
}
}
public void setLocale(java.util.Locale l)
{
}
// ---- HttpServletResponse implementation -------------------------
public void addCookie(javax.servlet.http.Cookie c)
{
}
public void addDateHeader(String s, long l)
{
}
public void addHeader(String name, String value)
{
}
public void addIntHeader(String name, int value)
{
}
public boolean containsHeader(String name)
{
return false;
}
public String encodeRedirectURL(String url)
{
return url;
}
public String encodeRedirectUrl(String url)
{
return url;
}
public String encodeURL(String url)
{
return url;
}
public String encodeUrl(String url)
{
return url;
}
public void sendError(int i) throws IOException
{
}
public void sendError(int i, String s) throws IOException
{
}
public void sendRedirect(String s) throws IOException
{
}
public void setDateHeader(String s, long l)
{
}
public void setHeader(String name, String value)
{
}
public void setIntHeader(String s, int i)
{
}
public void setStatus(int i)
{
}
public void setStatus(int i , String s)
{
}
}
}
1.90 +6 -0 jakarta-velocity/xdocs/changes.xml
Index: changes.xml
===================================================================
RCS file: /home/cvs/jakarta-velocity/xdocs/changes.xml,v
retrieving revision 1.89
retrieving revision 1.90
diff -u -u -r1.89 -r1.90
--- changes.xml 23 Aug 2003 00:22:11 -0000 1.89
+++ changes.xml 31 Aug 2003 18:09:59 -0000 1.90
@@ -23,6 +23,12 @@
<ul>
<li>
+Added support for dynamic selection of output character encoding to
+VelocityServlet. By default, the selected encoding is the value of
+the output.encoding Velocity property, but can be made dynamic by
+overriding the new chooseCharacterEncoding() method. (dlr)
+</li>
+<li>
Bill Boland pointed out that VelocityServlet's pooling of
VelocityWriter was preventing the underlying OutputStreamWriter from
being garbage collected. This was fixed by clearing the
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]