Deprecation begone!

git-svn-id: https://samskivert.googlecode.com/svn/trunk@2138 6335cc39-0255-0410-8fd6-9bcaacd3b74c
This commit is contained in:
mdb
2007-07-25 23:30:07 +00:00
parent 023384ead1
commit e021e82865
22 changed files with 398 additions and 282 deletions
+1 -3
View File
@@ -57,8 +57,7 @@
<!-- build the java class files -->
<target name="compile" depends="prepare,compute-builds">
<javac srcdir="${src.dir}" destdir="${deploy.dir}/classes" includeAntRuntime="false"
debug="on" optimize="${build.optimize}" deprecation="off"
source="1.5" target="1.5" encoding="utf-8">
debug="on" optimize="${build.optimize}" source="1.5" target="1.5" encoding="utf-8">
<classpath refid="classpath"/>
<exclude name="com/samskivert/io/**" unless="build.io"/>
<exclude name="com/samskivert/jdbc/**" unless="build.jdbc"/>
@@ -73,7 +72,6 @@
<exclude name="com/samskivert/xml/**" unless="build.xml"/>
<compilerarg value="-Xlint"/>
<compilerarg value="-Xlint:-serial"/>
<compilerarg value="-Xlint:-deprecation"/>
</javac>
</target>
@@ -57,23 +57,9 @@ public interface DatabaseLiaison
*/
public boolean isTransientException (SQLException sqe);
/**
* Returns the value of an <code>AUTO_INCREMENT</code> column for the last row insertion. This
* is MySQL specific, but exists here for now until we sort out a general purpose mechanism for
* assigning unique ids.
*
* Note: More general purpose: {@link #lastInsertedId(Connection, String, String)
*
* @return the most recent ID generated by an insert into an <code>AUTO_INCREMENT</code> table
* or -1 if it could not be obtained.
*/
@Deprecated
public int lastInsertedId (Connection conn)
throws SQLException;
/**
* This method initializes the column value auto-generator described in {@link
* #lastInsertedId(Connection, String, String)}.
* #lastInsertedId}.
*/
public void initializeGenerator (
Connection conn, String table, String column, int first, int step)
@@ -47,7 +47,7 @@ public class DefaultLiaison extends BaseLiaison
return false;
}
// from DatabaseLiaison
@SuppressWarnings("deprecation") // from DatabaseLiaison
public int lastInsertedId (Connection conn) throws SQLException
{
return -1;
@@ -65,7 +65,7 @@ public abstract class JORARepository extends SimpleRepository
throws SQLException, PersistenceException
{
table.insert(conn, object);
return liaison.lastInsertedId(conn);
return liaison.lastInsertedId(conn, table.getName(), "TODO");
}
});
}
@@ -265,7 +265,7 @@ public abstract class JORARepository extends SimpleRepository
{
if (table.update(conn, object) == 0) {
table.insert(conn, object);
return liaison.lastInsertedId(conn);
return liaison.lastInsertedId(conn, table.getName(), "TODO");
}
return -1;
}
+3 -10
View File
@@ -47,16 +47,9 @@ public class MySQLLiaison extends BaseLiaison
public boolean isTransientException (SQLException sqe)
{
String msg = sqe.getMessage();
return (msg != null &&
(msg.indexOf("Lost connection") != -1 ||
msg.indexOf("link failure") != -1 ||
msg.indexOf("Broken pipe") != -1));
}
// from DatabaseLiaison
public int lastInsertedId (Connection conn) throws SQLException
{
return lastInsertedId(conn, null, null);
return (msg != null && (msg.indexOf("Lost connection") != -1 ||
msg.indexOf("link failure") != -1 ||
msg.indexOf("Broken pipe") != -1));
}
// from DatabaseLiaison
@@ -49,13 +49,6 @@ public class PostgreSQLLiaison extends BaseLiaison
msg.indexOf("An I/O error occured while sending to the backend") != -1);
}
// from DatabaseLiaison
public int lastInsertedId (Connection conn) throws SQLException
{
throw new SQLException(
"No backwards-compatible lastInsertedId() support for PostgreSQL in this code.");
}
// from DatabaseLiaison
public int lastInsertedId (Connection conn, String table, String column) throws SQLException
{
@@ -27,6 +27,7 @@ import java.sql.SQLException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.samskivert.io.PersistenceException;
import com.samskivert.util.ArrayUtil;
@@ -50,7 +51,7 @@ import com.samskivert.jdbc.depot.expression.ValueExp;
* Provides a base for classes that provide access to persistent objects. Also defines the
* mechanism by which all persistent queries and updates are routed through the distributed cache.
*/
public class DepotRepository
public abstract class DepotRepository
{
/**
* Creates a repository with the supplied connection provider and its own private persistence
@@ -59,6 +60,7 @@ public class DepotRepository
protected DepotRepository (ConnectionProvider conprov)
{
_ctx = new PersistenceContext(getClass().getName(), conprov);
_ctx.repositoryCreated(this);
}
/**
@@ -67,8 +69,14 @@ public class DepotRepository
protected DepotRepository (PersistenceContext context)
{
_ctx = context;
_ctx.repositoryCreated(this);
}
/**
* Adds the persistent classes used by this repository to the supplied set.
*/
protected abstract void getManagedRecords (Set<Class<? extends PersistentRecord>> classes);
/**
* Loads the persistent object that matches the specified primary key.
*/
@@ -20,8 +20,11 @@
package com.samskivert.jdbc.depot;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -393,6 +396,29 @@ public class PersistenceContext
listenerSet.add(listener);
}
/**
* Iterates over all {@link PersistentRecord} classes managed by this context and initializes
* their {@link DepotMarshaller}. This forces migrations to run and the database schema to be
* created.
*/
public void initializeManagedRecords ()
throws PersistenceException
{
for (Class<? extends PersistentRecord> rclass : _managedRecords) {
getMarshaller(rclass);
}
}
/**
* Called when a depot repository is created. We register all persistent record classes used by
* the repository so that systems that desire it can force the resolution of all database
* tables rather than allowing resolution to happen on demand.
*/
protected void repositoryCreated (DepotRepository repo)
{
repo.getManagedRecords(_managedRecords);
}
/**
* Looks up and creates, but does not initialize, the marshaller for the specified Entity
* type.
@@ -474,4 +500,16 @@ public class PersistenceContext
protected Map<Class<?>, DepotMarshaller<?>> _marshallers =
new HashMap<Class<?>, DepotMarshaller<?>>();
/**
* The set of persistent records for which this context is responsible. This data is used by
* {@link #initializeManagedRecords} to force migration/schema initialization.
*/
protected Set<Class<? extends PersistentRecord>> _managedRecords =
new HashSet<Class<? extends PersistentRecord>>();
/**
* A collection of all {@link PersistenceContext} objects in existence.
*/
protected static List<PersistenceContext> _contexts = new ArrayList<PersistenceContext>();
}
@@ -22,10 +22,12 @@ package com.samskivert.jdbc.depot.tests;
import java.sql.Date;
import java.sql.Timestamp;
import java.util.Set;
import com.samskivert.jdbc.ConnectionProvider;
import com.samskivert.jdbc.StaticConnectionProvider;
import com.samskivert.jdbc.depot.DepotRepository;
import com.samskivert.jdbc.depot.PersistentRecord;
/**
* A test tool for the Depot repository services.
@@ -59,4 +61,10 @@ public class TestRepository extends DepotRepository
{
super(conprov);
}
@Override // from DepotRepository
protected void getManagedRecords (Set<Class<? extends PersistentRecord>> classes)
{
classes.add(TestRecord.class);
}
}
@@ -254,7 +254,7 @@ public class JDBCTableSiteIdentifier implements SiteIdentifier
if (1 != stmt.executeUpdate()) {
throw new PersistenceException("Not inserted " + site);
}
site.siteId = liaison.lastInsertedId(conn);
site.siteId = liaison.lastInsertedId(conn, "sites", "siteId");
} finally {
JDBCUtil.close(stmt);
@@ -420,7 +420,7 @@ public class UserRepository extends JORARepository
try {
_utable.insert(conn, user);
// update the userid now that it's known
user.userId = liaison.lastInsertedId(conn);
user.userId = liaison.lastInsertedId(conn, _utable.getName(), "userId");
// nothing to return
return null;
@@ -34,6 +34,7 @@ public class SmartPolygon extends Polygon
* Returns the internally cached bounds rectangle for this polygon.
* <em>Don't modify it!</em>
*/
@SuppressWarnings("deprecation")
public Rectangle getBoundingBox ()
{
return (bounds == null) ? super.getBoundingBox() : bounds;
@@ -553,10 +553,11 @@ public class TGraphics2D extends Graphics2D
return _primary.toString();
}
@SuppressWarnings("deprecation")
public Rectangle getClipRect ()
{
// getClipRect is deprecated, but getClipBounds is the new way
// to do the same thing. We call that to avoid deprecation warnings.
// getClipRect is deprecated, but getClipBounds is the new way to do the same thing. We
// call that to avoid deprecation warnings.
return _primary.getClipBounds();
}
@@ -62,6 +62,6 @@ public class AdjustTestApp
frame.getContentPane().add(RuntimeAdjust.createAdjustEditor(), BorderLayout.CENTER);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.show();
frame.setVisible(true);
}
}
@@ -143,7 +143,7 @@ public class LabelDemo extends JPanel
LabelDemo demo = new LabelDemo();
frame.getContentPane().add(demo);
frame.pack();
frame.show();
frame.setVisible(true);
}
protected Label[] _labels = new Label[10];
@@ -59,6 +59,6 @@ public class TestComboButtonBox
ComboButtonBox box = new ComboButtonBox(ComboButtonBox.HORIZONTAL, model);
frame.getContentPane().add(box);
frame.pack();
frame.show();
frame.setVisible(true);
}
}
@@ -3,7 +3,7 @@
//
// samskivert library - useful routines for java programs
// Copyright (C) 2001-2007 Michael Bayne
//
//
// This library is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation; either version 2.1 of the License, or
@@ -21,26 +21,33 @@
package com.samskivert.velocity;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Properties;
import java.util.logging.Level;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.velocity.Template;
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.runtime.RuntimeSingleton;
import org.apache.velocity.servlet.VelocityServlet;
import org.apache.velocity.util.SimplePool;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.event.EventCartridge;
import org.apache.velocity.app.event.MethodExceptionEventHandler;
import com.samskivert.Log;
import com.samskivert.servlet.HttpErrorException;
import com.samskivert.servlet.MessageManager;
import com.samskivert.servlet.RedirectException;
@@ -51,46 +58,39 @@ import com.samskivert.servlet.util.FriendlyException;
import com.samskivert.util.ConfigUtil;
import com.samskivert.util.StringUtil;
import static com.samskivert.Log.log;
/**
* The dispatcher servlet builds upon Velocity's architecture. It does so
* in the following ways:
* The dispatcher servlet builds upon Velocity's architecture. It does so in the following ways:
*
* <ul>
* <li> It defines the notion of a logic object which populates the
* context with data to be used to satisfy a particular request. The logic
* is not a servlet and is therefore limited in what it can do while
* populating data. Experience dictates that ultimate flexibility leads to
* bad design decisions and that this is a place where that sort of thing
* can be comfortably nipped in the bud. <br><br>
* <ul> <li> It defines the notion of a logic object which populates the context with data to be
* used to satisfy a particular request. The logic is not a servlet and is therefore limited in
* what it can do while populating data. Experience dictates that ultimate flexibility leads to bad
* design decisions and that this is a place where that sort of thing can be comfortably nipped in
* the bud. <br><br>
*
* <li> It allows template files to be referenced directly in the URL
* while maintaining the ability to choose a cobranded template based on
* information in the request. The URI is mapped to a servlet based on
* some simple mapping rules. This provides template designers with a
* clearer understanding of the structure of a web application as well as
* with an easy way to test their templates in the absence of an
* associated servlet. <br><br>
* <li> It allows template files to be referenced directly in the URL while maintaining the ability
* to choose a cobranded template based on information in the request. The URI is mapped to a
* servlet based on some simple mapping rules. This provides template designers with a clearer
* understanding of the structure of a web application as well as with an easy way to test their
* templates in the absence of an associated servlet. <br><br>
*
* <li> It provides a common error handling paradigm that simplifies the
* task of authoring web applications.
* <li> It provides a common error handling paradigm that simplifies the task of authoring web
* applications.
* </ul>
*
* <p><b>URI to servlet mapping</b><br>
* The mapping process allows the Velocity framework to be invoked for all
* requests ending in a particular file extension (usually
* <code>.wm</code>). It is necessary to instruct your servlet engine of
* choice to invoke the <code>DispatcherServlet</code> for all requests
* ending in that extension. For Apache/JServ this looks something like
* this:
* <p><b>URI to servlet mapping</b><br> The mapping process allows the Velocity framework to be
* invoked for all requests ending in a particular file extension (usually <code>.wm</code>). It is
* necessary to instruct your servlet engine of choice to invoke the <code>DispatcherServlet</code>
* for all requests ending in that extension. For Apache/JServ this looks something like this:
*
* <pre>
* ApJServAction .wm /servlets/com.samskivert.velocity.Dispatcher
* </pre>
*
* The request URI then defines the path of the template that will be used
* to satisfy the request. To understand how code is selected to go along
* with the request, let's look at an example. Consider the following
* configuration:
* The request URI then defines the path of the template that will be used to satisfy the
* request. To understand how code is selected to go along with the request, let's look at an
* example. Consider the following configuration:
*
* <pre>
* applications=whowhere
@@ -98,48 +98,44 @@ import com.samskivert.util.StringUtil;
* whowhere.base_pkg=whowhere.logic
* </pre>
*
* This defines an application identified as <code>whowhere</code>. An
* application is defined by three parameters, the application identifier,
* the <code>base_uri</code>, and the <code>base_pkg</code>. The
* <code>base_uri</code> defines the prefix shared by all pages served by
* the application and which serves to identify which application to
* invoke when processing a request. The <code>base_pkg</code> is used to
* construct the logic classname based on the URI and the
* <code>base_uri</code> parameter.
* This defines an application identified as <code>whowhere</code>. An application is defined by
* three parameters, the application identifier, the <code>base_uri</code>, and the
* <code>base_pkg</code>. The <code>base_uri</code> defines the prefix shared by all pages served
* by the application and which serves to identify which application to invoke when processing a
* request. The <code>base_pkg</code> is used to construct the logic classname based on the URI and
* the <code>base_uri</code> parameter.
*
* <p> Now let's look at a sample request to determine how the logic
* classname is resolved. Consider the following request URI:
* <p> Now let's look at a sample request to determine how the logic classname is
* resolved. Consider the following request URI:
*
* <pre>
* /whowhere/view/trips.wm
* </pre>
*
* It begins with <code>/whowhere</code> which tells the dispatcher that
* it's part of the <code>whowhere</code> application. That application's
* <code>base_uri</code> is then stripped from the URI leaving
* <code>/view/trips.wm</code>. The slashes are converted into periods to
* map directories to packages, giving us <code>view.trips.wm</code>.
* Finally, the <code>base_pkg</code> is prepended and the trailing
* <code>.wm</code> extension removed.
* It begins with <code>/whowhere</code> which tells the dispatcher that it's part of the
* <code>whowhere</code> application. That application's <code>base_uri</code> is then stripped
* from the URI leaving <code>/view/trips.wm</code>. The slashes are converted into periods to map
* directories to packages, giving us <code>view.trips.wm</code>. Finally, the
* <code>base_pkg</code> is prepended and the trailing <code>.wm</code> extension removed.
*
* <p> Thus the class invoked to populate the context for this request is
* <code>whowhere.servlets.view.trips</code> (note that the classname
* <em>is</em> lowercase which is an intentional choice in resolving
* conflicting recommendations that classnames should always start with a
* capital letter and URLs should always be lowercase).
* <code>whowhere.servlets.view.trips</code> (note that the classname <em>is</em> lowercase which
* is an intentional choice in resolving conflicting recommendations that classnames should always
* start with a capital letter and URLs should always be lowercase).
*
* <p> The template used to generate the result is loaded based on the
* full URI, essentially with a call to
* <code>getTemplate("/whowhere/view/trips.wm")</code> in this example.
* This is the place where more sophisticated cobranding support could be
* inserted in the future (ie. if I ever want to use this to develop a
* cobranded web site).
* <p> The template used to generate the result is loaded based on the full URI, essentially with a
* call to <code>getTemplate("/whowhere/view/trips.wm")</code> in this example. This is the place
* where more sophisticated cobranding support could be inserted in the future (ie. if I ever want
* to use this to develop a cobranded web site).
*
* @see Logic
*/
public class DispatcherServlet extends VelocityServlet
public class DispatcherServlet extends HttpServlet
implements MethodExceptionEventHandler
{
/** The HTTP content type context key. */
public static final String CONTENT_TYPE = "default.contentType";
/**
* Performs various initialization.
*/
@@ -148,29 +144,6 @@ public class DispatcherServlet extends VelocityServlet
{
super.init(config);
// determine the character set we'll use
_charset = config.getInitParameter(CHARSET_KEY);
if (_charset == null) {
_charset = "UTF-8";
}
}
/**
* Clean up after ourselves and our application.
*/
public void destroy ()
{
super.destroy();
// shutdown our application
_app.shutdown();
}
/**
* Initialize ourselves and our application.
*/
protected void initVelocity (ServletConfig config)
throws ServletException
{
// load up our application configuration
try {
String appcl = config.getInitParameter(APP_CLASS_KEY);
@@ -187,26 +160,62 @@ public class DispatcherServlet extends VelocityServlet
StringUtil.isBlank(logicPkg) ? "" : logicPkg);
} catch (Throwable t) {
Log.warning("Error instantiating application.");
Log.logStackTrace(t);
throw new ServletException("Error instantiating Application: " + t, t);
}
// now let velocity initialize itself
super.initVelocity(config);
try {
Velocity.init(loadConfiguration(config));
} catch (Exception e) {
throw new ServletException("Error initializing Velocity: " + e, e);
}
_defaultContentType = RuntimeSingleton.getString(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
// determine the character set we'll use
_charset = config.getInitParameter(CHARSET_KEY);
if (_charset == null) {
_charset = "UTF-8";
}
}
/**
* We load our velocity properties from the classpath rather than from
* a file.
* Handles HTTP <code>GET</code> requests by calling {@link #doRequest()}.
*/
public void doGet (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doRequest(request, response);
}
/**
* Handles HTTP <code>POST</code> requests by calling {@link #doRequest()}.
*/
public void doPost (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doRequest(request, response);
}
/**
* Clean up after ourselves and our application.
*/
public void destroy ()
{
super.destroy();
// shutdown our application
_app.shutdown();
}
/**
* We load our velocity properties from the classpath rather than from a file.
*/
protected Properties loadConfiguration (ServletConfig config)
throws IOException
{
String propsPath = config.getInitParameter(INIT_PROPS_KEY);
if (propsPath == null) {
throw new IOException(INIT_PROPS_KEY + " must point to " +
"the velocity properties file in " +
"the servlet configuration.");
throw new IOException(INIT_PROPS_KEY + " must point to the velocity properties file " +
"in the servlet configuration.");
}
// config util loads properties files from the classpath
@@ -230,16 +239,15 @@ public class DispatcherServlet extends VelocityServlet
if (props.getProperty("file.resource.loader.path") == null) {
SiteResourceLoader siteLoader = _app.getSiteResourceLoader();
if (siteLoader != null) {
Log.info("Velocity loading templates from site loader.");
log.info("Velocity loading templates from site loader.");
props.setProperty(RuntimeSingleton.RESOURCE_MANAGER_CLASS,
SiteResourceManager.class.getName());
_usingSiteLoading = true;
} else {
// otherwise use a servlet context resource loader
Log.info("Velocity loading templates from servlet context.");
props.setProperty(
RuntimeSingleton.RESOURCE_MANAGER_CLASS,
ServletContextResourceManager.class.getName());
log.info("Velocity loading templates from servlet context.");
props.setProperty(RuntimeSingleton.RESOURCE_MANAGER_CLASS,
ServletContextResourceManager.class.getName());
}
}
@@ -247,21 +255,18 @@ public class DispatcherServlet extends VelocityServlet
props.setProperty("userdirective", ImportDirective.class.getName());
// configure the servlet context logger
props.setProperty(RuntimeSingleton.RUNTIME_LOG_LOGSYSTEM_CLASS,
ServletContextLogger.class.getName());
props.put(RuntimeSingleton.RUNTIME_LOG_LOGSYSTEM, new ServletContextLogger());
// now return our augmented properties
return props;
}
/**
* Loads up the template appropriate for this request, locates and
* invokes any associated logic class and finally returns the prepared
* template which will be merged with the prepared context.
* Loads up the template appropriate for this request, locates and invokes any associated logic
* class and finally returns the prepared template which will be merged with the prepared
* context.
*/
public Template handleRequest (HttpServletRequest req,
HttpServletResponse rsp,
Context ctx)
public Template handleRequest (HttpServletRequest req, HttpServletResponse rsp, Context ctx)
throws Exception
{
InvocationContext ictx = (InvocationContext)ctx;
@@ -416,9 +421,8 @@ public class DispatcherServlet extends VelocityServlet
public Object methodException (Class clazz, String method, Exception e)
throws Exception
{
Log.warning("Exception [class=" + clazz.getName() +
", method=" + method + "].");
Log.logStackTrace(e);
log.log(Level.WARNING, "Exception [class=" + clazz.getName() +
", method=" + method + "].", e);
return "";
}
@@ -435,19 +439,67 @@ public class DispatcherServlet extends VelocityServlet
}
/**
* We override this to create a context of our own devising.
* Handles all requests (by default).
*
* @param request HttpServletRequest object containing client request.
* @param response HttpServletResponse object for the response.
*/
protected Context createContext (HttpServletRequest req,
HttpServletResponse rsp)
protected void doRequest (HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
return new InvocationContext(req, rsp);
Context context = null;
try {
context = new InvocationContext(request, response);
setContentType(request, response);
Template template = handleRequest(request, response, context);
if (template != null) {
mergeTemplate(template, context, response);
}
} catch (Exception e) {
log.log(Level.WARNING, "doRequest failed [uri=" + request.getRequestURI() + "].", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
}
}
/**
* This method is called to select the appropriate template for this
* request. The default implementation simply loads the template using
* Velocity's default template loading services based on the URI
* provided in the request.
* Sets the content type of the response, defaulting to {@link #defaultContentType} if not
* overriden. Delegates to {@link #chooseCharacterEncoding(HttpServletRequest)} to select the
* appropriate character encoding.
*/
protected void setContentType (HttpServletRequest request, HttpServletResponse response)
{
String contentType = _defaultContentType;
int index = contentType.lastIndexOf(';') + 1;
if (index <= 0 || (index < contentType.length() &&
contentType.indexOf("charset", index) == -1)) {
// append the character encoding which we'd like to use
String encoding = chooseCharacterEncoding(request);
if (!DEFAULT_OUTPUT_ENCODING.equalsIgnoreCase(encoding)) {
contentType += "; charset=" + encoding;
}
}
response.setContentType(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 {@link #setContentType} if an
* encoding isn't already specified by Content-Type. By default, chooses the value of
* RuntimeSingleton's <code>output.encoding</code> property.
*/
protected String chooseCharacterEncoding (HttpServletRequest request)
{
return RuntimeSingleton.getString(
RuntimeConstants.OUTPUT_ENCODING, DEFAULT_OUTPUT_ENCODING);
}
/**
* This method is called to select the appropriate template for this request. The default
* implementation simply loads the template using Velocity's default template loading services
* based on the URI provided in the request.
*
* @param ctx The context of this request.
*
@@ -458,20 +510,62 @@ public class DispatcherServlet extends VelocityServlet
{
String path = ctx.getRequest().getServletPath();
if (_usingSiteLoading) {
// if we're using site resource loading, we need to prefix the path
// with the site identifier
// if we're using site resource loading, we need to prefix the path with the site
// identifier
path = siteId + ":" + path;
}
// Log.info("Loading template [path=" + path + "].");
// log.info("Loading template [path=" + path + "].");
return RuntimeSingleton.getTemplate(path);
}
/**
* This method is called to select the appropriate logic for this
* request URI.
* Merges the template with the context.
*
* @return The logic to be used in generating the response or null if
* no logic could be matched.
* @param template template object returned by the {@link #handleRequest} method.
* @param context context created by the {@link #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();
// ASSUMPTION: response.setContentType() has been called.
String encoding = response.getCharacterEncoding();
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 {
if (vw != null) {
try {
// flush and put back into the pool don't close to allow us to play nicely with
// others.
vw.flush();
} catch (IOException e) {
// do nothing
}
// Clear the VelocityWriter's reference to its internal OutputStreamWriter to allow
// the latter to be GC'd while vw is pooled.
vw.recycle(null);
_writerPool.put(vw);
}
}
}
/**
* This method is called to select the appropriate logic for this request URI.
*
* @return The logic to be used in generating the response or null if no logic could be
* matched.
*/
protected Logic resolveLogic (String path)
{
@@ -488,14 +582,12 @@ public class DispatcherServlet extends VelocityServlet
// nothing interesting to report
} catch (Throwable t) {
Log.warning("Unable to instantiate logic for application " +
"[path=" + path + ", lclass=" + lclass + "].");
Log.logStackTrace(t);
log.log(Level.WARNING, "Unable to instantiate logic for application [path=" + path +
", lclass=" + lclass + "].", t);
}
// if something failed, use a dummy in it's place so that we
// don't sit around all day freaking out about our inability
// to instantiate the proper logic class
// if something failed, use a dummy in it's place so that we don't sit around all day
// freaking out about our inability to instantiate the proper logic class
if (logic == null) {
logic = new DummyLogic();
}
@@ -519,13 +611,20 @@ public class DispatcherServlet extends VelocityServlet
/** Set to true if we're using the {@link SiteResourceLoader}. */
protected boolean _usingSiteLoading;
/** Our default content type. */
protected String _defaultContentType;
/** A pool of VelocityWriter instances. */
protected static SimplePool _writerPool = new SimplePool(40);
/** Describes the location of our properties. */
protected static final String INIT_PROPS_KEY = "org.apache.velocity.properties";
/** This is the key used in the context for error messages. */
protected static final String ERROR_KEY = "error";
/**
* This is the key used to store a reference back to the dispatcher
* servlet in our invocation context.
*/
/** This is the key used to store a reference back to the dispatcher servlet in our invocation
* context. */
protected static final String APPLICATION_KEY = "%_app_%";
/** The key used to store the translation tool in the context. */
@@ -551,4 +650,10 @@ public class DispatcherServlet extends VelocityServlet
/** The servlet parameter key specifying the default character set. */
protected static final String CHARSET_KEY = "charset";
/** The default content type for responses. */
protected static final String DEFAULT_CONTENT_TYPE = "text/html";
/** The default encoding for the output stream. */
protected static final String DEFAULT_OUTPUT_ENCODING = "ISO-8859-1";
}
@@ -40,10 +40,9 @@ import com.samskivert.servlet.SiteIdentifier;
import com.samskivert.util.StringUtil;
/**
* Pluggable directive that handles the #import() statement in VTL. Import is
* like #parse() except that it creates a compound key
* (<code>siteId:template_path</code>) based on information from the current
* request when fetching the imported template.
* Pluggable directive that handles the #import() statement in VTL. Import is like #parse() except
* that it creates a compound key (<code>siteId:template_path</code>) based on information from the
* current request when fetching the imported template.
*/
public class ImportDirective extends Directive
{
@@ -73,14 +72,14 @@ public class ImportDirective extends Directive
{
// make sure an argument was supplied to the directive
if (node.getChild(0) == null) {
rsvc.error("#import() error : null argument");
rsvc.getLog().error("#import() error : null argument");
return false;
}
// make sure that argument has a value
Object value = node.getChild(0).value(context);
if (value == null) {
rsvc.error("#import() error : null argument");
rsvc.getLog().error("#import() error : null argument");
return false;
}
@@ -92,9 +91,8 @@ public class ImportDirective extends Directive
int maxlen = rsvc.getInt(
RuntimeConstants.PARSE_DIRECTIVE_MAXDEPTH, 20);
if (templateStack.length >= maxlen) {
rsvc.error("Max recursion depth reached (" + maxlen + "). " +
"File stack: " +
StringUtil.toString(templateStack) + ".");
rsvc.getLog().error("Max recursion depth reached (" + maxlen + "). " +
"File stack: " + StringUtil.toString(templateStack) + ".");
return false;
}
@@ -120,7 +118,7 @@ public class ImportDirective extends Directive
try {
siteId = ((Integer)siteIdVal).intValue();
} catch (Exception e) {
rsvc.error("#import() error: No siteId information in context.");
rsvc.getLog().error("#import() error: No siteId information in context.");
}
path = siteId + ":" + path;
}
@@ -131,22 +129,19 @@ public class ImportDirective extends Directive
t = rsvc.getTemplate(path, encoding);
} catch (ResourceNotFoundException rnfe) {
rsvc.error("#import(): cannot find template '" + path +
"', called from template " +
context.getCurrentTemplateName() +
" at (" + getLine() + ", " + getColumn() + ")");
rsvc.getLog().error("#import(): cannot find template '" + path +
"', called from template " + context.getCurrentTemplateName() +
" at (" + getLine() + ", " + getColumn() + ")");
throw rnfe;
} catch (ParseErrorException pee) {
rsvc.error("#import(): syntax error in #import()-ed template '" +
path + "', called from template " +
context.getCurrentTemplateName() +
" at (" + getLine() + ", " + getColumn() + ")");
rsvc.getLog().error("#import(): syntax error in #import()-ed template '" + path +
"', called from template " + context.getCurrentTemplateName() +
" at (" + getLine() + ", " + getColumn() + ")");
throw pee;
} catch (Exception e) {
rsvc.error("#import(): Error [path=" + path +
", error=" + e + "].");
rsvc.getLog().error("#import(): Error [path=" + path + ", error=" + e + "].");
return false;
}
@@ -156,7 +151,7 @@ public class ImportDirective extends Directive
((SimpleNode)t.getData()).render(context, writer);
} catch (Throwable th) {
rsvc.error("Exception rendering #import(" + path + "): " + th);
rsvc.getLog().error("Exception rendering #import(" + path + "): " + th);
// we want to pass method invocation exceptions through
if (th instanceof MethodInvocationException) {
throw (MethodInvocationException)th;
@@ -23,12 +23,12 @@ package com.samskivert.velocity;
import javax.servlet.ServletContext;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.log.LogSystem;
import org.apache.velocity.runtime.log.LogChute;
/**
* Routes Velocity log messages to the servlet context.
*/
public class ServletContextLogger implements LogSystem
public class ServletContextLogger implements LogChute
{
/**
* Constructs a servlet context logger that will obtain its servlet
@@ -48,22 +48,21 @@ public class ServletContextLogger implements LogSystem
_sctx = sctx;
}
// documentation inherited
// from interface LogChute
public void init (RuntimeServices rsvc)
{
// if we weren't constructed with a servlet context, try to obtain
// one via the application context
if (_sctx == null) {
// first look for the servlet context directly
_sctx = (ServletContext)
rsvc.getApplicationAttribute("ServletContext");
_sctx = (ServletContext)rsvc.getApplicationAttribute("ServletContext");
}
// if that didn't work, look for an application
if (_sctx == null) {
// first look for an application
Application app = (Application)rsvc.getApplicationAttribute(
Application.VELOCITY_ATTR_KEY);
Application app = (Application)
rsvc.getApplicationAttribute(Application.VELOCITY_ATTR_KEY);
if (app != null) {
_sctx = app.getServletContext();
}
@@ -71,22 +70,35 @@ public class ServletContextLogger implements LogSystem
// if we still don't have one, complain
if (_sctx == null) {
rsvc.warn("ServletContextLogger: servlet context was not " +
"supplied. A user of the servlet context logger must " +
"call Velocity.setApplicationAttribute(" +
"\"ServletContext\", getServletContext()).");
rsvc.getLog().warn("ServletContextLogger: servlet context was not supplied. A user " +
"of the servlet context logger must call " +
"Velocity.setApplicationAttribute(\"ServletContext\", " +
"getServletContext()).");
}
}
// documentation inherited
public void logVelocityMessage (int level, String message)
// from interface LogChute
public void log (int level, String message)
{
// log only warning or above for now
if (level >= LogSystem.WARN_ID) {
if (isLevelEnabled(level)) {
_sctx.log(message);
}
}
// from interface LogChute
public void log (int level, String message, Throwable t)
{
if (isLevelEnabled(level)) {
_sctx.log(message, t);
}
}
// from interface LogChute
public boolean isLevelEnabled (int level)
{
return (level >= WARN_ID);
}
/** A reference to our servlet context. */
protected ServletContext _sctx;
}
@@ -29,8 +29,7 @@ import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
/**
* A Velocity resource loader that loads resources from the servlet
* context.
* A Velocity resource loader that loads resources from the servlet context.
*
* @see ServletContext#getResource
* @see ServletContext#getResourceAsStream
@@ -38,17 +37,16 @@ import org.apache.velocity.runtime.resource.loader.ResourceLoader;
public class ServletContextResourceLoader extends ResourceLoader
{
/**
* When used with the default Velocity resource manager, we are
* constructed with our zero-argument constructor and later
* initialized via {@link #init}.
* When used with the default Velocity resource manager, we are constructed with our
* zero-argument constructor and later initialized via {@link #init}.
*/
public ServletContextResourceLoader ()
{
}
/**
* When used with the {@link SiteResourceManager} we are constructed
* with our servlet context reference and not later initialized.
* When used with the {@link SiteResourceManager} we are constructed with our servlet context
* reference and not later initialized.
*/
public ServletContextResourceLoader (ServletContext sctx)
{
@@ -60,22 +58,14 @@ public class ServletContextResourceLoader extends ResourceLoader
*/
public void init (ExtendedProperties config)
{
// there seems to be a tradition of logging this stuff; surely we
// don't want to buck tradition, do we?
rsvc.info("ServletContextResourceLoader: initialization starting.");
// the web framework was kind enough to slip this into the runtime
// instance when it started up
// the web framework was kind enough to slip this into the runtime when it started up
_sctx = (ServletContext)rsvc.getApplicationAttribute("ServletContext");
if (_sctx == null) {
rsvc.warn("ServletContextResourceLoader: servlet context " +
"was not supplied as application context. A " +
"user of the servlet context resource loader " +
"must call Velocity.setApplicationAttribute(" +
"\"ServletContext\", getServletContext()).");
rsvc.getLog().warn("ServletContextResourceLoader: servlet context was not supplied " +
"as application context. A user of the servlet context resource " +
"loader must call Velocity.setApplicationAttribute(" +
"\"ServletContext\", getServletContext()).");
}
rsvc.info("ServletContextResourceLoader : initialization complete.");
}
/**
@@ -31,8 +31,7 @@ import org.apache.velocity.runtime.resource.ResourceManagerImpl;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
/**
* A resource manager implementation for Velocity that loads resources
* from the servlet context.
* A resource manager implementation for Velocity that loads resources from the servlet context.
*/
public class ServletContextResourceManager extends ResourceManagerImpl
{
@@ -40,37 +39,31 @@ public class ServletContextResourceManager extends ResourceManagerImpl
throws Exception
{
super.initialize(rsvc);
rsvc.info("SCRM initializing.");
rsvc.getLog().info("SCRM initializing.");
// the web framework was kind enough to slip this into the runtime
// instance when it started up
Application app = (Application)rsvc.getApplicationAttribute(
Application.VELOCITY_ATTR_KEY);
// the web framework was kind enough to slip this into the runtime when it started up
Application app = (Application)rsvc.getApplicationAttribute(Application.VELOCITY_ATTR_KEY);
if (app == null) {
rsvc.warn("SCRM: No application was initialized. A user of the " +
"servlet context resource manager must ensure that " +
"an application is instantiated and initialized.");
rsvc.getLog().warn("SCRM: No application was initialized. A user of the " +
"servlet context resource manager must ensure that " +
"an application is instantiated and initialized.");
}
// create our resource loader
_contextLoader = new ServletContextResourceLoader(
app.getServletContext());
_contextLoader = new ServletContextResourceLoader(app.getServletContext());
// for now, turn caching on with the expectation that new
// resources of any sort will result in the entire web application
// being reloaded and clearing out the cache
// for now, turn caching on with the expectation that new resources of any sort will result
// in the entire web application being reloaded and clearing out the cache
_contextLoader.setCachingOn(true);
rsvc.info("SCRM initialization complete.");
rsvc.getLog().info("SCRM initialization complete.");
}
protected Resource loadResource(
String resourceName, int resourceType, String encoding)
protected Resource loadResource(String resourceName, int resourceType, String encoding)
throws ResourceNotFoundException, ParseErrorException, Exception
{
// create a blank new resource
Resource resource =
ResourceFactory.getResource(resourceName, resourceType);
Resource resource = ResourceFactory.getResource(resourceName, resourceType);
resource.setRuntimeServices(rsvc);
resource.setName(resourceName);
resource.setEncoding(encoding);
@@ -78,8 +71,7 @@ public class ServletContextResourceManager extends ResourceManagerImpl
resource.setResourceLoader(_contextLoader);
resource.process();
resource.setLastModified(_contextLoader.getLastModified(resource));
resource.setModificationCheckInterval(
_contextLoader.getModificationCheckInterval());
resource.setModificationCheckInterval(_contextLoader.getModificationCheckInterval());
resource.touch();
return resource;
@@ -30,13 +30,15 @@ import org.apache.velocity.runtime.resource.ResourceFactory;
import org.apache.velocity.runtime.resource.ResourceManagerImpl;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
import com.samskivert.Log;
import com.samskivert.servlet.SiteIdentifier;
import com.samskivert.servlet.SiteResourceLoader;
/**
* A resource manager implementation for Velocity that first loads site
* specific resources (via the {@link SiteJarResourceLoader}), but falls back
* to default resources if no site-specific resource loader is available.
* A resource manager implementation for Velocity that first loads site specific resources (via the
* {@link SiteJarResourceLoader}), but falls back to default resources if no site-specific resource
* loader is available.
*/
public class SiteResourceManager extends ResourceManagerImpl
{
@@ -44,16 +46,15 @@ public class SiteResourceManager extends ResourceManagerImpl
throws Exception
{
super.initialize(rsvc);
rsvc.info("SiteResourceManager initializing.");
Log.log.info("SiteResourceManager initializing.");
// the web framework was kind enough to slip this into the runtime
// instance when it started up
// the web framework was kind enough to slip this into the runtime when it started up
Application app = (Application)rsvc.getApplicationAttribute(
Application.VELOCITY_ATTR_KEY);
if (app == null) {
rsvc.warn("SiteResourceManager: No application was initialized. " +
"A user of the site resource manager must ensure that " +
"an application is instantiated and initialized.");
Log.log.warning("SiteResourceManager: No application was initialized. " +
"A user of the site resource manager must ensure that " +
"an application is instantiated and initialized.");
}
// get handles on the good stuff
@@ -63,33 +64,30 @@ public class SiteResourceManager extends ResourceManagerImpl
// make sure the app has a site resource loader
SiteResourceLoader loader = app.getSiteResourceLoader();
if (loader == null) {
rsvc.warn("SiteResourceManager: application must be " +
"configured with a site-specific resource loader " +
"that we can use to fetch site-specific resources.");
Log.log.warning("SiteResourceManager: application must be " +
"configured with a site-specific resource loader " +
"that we can use to fetch site-specific resources.");
}
// create our resource loaders
_siteLoader = new SiteJarResourceLoader(loader);
_contextLoader = new ServletContextResourceLoader(_sctx);
// for now, turn caching on with the expectation that new
// resources of any sort will result in the entire web application
// being reloaded and clearing out the cache
// for now, turn caching on with the expectation that new resources of any sort will result
// in the entire web application being reloaded and clearing out the cache
_siteLoader.setCachingOn(true);
_contextLoader.setCachingOn(true);
rsvc.info("SiteResourceManager initialization complete.");
Log.log.info("SiteResourceManager initialization complete.");
}
protected Resource loadResource(
String resourceName, int resourceType, String encoding)
protected Resource loadResource(String resourceName, int resourceType, String encoding)
throws ResourceNotFoundException, ParseErrorException, Exception
{
SiteKey skey = new SiteKey(resourceName);
// create a blank new resource
Resource resource =
ResourceFactory.getResource(skey.path, resourceType);
Resource resource = ResourceFactory.getResource(skey.path, resourceType);
resource.setRuntimeServices(rsvc);
resource.setEncoding(encoding);
@@ -101,8 +99,7 @@ public class SiteResourceManager extends ResourceManagerImpl
// nothing to worry about here
}
// then try the servlet context loader if we didn't find a
// site-specific resource
// then try the servlet context loader if we didn't find a site-specific resource
if (resource.getData() == null) {
resource.setName(skey.path);
resolveResource(resource, _contextLoader);
@@ -117,8 +114,7 @@ public class SiteResourceManager extends ResourceManagerImpl
resource.setResourceLoader(loader);
resource.process();
resource.setLastModified(loader.getLastModified(resource));
resource.setModificationCheckInterval(
loader.getModificationCheckInterval());
resource.setModificationCheckInterval(loader.getModificationCheckInterval());
resource.touch();
}