Refactor and simplify concurrency support.

git-svn-id: https://svn.apache.org/repos/asf/tapestry/tapestry3/trunk@681513 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java b/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java
index 1107a47..df5f266 100644
--- a/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java
+++ b/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java
@@ -14,7 +14,6 @@
 
 package org.apache.tapestry;
 
-import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tapestry.engine.BaseEngine;
@@ -39,141 +38,108 @@
 import java.util.Locale;
 
 /**
- *  Links a servlet container with a Tapestry application.  The servlet has some
- *  responsibilities related to bootstrapping the application (in terms of
- *  logging, reading the {@link ApplicationSpecification specification}, etc.).
- *  It is also responsible for creating or locating the {@link IEngine} and delegating
- *  incoming requests to it.
- * 
- *  <p>The servlet init parameter
- *  <code>org.apache.tapestry.specification-path</code>
- *  should be set to the complete resource path (within the classpath)
- *  to the application specification, i.e.,
- *  <code>/com/foo/bar/MyApp.application</code>. 
+ * Links a servlet container with a Tapestry application.  The servlet has some responsibilities related to
+ * bootstrapping the application (in terms of logging, reading the {@link ApplicationSpecification specification},
+ * etc.). It is also responsible for creating or locating the {@link IEngine} and delegating incoming requests to it.
+ * <p/>
+ * <p>The servlet init parameter <code>org.apache.tapestry.specification-path</code> should be set to the complete
+ * resource path (within the classpath) to the application specification, i.e., <code>/com/foo/bar/MyApp.application</code>.
+ * <p/>
+ * <p>In some servlet containers (notably <a href="www.bea.com"/>WebLogic</a>) it is necessary to invoke {@link
+ * HttpSession#setAttribute(String,Object)} in order to force a persistent value to be replicated to the other servers
+ * in the cluster.  Tapestry applications usually only have a single persistent value, the {@link IEngine engine}.  For
+ * persistence to work in such an environment, the JVM system property <code>org.apache.tapestry.store-engine</code>
+ * must be set to <code>true</code>.  This will force the application servlet to restore the engine into the {@link
+ * HttpSession} at the end of each request cycle.
+ * <p/>
+ * <p>As of release 1.0.1, it is no longer necessary for a {@link HttpSession} to be created on the first request cycle.
+ * Instead, the HttpSession is created as needed by the {@link IEngine} ... that is, when a visit object is created, or
+ * when persistent page state is required.  Otherwise, for sessionless requests, an {@link IEngine} from a {@link Pool}
+ * is used.  Additional work must be done so that the {@link IEngine} can change locale <em>without</em> forcing the
+ * creation of a session; this involves the servlet and the engine storing locale information in a {@link Cookie}.
  *
- *  <p>In some servlet containers (notably
- *  <a href="www.bea.com"/>WebLogic</a>)
- *  it is necessary to invoke {@link HttpSession#setAttribute(String,Object)}
- *  in order to force a persistent value to be replicated to the other
- *  servers in the cluster.  Tapestry applications usually only have a single
- *  persistent value, the {@link IEngine engine}.  For persistence to
- *  work in such an environment, the
- *  JVM system property <code>org.apache.tapestry.store-engine</code>
- *  must be set to <code>true</code>.  This will force the application
- *  servlet to restore the engine into the {@link HttpSession} at the
- *  end of each request cycle.
- * 
- *  <p>As of release 1.0.1, it is no longer necessary for a {@link HttpSession}
- *  to be created on the first request cycle.  Instead, the HttpSession is created
- *  as needed by the {@link IEngine} ... that is, when a visit object is created,
- *  or when persistent page state is required.  Otherwise, for sessionless requests,
- *  an {@link IEngine} from a {@link Pool} is used.  Additional work must be done
- *  so that the {@link IEngine} can change locale <em>without</em> forcing 
- *  the creation of a session; this involves the servlet and the engine storing
- *  locale information in a {@link Cookie}.
- * 
- *  @version $Id$
- *  @author Howard Lewis Ship
- * 
- **/
+ * @author Howard Lewis Ship
+ * @version $Id$
+ */
 
 public class ApplicationServlet extends HttpServlet
 {
     private static final Log LOG = LogFactory.getLog(ApplicationServlet.class);
 
-    /** @since 2.3 **/
+    /**
+     * @since 2.3 *
+     */
 
     private static final String APP_SPEC_PATH_PARAM =
-        "org.apache.tapestry.application-specification";
+            "org.apache.tapestry.application-specification";
 
     /**
-     *  Name of the cookie written to the client web browser to
-     *  identify the locale.
-     *
-     **/
+     * Name of the cookie written to the client web browser to identify the locale.
+     */
 
     private static final String LOCALE_COOKIE_NAME = "org.apache.tapestry.locale";
 
     /**
-     *  A {@link Pool} used to store {@link IEngine engine}s that are not currently
-     *  in use.  The key is on {@link Locale}.
-     *
-     **/
+     * A {@link Pool} used to store {@link IEngine engine}s that are not currently in use.  The key is on {@link
+     * Locale}.
+     */
 
     private Pool _enginePool = new Pool();
 
     /**
-     *  The application specification, which is read once and kept in memory
-     *  thereafter.
-     *
-     **/
+     * The application specification, which is read once and kept in memory thereafter.
+     */
 
     private IApplicationSpecification _specification;
 
     /**
-     * The name under which the {@link IEngine engine} is stored within the
-     * {@link HttpSession}.
-     *
-     **/
+     * The name under which the {@link IEngine engine} is stored within the {@link HttpSession}.
+     */
 
     private String _attributeName;
 
     /**
-     *  The resolved class name used to instantiate the engine.
-     * 
-     *  @since 3.0
-     * 
-     **/
+     * The resolved class name used to instantiate the engine.
+     *
+     * @since 3.0
+     */
 
     private String _engineClassName;
 
     /**
-     *  Used to search for configuration properties.
-     * 
-     *  
-     *  @since 3.0
-     * 
-     **/
+     * Used to search for configuration properties.
+     *
+     * @since 3.0
+     */
 
     private IPropertySource _propertySource;
 
     /**
-     * Global lock used to synchronize global thread access to commonly shared
-     * services / data structures.
+     * Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
+     *
+     * @since 1.0.6
      */
-    private ReentrantLock _lock = new ReentrantLock();
-
-    /**
-     *  Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
-     *
-     *  @since 1.0.6
-     *
-     **/
 
     public void doGet(HttpServletRequest request, HttpServletResponse response)
-        throws IOException, ServletException
+            throws IOException, ServletException
     {
         doService(request, response);
     }
 
     /**
-     *  @since 2.3
-     * 
-     **/
+     * @since 2.3
+     */
 
     private IResourceResolver _resolver;
 
     /**
-     * Handles the GET and POST requests. Performs the following:
-     * <ul>
-     * <li>Construct a {@link RequestContext}
-     * <li>Invoke {@link #getEngine(RequestContext)} to get or create the {@link IEngine}
-     * <li>Invoke {@link IEngine#service(RequestContext)} on the application
-     * </ul>
-     **/
+     * Handles the GET and POST requests. Performs the following: <ul> <li>Construct a {@link RequestContext} <li>Invoke
+     * {@link #getEngine(RequestContext)} to get or create the {@link IEngine} <li>Invoke {@link
+     * IEngine#service(RequestContext)} on the application </ul>
+     */
 
     protected void doService(HttpServletRequest request, HttpServletResponse response)
-        throws IOException, ServletException
+            throws IOException, ServletException
     {
         RequestContext context = null;
 
@@ -189,7 +155,7 @@
 
             if (engine == null)
                 throw new ServletException(
-                    Tapestry.getMessage("ApplicationServlet.could-not-locate-engine"));
+                        Tapestry.getMessage("ApplicationServlet.could-not-locate-engine"));
 
             boolean dirty = engine.service(context);
 
@@ -210,7 +176,7 @@
                 {
 
                     boolean forceStore =
-                        engine.isStateful() && (session.getAttribute(_attributeName) == null);
+                            engine.isStateful() && (session.getAttribute(_attributeName) == null);
 
                     if (forceStore || dirty)
                     {
@@ -239,9 +205,9 @@
             if (engine.isStateful())
             {
                 LOG.error(
-                    Tapestry.format(
-                        "ApplicationServlet.engine-stateful-without-session",
-                        engine));
+                        Tapestry.format(
+                                "ApplicationServlet.engine-stateful-without-session",
+                                engine));
                 return;
             }
 
@@ -285,18 +251,17 @@
     }
 
     /**
-     *  Invoked by {@link #doService(HttpServletRequest, HttpServletResponse)} to create
-     *  the {@link RequestContext} for this request cycle.  Some applications may need to
-     *  replace the default RequestContext with a subclass for particular behavior.
-     * 
-     *  @since 2.3
-     * 
-     **/
+     * Invoked by {@link #doService(HttpServletRequest, HttpServletResponse)} to create the {@link RequestContext} for
+     * this request cycle.  Some applications may need to replace the default RequestContext with a subclass for
+     * particular behavior.
+     *
+     * @since 2.3
+     */
 
     protected RequestContext createRequestContext(
-        HttpServletRequest request,
-        HttpServletResponse response)
-        throws IOException
+            HttpServletRequest request,
+            HttpServletResponse response)
+            throws IOException
     {
         return new RequestContext(this, request, response);
     }
@@ -312,22 +277,18 @@
     }
 
     /**
-     *  Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
-     *
-     *
-     **/
+     * Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
+     */
 
     public void doPost(HttpServletRequest request, HttpServletResponse response)
-        throws IOException, ServletException
+            throws IOException, ServletException
     {
         doService(request, response);
     }
 
     /**
-     *  Returns the application specification, which is read
-     *  by the {@link #init(ServletConfig)} method.
-     *
-     **/
+     * Returns the application specification, which is read by the {@link #init(ServletConfig)} method.
+     */
 
     public IApplicationSpecification getApplicationSpecification()
     {
@@ -335,25 +296,10 @@
     }
 
     /**
-     * Used internally to synchronize access to creation of shared services.
-     *
-     * @return The global shared lock.
+     * Retrieves the {@link IEngine engine} that will process this request.  This comes from one of the following
+     * places: <ul> <li>The {@link HttpSession}, if the there is one. <li>From the pool of available engines <li>Freshly
+     * created </ul>
      */
-    public ReentrantLock getLock()
-    {
-        return _lock;
-    }
-
-    /**
-     *  Retrieves the {@link IEngine engine} that will process this
-     *  request.  This comes from one of the following places:
-     *  <ul>
-     *  <li>The {@link HttpSession}, if the there is one.
-     *  <li>From the pool of available engines
-     *  <li>Freshly created
-     *  </ul>
-     *
-     **/
 
     protected IEngine getEngine(RequestContext context) throws ServletException
     {
@@ -396,12 +342,9 @@
     }
 
     /**
-     *  Determines the {@link Locale} for the incoming request.
-     *  This is determined from the locale cookie or, if not set,
-     *  from the request itself.  This may return null
-     *  if no locale is determined.
-     *
-     **/
+     * Determines the {@link Locale} for the incoming request. This is determined from the locale cookie or, if not set,
+     * from the request itself.  This may return null if no locale is determined.
+     */
 
     protected Locale getLocaleFromRequest(RequestContext context) throws ServletException
     {
@@ -414,15 +357,13 @@
     }
 
     /**
-     *  Reads the application specification when the servlet is
-     *  first initialized.  All {@link IEngine engine instances}
-     *  will have access to the specification via the servlet.
-     * 
-     *  @see #getApplicationSpecification()
-     *  @see #constructApplicationSpecification()
-     *  @see #createResourceResolver()
+     * Reads the application specification when the servlet is first initialized.  All {@link IEngine engine instances}
+     * will have access to the specification via the servlet.
      *
-     **/
+     * @see #getApplicationSpecification()
+     * @see #constructApplicationSpecification()
+     * @see #createResourceResolver()
+     */
 
     public void init(ServletConfig config) throws ServletException
     {
@@ -436,17 +377,15 @@
     }
 
     /**
-     *  Invoked from {@link #init(ServletConfig)} to create a resource resolver
-     *  for the servlet (which will utlimately be shared and used through the
-     *  application).
-     * 
-     *  <p>This implementation constructs a {@link DefaultResourceResolver}, subclasses
-     *  may provide a different implementation.
-     * 
-     *  @see #getResourceResolver()
-     *  @since 2.3
-     * 
-     **/
+     * Invoked from {@link #init(ServletConfig)} to create a resource resolver for the servlet (which will utlimately be
+     * shared and used through the application).
+     * <p/>
+     * <p>This implementation constructs a {@link DefaultResourceResolver}, subclasses may provide a different
+     * implementation.
+     *
+     * @see #getResourceResolver()
+     * @since 2.3
+     */
 
     protected IResourceResolver createResourceResolver() throws ServletException
     {
@@ -454,24 +393,18 @@
     }
 
     /**
-     *  Invoked from {@link #init(ServletConfig)} to read and construct
-     *  the {@link ApplicationSpecification} for this servlet.
-     *  Invokes {@link #getApplicationSpecificationPath()}, opens
-     *  the resource as a stream, then invokes
-     *  {@link #parseApplicationSpecification(IResourceLocation)}.
-     * 
-     *  <p>
-     *  This method exists to be overriden in
-     *  applications where the application specification cannot be
-     *  loaded from the classpath.  Alternately, a subclass
-     *  could override this method, invoke this implementation,
-     *  and then add additional data to it (for example, an application
-     *  where some of the pages are defined in an external source
-     *  such as a database).
-     *  
-     *  @since 2.2
-     * 
-     **/
+     * Invoked from {@link #init(ServletConfig)} to read and construct the {@link ApplicationSpecification} for this
+     * servlet. Invokes {@link #getApplicationSpecificationPath()}, opens the resource as a stream, then invokes {@link
+     * #parseApplicationSpecification(IResourceLocation)}.
+     * <p/>
+     * <p/>
+     * This method exists to be overriden in applications where the application specification cannot be loaded from the
+     * classpath.  Alternately, a subclass could override this method, invoke this implementation, and then add
+     * additional data to it (for example, an application where some of the pages are defined in an external source such
+     * as a database).
+     *
+     * @since 2.2
+     */
 
     protected IApplicationSpecification constructApplicationSpecification() throws ServletException
     {
@@ -492,24 +425,16 @@
     }
 
     /**
-     *  Gets the location of the application specification, if there is one.
-     *  
-     *  <ul>
-     *  <li>Invokes {@link #getApplicationSpecificationPath()} to get the
-     *  location of the application specification on the classpath.
-     *  <li>If that return null, search for the application specification:
-     *  <ul>
-     *  <li><i>name</i>.application in /WEB-INF/<i>name</i>/
-     *  <li><i>name</i>.application in /WEB-INF/
-     *  </ul>
-     *  </ul>
-     * 
-     *  <p>Returns the location of the application specification, or null
-     *  if not found.
-     * 
-     *  @since 3.0
-     * 
-     **/
+     * Gets the location of the application specification, if there is one.
+     * <p/>
+     * <ul> <li>Invokes {@link #getApplicationSpecificationPath()} to get the location of the application specification
+     * on the classpath. <li>If that return null, search for the application specification: <ul>
+     * <li><i>name</i>.application in /WEB-INF/<i>name</i>/ <li><i>name</i>.application in /WEB-INF/ </ul> </ul>
+     * <p/>
+     * <p>Returns the location of the application specification, or null if not found.
+     *
+     * @since 3.0
+     */
 
     protected IResourceLocation getApplicationSpecificationLocation() throws ServletException
     {
@@ -533,12 +458,10 @@
     }
 
     /**
-     *  Checks for the application specification relative to the specified
-     *  location.
-     * 
-     *  @since 3.0
-     * 
-     **/
+     * Checks for the application specification relative to the specified location.
+     *
+     * @since 3.0
+     */
 
     private IResourceLocation check(IResourceLocation location, String name)
     {
@@ -557,21 +480,19 @@
     }
 
     /**
-     *  Invoked from {@link #constructApplicationSpecification()} when
-     *  the application doesn't have an explicit specification.  A
-     *  simple specification is constructed and returned.  This is useful
-     *  for minimal applications and prototypes.
-     * 
-     *  @since 3.0
-     * 
-     **/
+     * Invoked from {@link #constructApplicationSpecification()} when the application doesn't have an explicit
+     * specification.  A simple specification is constructed and returned.  This is useful for minimal applications and
+     * prototypes.
+     *
+     * @since 3.0
+     */
 
     protected IApplicationSpecification constructStandinSpecification()
     {
         ApplicationSpecification result = new ApplicationSpecification();
 
         IResourceLocation virtualLocation =
-            new ContextResourceLocation(getServletContext(), "/WEB-INF/");
+                new ContextResourceLocation(getServletContext(), "/WEB-INF/");
 
         result.setSpecificationLocation(virtualLocation);
 
@@ -582,16 +503,14 @@
     }
 
     /**
-     *  Invoked from {@link #constructApplicationSpecification()} to
-     *  actually parse the stream (with content provided from the path)
-     *  and convert it into an {@link ApplicationSpecification}.
-     * 
-     *  @since 2.2
-     * 
-     **/
+     * Invoked from {@link #constructApplicationSpecification()} to actually parse the stream (with content provided
+     * from the path) and convert it into an {@link ApplicationSpecification}.
+     *
+     * @since 2.2
+     */
 
     protected IApplicationSpecification parseApplicationSpecification(IResourceLocation location)
-        throws ServletException
+            throws ServletException
     {
         try
         {
@@ -604,15 +523,14 @@
             show(ex);
 
             throw new ServletException(
-                Tapestry.format("ApplicationServlet.could-not-parse-spec", location),
-                ex);
+                    Tapestry.format("ApplicationServlet.could-not-parse-spec", location),
+                    ex);
         }
     }
 
     /**
-     *  Closes the stream, ignoring any exceptions.
-     * 
-     **/
+     * Closes the stream, ignoring any exceptions.
+     */
 
     protected void close(InputStream stream)
     {
@@ -628,18 +546,15 @@
     }
 
     /**
-     *  Reads the servlet init parameter
-     *  <code>org.apache.tapestry.application-specification</code>, which
-     *  is the location, on the classpath, of the application specification.
+     * Reads the servlet init parameter <code>org.apache.tapestry.application-specification</code>, which is the
+     * location, on the classpath, of the application specification.
+     * <p/>
+     * <p/>
+     * If the parameter is not set, this method returns null, and a search for the application specification within the
+     * servlet context will begin.
      *
-     *  <p>
-     *  If the parameter is not set, this method returns null, and a search
-     *  for the application specification within the servlet context
-     *  will begin.
-     * 
-     *  @see #getApplicationSpecificationLocation()
-     * 
-     **/
+     * @see #getApplicationSpecificationLocation()
+     */
 
     protected String getApplicationSpecificationPath() throws ServletException
     {
@@ -647,17 +562,13 @@
     }
 
     /**
-     *  Invoked by {@link #getEngine(RequestContext)} to create
-     *  the {@link IEngine} instance specific to the
-     *  application, if not already in the
-     *  {@link HttpSession}.
+     * Invoked by {@link #getEngine(RequestContext)} to create the {@link IEngine} instance specific to the application,
+     * if not already in the {@link HttpSession}.
+     * <p/>
+     * <p>The {@link IEngine} instance returned is stored into the {@link HttpSession}.
      *
-     *  <p>The {@link IEngine} instance returned is stored into the
-     *  {@link HttpSession}.
-     *
-     *  @see #getEngineClassName()    
-     *
-     **/
+     * @see #getEngineClassName()
+     */
 
     protected IEngine createEngine(RequestContext context) throws ServletException
     {
@@ -684,19 +595,12 @@
     }
 
     /**
-     * 
-     *  Returns the name of the class to use when instantiating
-     *  an engine instance for this application.  
-     *  If the application specification
-     *  provides a value, this is returned.  Otherwise, a search for
-     *  the configuration property 
-     *  <code>org.apache.tapestry.engine-class</code>
-     *  occurs (see {@link #searchConfiguration(String)}).
-     * 
-     *  <p>If the search is still unsuccessful, then
-     *  {@link org.apache.tapestry.engine.BaseEngine} is used.
-     * 
-     **/
+     * Returns the name of the class to use when instantiating an engine instance for this application. If the
+     * application specification provides a value, this is returned.  Otherwise, a search for the configuration property
+     * <code>org.apache.tapestry.engine-class</code> occurs (see {@link #searchConfiguration(String)}).
+     * <p/>
+     * <p>If the search is still unsuccessful, then {@link org.apache.tapestry.engine.BaseEngine} is used.
+     */
 
     protected String getEngineClassName()
     {
@@ -715,48 +619,30 @@
     }
 
     /**
-     *  Searches for a configuration property in:
-     *  <ul>
-     *  <li>The servlet's initial parameters
-     *  <li>The servlet context's initial parameters
-     *  <li>JVM system properties
-     *  </ul>
-     * 
-     *  @see #createPropertySource()
-     *  @since 3.0
-     * 
-     **/
+     * Searches for a configuration property in: <ul> <li>The servlet's initial parameters <li>The servlet context's
+     * initial parameters <li>JVM system properties </ul>
+     *
+     * @see #createPropertySource()
+     * @since 3.0
+     */
 
     protected String searchConfiguration(String propertyName)
     {
-        if (_propertySource == null)
+        synchronized (this)
         {
-            _lock.lock();
-
-            try
-            {
-                if (_propertySource == null)
-                {
-                    _propertySource = createPropertySource();
-                }
-            } finally
-            {
-                _lock.unlock();
-            }
+            if (_propertySource == null)
+                _propertySource = createPropertySource();
         }
 
         return _propertySource.getPropertyValue(propertyName);
     }
 
     /**
-     *  Creates an instance of {@link IPropertySource} used for
-     *  searching of configuration values.  Subclasses may override
-     *  this method if they want to change the normal locations
-     *  that properties are searched for within.
-     * 
-     *  @since 3.0
-     * 
-     **/
+     * Creates an instance of {@link IPropertySource} used for searching of configuration values.  Subclasses may
+     * override this method if they want to change the normal locations that properties are searched for within.
+     *
+     * @since 3.0
+     */
 
     protected IPropertySource createPropertySource()
     {
@@ -770,16 +656,14 @@
     }
 
     /**
-     *  Invoked from the {@link IEngine engine}, just prior to starting to
-     *  render a response, when the locale has changed.  The servlet writes a
-     *  {@link Cookie} so that, on subsequent request cycles, an engine localized
-     *  to the selected locale is chosen.
+     * Invoked from the {@link IEngine engine}, just prior to starting to render a response, when the locale has
+     * changed.  The servlet writes a {@link Cookie} so that, on subsequent request cycles, an engine localized to the
+     * selected locale is chosen.
+     * <p/>
+     * <p>At this time, the cookie is <em>not</em> persistent.  That may change in subsequent releases.
      *
-     *  <p>At this time, the cookie is <em>not</em> persistent.  That may
-     *  change in subsequent releases.
-     *
-     *  @since 1.0.1
-     **/
+     * @since 1.0.1
+     */
 
     public void writeLocaleCookie(Locale locale, IEngine engine, RequestContext cycle)
     {
@@ -793,14 +677,11 @@
     }
 
     /**
-     *  Returns a resource resolver that can access classes and resources related
-     *  to the current web application context.  Relies on
-     *  {@link java.lang.Thread#getContextClassLoader()}, which is set by
-     *  most modern servlet containers.
-     * 
-     *  @since 2.3
+     * Returns a resource resolver that can access classes and resources related to the current web application context.
+     * Relies on {@link java.lang.Thread#getContextClassLoader()}, which is set by most modern servlet containers.
      *
-     **/
+     * @since 2.3
+     */
 
     public IResourceResolver getResourceResolver()
     {
@@ -809,6 +690,7 @@
 
     /**
      * Ensures that shared janitor thread is terminated.
+     *
      * @see javax.servlet.Servlet#destroy()
      * @since 3.0.3
      */
diff --git a/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java b/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java
index 423b24b..f32fa33 100644
--- a/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java
+++ b/tapestry-framework/src/org/apache/tapestry/BaseComponentTemplateLoader.java
@@ -20,7 +20,6 @@
 import org.apache.tapestry.binding.ExpressionBinding;
 import org.apache.tapestry.binding.StaticBinding;
 import org.apache.tapestry.binding.StringBinding;
-import org.apache.tapestry.engine.ExpressionEvaluator;
 import org.apache.tapestry.engine.IPageLoader;
 import org.apache.tapestry.engine.IPageSource;
 import org.apache.tapestry.engine.ITemplateSource;
@@ -34,16 +33,14 @@
 import java.util.Set;
 
 /**
- *  Utility class instantiated by {@link org.apache.tapestry.BaseComponent} to
- *  process the component's {@link org.apache.tapestry.parse.ComponentTemplate template},
- *  which involves working through the nested structure of the template and hooking
- *  the various static template blocks and components together using
- *  {@link IComponent#addBody(IRender)} and 
- *  {@link org.apache.tapestry.BaseComponent#addOuter(IRender)}.
+ * Utility class instantiated by {@link org.apache.tapestry.BaseComponent} to process the component's {@link
+ * org.apache.tapestry.parse.ComponentTemplate template}, which involves working through the nested structure of the
+ * template and hooking the various static template blocks and components together using {@link
+ * IComponent#addBody(IRender)} and {@link org.apache.tapestry.BaseComponent#addOuter(IRender)}.
  *
- *  @author Howard Lewis Ship
- *  @version $Id$
- *  @since 3.0
+ * @author Howard Lewis Ship
+ * @version $Id$
+ * @since 3.0
  */
 
 public class BaseComponentTemplateLoader
@@ -58,12 +55,10 @@
     private IComponent[] _stack;
     private int _stackx = 0;
     private IComponent _activeComponent = null;
-    private ExpressionEvaluator _evaluator;
     private Set _seenIds = new HashSet();
 
     /**
-     *  A class used with invisible localizations.  Constructed
-     *  from a {@link TextToken}.
+     * A class used with invisible localizations.  Constructed from a {@link TextToken}.
      */
 
     private static class LocalizedStringRender implements IRender
@@ -130,11 +125,11 @@
     }
 
     public BaseComponentTemplateLoader(
-        IRequestCycle requestCycle,
-        IPageLoader pageLoader,
-        BaseComponent loadComponent,
-        ComponentTemplate template,
-        IPageSource pageSource)
+            IRequestCycle requestCycle,
+            IPageLoader pageLoader,
+            BaseComponent loadComponent,
+            ComponentTemplate template,
+            IPageSource pageSource)
     {
         _requestCycle = requestCycle;
         _pageLoader = pageLoader;
@@ -185,21 +180,20 @@
 
         if (_stackx != 0)
             throw new ApplicationRuntimeException(
-                Tapestry.getMessage("BaseComponent.unbalance-open-tags"),
-                _loadComponent,
-                null,
-                null);
+                    Tapestry.getMessage("BaseComponent.unbalance-open-tags"),
+                    _loadComponent,
+                    null,
+                    null);
 
         checkAllComponentsReferenced();
     }
 
     /**
-     *  Adds the token (which implements {@link IRender})
-     *  to the active component (using {@link IComponent#addBody(IRender)}),
-     *  or to this component {@link BaseComponent#addOuter(IRender)}.
-     * 
-     *  <p>
-     *  A check is made that the active component allows a body.
+     * Adds the token (which implements {@link IRender}) to the active component (using {@link
+     * IComponent#addBody(IRender)}), or to this component {@link BaseComponent#addOuter(IRender)}.
+     * <p/>
+     * <p/>
+     * A check is made that the active component allows a body.
      */
 
     private void process(TextToken token)
@@ -235,13 +229,13 @@
 
         if (_seenIds.contains(id))
             throw new ApplicationRuntimeException(
-                Tapestry.format(
-                    "BaseComponent.multiple-component-references",
-                    _loadComponent.getExtendedId(),
-                    id),
-                _loadComponent,
-                token.getLocation(),
-                null);
+                    Tapestry.format(
+                            "BaseComponent.multiple-component-references",
+                            _loadComponent.getExtendedId(),
+                            id),
+                    _loadComponent,
+                    token.getLocation(),
+                    null);
 
         _seenIds.add(id);
 
@@ -274,25 +268,25 @@
 
         if (cc != null)
             throw new ApplicationRuntimeException(
-                Tapestry.format(
-                    "BaseComponentTemplateLoader.dupe-component-id",
-                    id,
+                    Tapestry.format(
+                            "BaseComponentTemplateLoader.dupe-component-id",
+                            id,
+                            location,
+                            cc.getLocation()),
+                    _loadComponent,
                     location,
-                    cc.getLocation()),
-                _loadComponent,
-                location,
-                null);
+                    null);
     }
 
     private IComponent createImplicitComponent(String id, String componentType, ILocation location)
     {
         IComponent result =
-            _pageLoader.createImplicitComponent(
-                _requestCycle,
-                _loadComponent,
-                id,
-                componentType,
-                location);
+                _pageLoader.createImplicitComponent(
+                        _requestCycle,
+                        _loadComponent,
+                        id,
+                        componentType,
+                        location);
 
         return result;
     }
@@ -309,10 +303,10 @@
 
         if (_stackx <= 0)
             throw new ApplicationRuntimeException(
-                Tapestry.getMessage("BaseComponent.unbalanced-close-tags"),
-                _loadComponent,
-                token.getLocation(),
-                null);
+                    Tapestry.getMessage("BaseComponent.unbalanced-close-tags"),
+                    _loadComponent,
+                    token.getLocation(),
+                    null);
 
         // Null and forget the top element on the stack.
 
@@ -332,7 +326,7 @@
     }
 
     /**
-     *  Adds bindings based on attributes in the template.
+     * Adds bindings based on attributes in the template.
      */
 
     private void addTemplateBindings(IComponent component, OpenToken token)
@@ -356,32 +350,32 @@
                 if (type == AttributeType.OGNL_EXPRESSION)
                 {
                     addExpressionBinding(
-                        component,
-                        spec,
-                        name,
-                        attribute.getValue(),
-                        token.getLocation());
+                            component,
+                            spec,
+                            name,
+                            attribute.getValue(),
+                            token.getLocation());
                     continue;
                 }
 
                 if (type == AttributeType.LOCALIZATION_KEY)
                 {
                     addStringBinding(
-                        component,
-                        spec,
-                        name,
-                        attribute.getValue(),
-                        token.getLocation());
+                            component,
+                            spec,
+                            name,
+                            attribute.getValue(),
+                            token.getLocation());
                     continue;
                 }
 
                 if (type == AttributeType.LITERAL)
                     addStaticBinding(
-                        component,
-                        spec,
-                        name,
-                        attribute.getValue(),
-                        token.getLocation());
+                            component,
+                            spec,
+                            name,
+                            attribute.getValue(),
+                            token.getLocation());
             }
         }
 
@@ -389,33 +383,30 @@
         // there is no established binding for that parameter, 
         // add a static binding carrying the template tag  
         if (spec.getParameter(ITemplateSource.TEMPLATE_TAG_PARAMETER_NAME) != null
-            && component.getBinding(ITemplateSource.TEMPLATE_TAG_PARAMETER_NAME) == null)
+                && component.getBinding(ITemplateSource.TEMPLATE_TAG_PARAMETER_NAME) == null)
         {
             addStaticBinding(
-                component,
-                spec,
-                ITemplateSource.TEMPLATE_TAG_PARAMETER_NAME,
-                token.getTag(),
-                token.getLocation());
+                    component,
+                    spec,
+                    ITemplateSource.TEMPLATE_TAG_PARAMETER_NAME,
+                    token.getTag(),
+                    token.getLocation());
         }
 
     }
 
     /**
-     *  Adds an expression binding, checking for errors related
-     *  to reserved and informal parameters.
-     *
-     *  <p>It is an error to specify expression 
-     *  bindings in both the specification
-     *  and the template.
+     * Adds an expression binding, checking for errors related to reserved and informal parameters.
+     * <p/>
+     * <p>It is an error to specify expression bindings in both the specification and the template.
      */
 
     private void addExpressionBinding(
-        IComponent component,
-        IComponentSpecification spec,
-        String name,
-        String expression,
-        ILocation location)
+            IComponent component,
+            IComponentSpecification spec,
+            String name,
+            String expression,
+            ILocation location)
     {
 
         // If matches a formal parameter name, allow it to be set
@@ -427,68 +418,65 @@
         {
             if (component.getBinding(name) != null)
                 throw new ApplicationRuntimeException(
-                    Tapestry.format(
-                        "BaseComponent.dupe-template-expression",
-                        name,
-                        component.getExtendedId(),
-                        _loadComponent.getExtendedId()),
-                    component,
-                    location,
-                    null);
+                        Tapestry.format(
+                                "BaseComponent.dupe-template-expression",
+                                name,
+                                component.getExtendedId(),
+                                _loadComponent.getExtendedId()),
+                        component,
+                        location,
+                        null);
         }
         else
         {
             if (!spec.getAllowInformalParameters())
                 throw new ApplicationRuntimeException(
-                    Tapestry.format(
-                        "BaseComponent.template-expression-for-informal-parameter",
-                        name,
-                        component.getExtendedId(),
-                        _loadComponent.getExtendedId()),
-                    component,
-                    location,
-                    null);
+                        Tapestry.format(
+                                "BaseComponent.template-expression-for-informal-parameter",
+                                name,
+                                component.getExtendedId(),
+                                _loadComponent.getExtendedId()),
+                        component,
+                        location,
+                        null);
 
             // If the name is reserved (matches a formal parameter
             // or reserved name, caselessly), then skip it.
 
             if (spec.isReservedParameterName(name))
                 throw new ApplicationRuntimeException(
-                    Tapestry.format(
-                        "BaseComponent.template-expression-for-reserved-parameter",
-                        name,
-                        component.getExtendedId(),
-                        _loadComponent.getExtendedId()),
-                    component,
-                    location,
-                    null);
+                        Tapestry.format(
+                                "BaseComponent.template-expression-for-reserved-parameter",
+                                name,
+                                component.getExtendedId(),
+                                _loadComponent.getExtendedId()),
+                        component,
+                        location,
+                        null);
         }
 
         IBinding binding =
-            new ExpressionBinding(
-                _pageSource.getResourceResolver(),
-                _loadComponent,
-                expression,
-                location);
+                new ExpressionBinding(
+                        _pageSource.getResourceResolver(),
+                        _loadComponent,
+                        expression,
+                        location);
 
         component.setBinding(name, binding);
     }
 
     /**
-      *  Adds an expression binding, checking for errors related
-      *  to reserved and informal parameters.
-      *
-      *  <p>It is an error to specify expression 
-      *  bindings in both the specification
-      *  and the template.
-      */
+     * Adds an expression binding, checking for errors related to reserved and informal parameters.
+     * <p/>
+     * <p>It is an error to specify expression bindings in both the specification and the template.
+     */
 
     private void addStringBinding(
-        IComponent component,
-        IComponentSpecification spec,
-        String name,
-        String localizationKey,
-        ILocation location)
+            IComponent component,
+            IComponentSpecification spec,
+            String name,
+            String localizationKey,
+            ILocation location)
     {
         // If matches a formal parameter name, allow it to be set
         // unless there's already a binding.
@@ -499,41 +487,41 @@
         {
             if (component.getBinding(name) != null)
                 throw new ApplicationRuntimeException(
-                    Tapestry.format(
-                        "BaseComponent.dupe-string",
-                        name,
-                        component.getExtendedId(),
-                        _loadComponent.getExtendedId()),
-                    component,
-                    location,
-                    null);
+                        Tapestry.format(
+                                "BaseComponent.dupe-string",
+                                name,
+                                component.getExtendedId(),
+                                _loadComponent.getExtendedId()),
+                        component,
+                        location,
+                        null);
         }
         else
         {
             if (!spec.getAllowInformalParameters())
                 throw new ApplicationRuntimeException(
-                    Tapestry.format(
-                        "BaseComponent.template-expression-for-informal-parameter",
-                        name,
-                        component.getExtendedId(),
-                        _loadComponent.getExtendedId()),
-                    component,
-                    location,
-                    null);
+                        Tapestry.format(
+                                "BaseComponent.template-expression-for-informal-parameter",
+                                name,
+                                component.getExtendedId(),
+                                _loadComponent.getExtendedId()),
+                        component,
+                        location,
+                        null);
 
             // If the name is reserved (matches a formal parameter
             // or reserved name, caselessly), then skip it.
 
             if (spec.isReservedParameterName(name))
                 throw new ApplicationRuntimeException(
-                    Tapestry.format(
-                        "BaseComponent.template-expression-for-reserved-parameter",
-                        name,
-                        component.getExtendedId(),
-                        _loadComponent.getExtendedId()),
-                    component,
-                    location,
-                    null);
+                        Tapestry.format(
+                                "BaseComponent.template-expression-for-reserved-parameter",
+                                name,
+                                component.getExtendedId(),
+                                _loadComponent.getExtendedId()),
+                        component,
+                        location,
+                        null);
         }
 
         IBinding binding = new StringBinding(_loadComponent, localizationKey, location);
@@ -542,20 +530,18 @@
     }
 
     /**
-     *  Adds a static binding, checking for errors related
-     *  to reserved and informal parameters.
-     * 
-     *  <p>
-     *  Static bindings that conflict with bindings in the
-     *  specification are quietly ignored.
+     * Adds a static binding, checking for errors related to reserved and informal parameters.
+     * <p/>
+     * <p/>
+     * Static bindings that conflict with bindings in the specification are quietly ignored.
      */
 
     private void addStaticBinding(
-        IComponent component,
-        IComponentSpecification spec,
-        String name,
-        String staticValue,
-        ILocation location)
+            IComponent component,
+            IComponentSpecification spec,
+            String name,
+            String staticValue,
+            ILocation location)
     {
 
         if (component.getBinding(name) != null)
@@ -609,12 +595,12 @@
         int count = ids.size();
 
         String key =
-            (count == 1)
+                (count == 1)
                 ? "BaseComponent.missing-component-spec-single"
                 : "BaseComponent.missing-component-spec-multi";
 
         StringBuffer buffer =
-            new StringBuffer(Tapestry.format(key, _loadComponent.getExtendedId()));
+                new StringBuffer(Tapestry.format(key, _loadComponent.getExtendedId()));
 
         Iterator i = ids.iterator();
         int j = 1;
@@ -623,15 +609,14 @@
         {
             if (j == 1)
                 buffer.append(' ');
+            else if (j == count)
+            {
+                buffer.append(' ');
+                buffer.append(Tapestry.getMessage("BaseComponent.and"));
+                buffer.append(' ');
+            }
             else
-                if (j == count)
-                {
-                    buffer.append(' ');
-                    buffer.append(Tapestry.getMessage("BaseComponent.and"));
-                    buffer.append(' ');
-                }
-                else
-                    buffer.append(", ");
+                buffer.append(", ");
 
             buffer.append(i.next());
 
@@ -646,9 +631,9 @@
     protected ApplicationRuntimeException createBodylessComponentException(IComponent component)
     {
         return new ApplicationRuntimeException(
-            Tapestry.getMessage("BaseComponentTemplateLoader.bodyless-component"),
-            component,
-            null,
-            null);
+                Tapestry.getMessage("BaseComponentTemplateLoader.bodyless-component"),
+                component,
+                null,
+                null);
     }
 }
diff --git a/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java b/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java
index a4ab6f7..8629974 100644
--- a/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java
+++ b/tapestry-framework/src/org/apache/tapestry/binding/ExpressionBinding.java
@@ -29,118 +29,87 @@
 import java.util.Map;
 
 /**
- *  Implements a dynamic binding, based on getting and fetching
- *  values using JavaBeans property access.  This is built
- *  upon the <a href="http://www.ognl.org">OGNL</a> library.
+ * Implements a dynamic binding, based on getting and fetching values using JavaBeans property access.  This is built
+ * upon the <a href="http://www.ognl.org">OGNL</a> library.
+ * <p/>
+ * <p><b>Optimization of the Expression</b>
+ * <p/>
+ * <p>There's a lot of room for optimization here because we can count on some portions of the expression to be
+ * effectively static.  Note that we type the root object as {@link IComponent}.  We have some expectations that certain
+ * properties of the root (and properties reachable from the root) will be constant for the lifetime of the binding. For
+ * example, components never change thier page or container.  This means that certain property prefixes can be
+ * optimized:
+ * <p/>
+ * <ul> <li>page <li>container <li>components.<i>name</i> </ul>
+ * <p/>
+ * <p>This means that once an ExpressionBinding has been triggered, the {@link #toString()} method may return different
+ * values for the root component and the expression than was originally set.
+ * <p/>
+ * <p><b>Identifying Invariants</b>
+ * <p/>
+ * <p>Most expressions are fully dynamic; they must be resolved each time they are accessed.  This can be somewhat
+ * inefficient. Tapestry can identify certain paths as invariant:
+ * <p/>
+ * <ul> <li>A component within the page hierarchy <li>An {@link org.apache.tapestry.IAsset} from then assets map
+ * (property <code>assets</code>) <li>A {@link org.apache.tapestry.IActionListener} from the listener map (property
+ * <code>listeners</code>) <li>A bean with a {@link org.apache.tapestry.spec.BeanLifecycle#PAGE} lifecycle (property
+ * <code>beans</code>) <li>A binding (property <code>bindings</code>) </ul>
+ * <p/>
+ * <p/>
+ * These optimizations have some inherent dangers; they assume that the components have not overidden the specified
+ * properties; the last one (concerning helper beans) assumes that the component does inherit from {@link
+ * org.apache.tapestry.AbstractComponent}. If this becomes a problem in the future, it may be necessary to have the
+ * component itself involved in these determinations.
  *
- *  <p><b>Optimization of the Expression</b>
- *
- *  <p>There's a lot of room for optimization here because we can
- *  count on some portions of the expression to be
- *  effectively static.  Note that we type the root object as
- *  {@link IComponent}.  We have some expectations that
- *  certain properties of the root (and properties reachable from the root)
- *  will be constant for the lifetime of the binding.  For example, 
- *  components never change thier page or container.  This means
- *  that certain property prefixes can be optimized:
- *
- *  <ul>
- *  <li>page
- *  <li>container
- *  <li>components.<i>name</i>
- *  </ul>
- *
- *  <p>This means that once an ExpressionBinding has been triggered, 
- *  the {@link #toString()} method may return different values for the root
- *  component and the expression than was originally set.
- *
- *  <p><b>Identifying Invariants</b>
- *
- *  <p>Most expressions are fully dynamic; they must be
- *  resolved each time they are accessed.  This can be somewhat inefficient.
- *  Tapestry can identify certain paths as invariant:
- *
- *  <ul>
- *  <li>A component within the page hierarchy 
- *  <li>An {@link org.apache.tapestry.IAsset} from then assets map (property <code>assets</code>)
- *  <li>A {@link org.apache.tapestry.IActionListener}
- *  from the listener map (property <code>listeners</code>)
- *  <li>A bean with a {@link org.apache.tapestry.spec.BeanLifecycle#PAGE}
- *  lifecycle (property <code>beans</code>)
- *  <li>A binding (property <code>bindings</code>)
- *  </ul>
- *
- *  <p>
- *  These optimizations have some inherent dangers; they assume that
- *  the components have not overidden the specified properties;
- *  the last one (concerning helper beans) assumes that the
- *  component does inherit from {@link org.apache.tapestry.AbstractComponent}.
- *  If this becomes a problem in the future, it may be necessary to
- *  have the component itself involved in these determinations.
- *
- *  @author Howard Lewis Ship
- *  @version $Id$
- *  @since 2.2
- *
- **/
+ * @author Howard Lewis Ship
+ * @version $Id$
+ * @since 2.2
+ */
 
 public class ExpressionBinding extends AbstractBinding
 {
     /**
-     *  The root object against which the nested property name is evaluated.
-     *
-     **/
+     * The root object against which the nested property name is evaluated.
+     */
 
     private IComponent _root;
 
     /**
-     *  The OGNL expression, as a string.
-     *
-     **/
+     * The OGNL expression, as a string.
+     */
 
     private String _expression;
 
     /**
-     *  If true, then the binding is invariant, and cachedValue
-     *  is the ultimate value.
-     *
-     **/
+     * If true, then the binding is invariant, and cachedValue is the ultimate value.
+     */
 
     private boolean _invariant = false;
 
     /**
-     *  Stores the cached value for the binding, if invariant
-     *  is true.
-     *
-     **/
+     * Stores the cached value for the binding, if invariant is true.
+     */
 
     private Object _cachedValue;
 
     /**
-     *   Parsed OGNL expression.
-     *
-     **/
+     * Parsed OGNL expression.
+     */
 
     private Node _parsedExpression;
 
     /**
-     *  Flag set once the binding has initialized.
-     *  _cachedValue, _invariant and _final value
-     *  for _expression
-     *  are not valid until after initialization.
-     *
-     *
-     **/
+     * Flag set once the binding has initialized. _cachedValue, _invariant and _final value for _expression are not
+     * valid until after initialization.
+     */
 
     private boolean _initialized;
 
     private IResourceResolver _resolver;
 
     /**
-     *  The OGNL context for this binding.  It is retained
-     *  for the lifespan of the binding once created.
-     *
-     **/
+     * The OGNL context for this binding.  It is retained for the lifespan of the binding once created.
+     */
 
     private Map _context;
 
@@ -156,17 +125,19 @@
     private ExpressionAccessor _accessor;
 
     /**
-     * Used to detect previous failed attempts at writing values when compiling expressions so
-     * that as many expressions as possible can be fully compiled into their java byte form when
-     * all objects in the expression are available.
+     * Used to detect previous failed attempts at writing values when compiling expressions so that as many expressions
+     * as possible can be fully compiled into their java byte form when all objects in the expression are available.
      */
     private boolean _writeFailed;
 
     /**
-     *  Creates a {@link ExpressionBinding} from the root object
-     *  and an OGNL expression.
-     *
-     **/
+     * This is current set to false, to prevent any attempts at bytecode compilation of OGNL expressions.
+     */
+    private static final boolean EXPRESSION_EVALUATION_ENABLED = false;
+
+    /**
+     * Creates a {@link ExpressionBinding} from the root object and an OGNL expression.
+     */
 
     public ExpressionBinding(
             IResourceResolver resolver,
@@ -193,12 +164,10 @@
     }
 
     /**
-     *  Gets the value of the property path, with the assistance of a 
-     *  OGNL.
+     * Gets the value of the property path, with the assistance of a OGNL.
      *
-     *  @throws BindingException if an exception is thrown accessing the property.
-     *
-     **/
+     * @throws BindingException if an exception is thrown accessing the property.
+     */
 
     public Object getObject()
     {
@@ -214,7 +183,7 @@
     {
         try
         {
-            if (false && _evaluator.isCompileEnabled() && _accessor == null && !_writeFailed)
+            if (EXPRESSION_EVALUATION_ENABLED && _evaluator.isCompileEnabled() && _accessor == null && !_writeFailed)
             {
                 _evaluator.compileExpression(_root, _parsedExpression, _expression);
                 _accessor = _parsedExpression.getAccessor();
@@ -238,14 +207,10 @@
     }
 
     /**
-     *  Creates an OGNL context used to get or set a value.
-     *  We may extend this in the future to set additional
-     *  context variables (such as page, request cycle and engine).
-     *  An optional type converter will be added to the OGNL context
-     *  if it is specified as an application extension with the name
-     *  {@link Tapestry#OGNL_TYPE_CONVERTER}.
-     *
-     **/
+     * Creates an OGNL context used to get or set a value. We may extend this in the future to set additional context
+     * variables (such as page, request cycle and engine). An optional type converter will be added to the OGNL context
+     * if it is specified as an application extension with the name {@link Tapestry#OGNL_TYPE_CONVERTER}.
+     */
 
     private Map getOgnlContext()
     {
@@ -273,11 +238,8 @@
     }
 
     /**
-     *  Returns true if the binding is expected to always 
-     *  return the same value.
-     *
-     *
-     **/
+     * Returns true if the binding is expected to always return the same value.
+     */
 
     public boolean isInvariant()
     {
@@ -307,10 +269,8 @@
     }
 
     /**
-     *  Sets up the helper object, but also optimizes the property path
-     *  and determines if the binding is invarant.
-     *
-     **/
+     * Sets up the helper object, but also optimizes the property path and determines if the binding is invarant.
+     */
 
     private void initialize()
     {
@@ -341,7 +301,6 @@
             throw new BindingException(ex.getMessage(), this, ex);
         }
 
-
         // Split the expression into individual property names.
         // We then optimize what we can from the expression.  This will
         // shorten the expression and, in some cases, eliminate
@@ -375,13 +334,11 @@
     }
 
     /**
-     *  Looks for common prefixes on the expression (provided pre-split) that
-     *  are recognized as references to other components.
+     * Looks for common prefixes on the expression (provided pre-split) that are recognized as references to other
+     * components.
      *
-     *  @return the number of leading elements of the split expression that
-     *  have been removed.
-     *
-     **/
+     * @return the number of leading elements of the split expression that have been removed.
+     */
 
     private int optimizeRootObject(String[] split)
     {
@@ -437,10 +394,8 @@
     }
 
     /**
-     *  Reassembles the remainder of the split property path
-     *  from the start point.
-     *
-     **/
+     * Reassembles the remainder of the split property path from the start point.
+     */
 
     private String reassemble(int start, String[] split)
     {
@@ -466,9 +421,8 @@
     }
 
     /**
-     *  Checks to see if the binding can be converted to an invariant.
-     *
-     **/
+     * Checks to see if the binding can be converted to an invariant.
+     */
 
     private void checkForInvariant(int start, String[] split)
     {
@@ -547,12 +501,12 @@
     }
 
     /**
-     *  Updates the property for the binding to the given value.  
+     * Updates the property for the binding to the given value.
      *
-     *  @throws BindingException if the property can't be updated (typically
-     *  due to an security problem, or a missing mutator method).
-     *  @throws BindingException if the binding is invariant.
-     **/
+     * @throws BindingException if the property can't be updated (typically due to an security problem, or a missing
+     *                          mutator method).
+     * @throws BindingException if the binding is invariant.
+     */
 
     public void setObject(Object value)
     {
@@ -566,7 +520,8 @@
             if (_accessor != null)
             {
                 _evaluator.write(_root, _accessor, value);
-            } else if (false && _evaluator.isCompileEnabled() && _accessor == null)
+            }
+            else if (EXPRESSION_EVALUATION_ENABLED && _evaluator.isCompileEnabled() && _accessor == null)
             {
                 //_evaluator.compileExpression(_root, _parsedExpression, _expression);
                 //_accessor = _parsedExpression.getAccessor();
@@ -578,7 +533,8 @@
                     {
                         _evaluator.compileExpression(_root, _parsedExpression, _expression);
                         _accessor = _parsedExpression.getAccessor();
-                    } catch (Throwable t)
+                    }
+                    catch (Throwable t)
                     {
                         // ignore re-read failures as they aren't supposed to be happening now anyways
                         // and a more user friendly version will be available if someone actually calls
@@ -589,7 +545,8 @@
                             _writeFailed = true;
                     }
                 }
-            } else
+            }
+            else
             {
                 _evaluator.writeCompiled(_root, _parsedExpression, value);
             }
@@ -608,12 +565,10 @@
     }
 
     /**
-     *  Returns the a String representing the property path.  This includes
-     *  the {@link IComponent#getExtendedId() extended id} of the root component
-     *  and the property path ... once the binding is used, these may change
-     *  due to optimization of the property path.
-     *
-     **/
+     * Returns the a String representing the property path.  This includes the {@link IComponent#getExtendedId()
+     * extended id} of the root component and the property path ... once the binding is used, these may change due to
+     * optimization of the property path.
+     */
 
     public String toString()
     {
diff --git a/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java b/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java
index 158e355..4a29195 100644
--- a/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java
+++ b/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java
@@ -43,56 +43,36 @@
 import java.util.*;
 
 /**
- *  Basis for building real Tapestry applications.  Immediate subclasses
- *  provide different strategies for managing page state and other resources
- *  between request cycles.
+ * Basis for building real Tapestry applications.  Immediate subclasses provide different strategies for managing page
+ * state and other resources between request cycles.
+ * <p/>
+ * Uses a shared instance of {@link ITemplateSource}, {@link ISpecificationSource}, {@link IScriptSource} and {@link
+ * IComponentMessagesSource} stored as attributes of the  {@link ServletContext} (they will be shared by all sessions).
+ * <p/>
+ * <p>An application is designed to be very lightweight. Particularily, it should <b>never</b> hold references to any
+ * {@link IPage} or {@link org.apache.tapestry.IComponent} objects.  The entire system is based upon being able to
+ * quickly rebuild the state of any page(s).
+ * <p/>
+ * <p>Where possible, instance variables should be transient.  They can be restored inside {@link
+ * #setupForRequest(RequestContext)}.
+ * <p/>
+ * <p>In practice, a subclass (usually {@link BaseEngine}) is used without subclassing.  Instead, a visit object is
+ * specified.  To facilitate this, the application specification may include a property,
+ * <code>org.apache.tapestry.visit-class</code> which is the class name  to instantiate when a visit object is first
+ * needed.  See {@link #createVisit(IRequestCycle)} for more details.
+ * <p/>
+ * <p>Some of the classes' behavior is controlled by JVM system properties (typically only used during development):
+ * <p/>
+ * <table border=1> <tr> <th>Property</th> <th>Description</th> </tr> <tr> <td>org.apache.tapestry.enable-reset-service</td>
+ * <td>If true, enabled an additional service, reset, that allow page, specification and template caches to be cleared
+ * on demand. See {@link #isResetServiceEnabled()}. </td> </tr> <tr> <td>org.apache.tapestry.disable-caching</td> <td>If
+ * true, then the page, specification, template and script caches will be cleared after each request. This slows things
+ * down, but ensures that the latest versions of such files are used. Care should be taken that the source directories
+ * for the files preceeds any versions of the files available in JARs or WARs. </td> </tr> </table>
  *
- *  Uses a shared instance of
- *  {@link ITemplateSource}, {@link ISpecificationSource},
- *  {@link IScriptSource} and {@link IComponentMessagesSource}
- *  stored as attributes of the  {@link ServletContext}
- *  (they will be shared by all sessions).
- *
- *  <p>An application is designed to be very lightweight.
- *  Particularily, it should <b>never</b> hold references to any
- *  {@link IPage} or {@link org.apache.tapestry.IComponent} objects.  The entire system is
- *  based upon being able to quickly rebuild the state of any page(s).
- *
- * <p>Where possible, instance variables should be transient.  They
- * can be restored inside {@link #setupForRequest(RequestContext)}.
- *
- *  <p>In practice, a subclass (usually {@link BaseEngine})
- *  is used without subclassing.  Instead, a
- *  visit object is specified.  To facilitate this, the application specification
- *  may include a property, <code>org.apache.tapestry.visit-class</code>
- *  which is the class name  to instantiate when a visit object is first needed.  See
- *  {@link #createVisit(IRequestCycle)} for more details.
- *
- * <p>Some of the classes' behavior is controlled by JVM system properties
- * (typically only used during development):
- *
- * <table border=1>
- * 	<tr> <th>Property</th> <th>Description</th> </tr>
- *  <tr> <td>org.apache.tapestry.enable-reset-service</td>
- *		<td>If true, enabled an additional service, reset, that
- *		allow page, specification and template caches to be cleared on demand.
- *  	See {@link #isResetServiceEnabled()}. </td>
- * </tr>
- * <tr>
- *		<td>org.apache.tapestry.disable-caching</td>
- *	<td>If true, then the page, specification, template and script caches
- *  will be cleared after each request. This slows things down,
- *  but ensures that the latest versions of such files are used.
- *  Care should be taken that the source directories for the files
- *  preceeds any versions of the files available in JARs or WARs. </td>
- * </tr>
- * </table>
- *
- *
- *  @author Howard Lewis Ship
- *  @version $Id$
- *
- **/
+ * @author Howard Lewis Ship
+ * @version $Id$
+ */
 
 public abstract class AbstractEngine
         implements IEngine, IEngineServiceView, Externalizable, HttpSessionBindingListener
@@ -100,9 +80,8 @@
     private static final Log LOG = LogFactory.getLog(AbstractEngine.class);
 
     /**
-     *  @since 2.0.4
-     *
-     **/
+     * @since 2.0.4
+     */
 
     private static final long serialVersionUID = 6884834397673817117L;
 
@@ -113,216 +92,177 @@
     private transient boolean _stateful;
     private transient ListenerMap _listeners;
 
-    /** @since 2.2 **/
+    /**
+     * @since 2.2 *
+     */
 
     private transient DataSqueezer _dataSqueezer;
 
     /**
-     *  An object used to contain application-specific server side state.
-     *
-     **/
+     * An object used to contain application-specific server side state.
+     */
 
     private Object _visit;
 
     /**
-     *  The globally shared application object.  Typically, this is created
-     *  when first needed, shared between sessions and engines, and
-     *  stored in the {@link ServletContext}.
+     * The globally shared application object.  Typically, this is created when first needed, shared between sessions
+     * and engines, and stored in the {@link ServletContext}.
      *
-     *  @since 2.3
-     *
-     **/
+     * @since 2.3
+     */
 
     private transient Object _global;
 
     /**
-     *  The base name for the servlet context key used to store
-     *  the application-defined Global object, if any.
+     * The base name for the servlet context key used to store the application-defined Global object, if any.
      *
-     *  @since 2.3
-     *
-     **/
+     * @since 2.3
+     */
 
     public static final String GLOBAL_NAME = "org.apache.tapestry.global";
 
     /**
-     *  The name of the application property that will be used to
-     *  determine the encoding to use when generating the output
+     * The name of the application property that will be used to determine the encoding to use when generating the
+     * output
      *
-     *  @since 3.0
-     **/
+     * @since 3.0
+     */
 
     public static final String OUTPUT_ENCODING_PROPERTY_NAME =
             "org.apache.tapestry.output-encoding";
 
     /**
-     *  The default encoding that will be used when generating the output.
-     *  It is used if no output encoding property has been specified.
+     * The default encoding that will be used when generating the output. It is used if no output encoding property has
+     * been specified.
      *
-     *  @since 3.0
+     * @since 3.0
      */
 
     public static final String DEFAULT_OUTPUT_ENCODING = "UTF-8";
 
     /**
-     *  The curent locale for the engine, which may be changed at any time.
-     *
-     **/
+     * The curent locale for the engine, which may be changed at any time.
+     */
 
     private Locale _locale;
 
     /**
-     *  Set by {@link #setLocale(Locale)} when the locale is changed;
-     *  this allows the locale cookie to be updated.
-     *
-     **/
+     * Set by {@link #setLocale(Locale)} when the locale is changed; this allows the locale cookie to be updated.
+     */
 
     private boolean _localeChanged;
 
     /**
-     *  The specification for the application, which
-     *  lives in the {@link ServletContext}.  If the
-     *  session (and application) moves to a different context (i.e.,
-     *  a different JVM), then
-     *  we want to reconnect to the specification in the new context.
-     *  A check is made on every request
-     *  cycle as needed.
-     *
-     **/
+     * The specification for the application, which lives in the {@link ServletContext}.  If the session (and
+     * application) moves to a different context (i.e., a different JVM), then we want to reconnect to the specification
+     * in the new context. A check is made on every request cycle as needed.
+     */
 
     protected transient IApplicationSpecification _specification;
 
     /**
-     *  The source for template data. The template source is stored
-     *  in the {@link ServletContext} as a named attribute.
-     *  After de-serialization, the application can re-connect to
-     *  the template source (or create a new one).
-     *
-     **/
+     * The source for template data. The template source is stored in the {@link ServletContext} as a named attribute.
+     * After de-serialization, the application can re-connect to the template source (or create a new one).
+     */
 
     protected transient ITemplateSource _templateSource;
 
     /**
-     *  The source for component specifications, stored in the
-     *  {@link ServletContext} (like {@link #_templateSource}).
-     *
-     **/
+     * The source for component specifications, stored in the {@link ServletContext} (like {@link #_templateSource}).
+     */
 
     protected transient ISpecificationSource _specificationSource;
 
     /**
-     *  The source for parsed scripts, again, stored in the
-     *  {@link ServletContext}.
+     * The source for parsed scripts, again, stored in the {@link ServletContext}.
      *
-     *  @since 1.0.2
-     *
-     **/
+     * @since 1.0.2
+     */
 
     private transient IScriptSource _scriptSource;
 
     /**
-     *  The name of the context attribute for the {@link IScriptSource} instance.
-     *  The application's name is appended.
+     * The name of the context attribute for the {@link IScriptSource} instance. The application's name is appended.
      *
-     *  @since 1.0.2
-     *
-     **/
+     * @since 1.0.2
+     */
 
     protected static final String SCRIPT_SOURCE_NAME = "org.apache.tapestry.ScriptSource";
 
     /**
-     *  The name of the context attribute for the {@link IComponentMessagesSource}
-     *  instance.  The application's name is appended.
+     * The name of the context attribute for the {@link IComponentMessagesSource} instance.  The application's name is
+     * appended.
      *
-     *  @since 2.0.4
-     *
-     **/
+     * @since 2.0.4
+     */
 
     protected static final String STRINGS_SOURCE_NAME = "org.apache.tapestry.StringsSource";
 
     private transient IComponentMessagesSource _stringsSource;
 
     /**
-     *  The name of the application specification property used to specify the
-     *  class of the visit object.
-     *
-     **/
+     * The name of the application specification property used to specify the class of the visit object.
+     */
 
     public static final String VISIT_CLASS_PROPERTY_NAME = "org.apache.tapestry.visit-class";
 
     /**
-     *  Servlet context attribute name for the default {@link ITemplateSource}
-     *  instance.  The application's name is appended.
-     *
-     **/
+     * Servlet context attribute name for the default {@link ITemplateSource} instance.  The application's name is
+     * appended.
+     */
 
     protected static final String TEMPLATE_SOURCE_NAME = "org.apache.tapestry.TemplateSource";
 
     /**
-     *  Servlet context attribute name for the default {@link ISpecificationSource}
-     *  instance.  The application's name is appended.
-     *
-     **/
+     * Servlet context attribute name for the default {@link ISpecificationSource} instance.  The application's name is
+     * appended.
+     */
 
     protected static final String SPECIFICATION_SOURCE_NAME =
             "org.apache.tapestry.SpecificationSource";
 
     /**
-     *  Servlet context attribute name for the {@link IPageSource}
-     *  instance.  The application's name is appended.
-     *
-     **/
+     * Servlet context attribute name for the {@link IPageSource} instance.  The application's name is appended.
+     */
 
     protected static final String PAGE_SOURCE_NAME = "org.apache.tapestry.PageSource";
 
     /**
-     *  Servlet context attribute name for a shared instance
-     *  of {@link DataSqueezer}.  The instance is actually shared
-     *  between Tapestry applications within the same context
-     *  (which will have the same ClassLoader).
+     * Servlet context attribute name for a shared instance of {@link DataSqueezer}.  The instance is actually shared
+     * between Tapestry applications within the same context (which will have the same ClassLoader).
      *
-     *  @since 2.2
-     *
-     **/
+     * @since 2.2
+     */
 
     protected static final String DATA_SQUEEZER_NAME = "org.apache.tapestry.DataSqueezer";
 
     /**
-     * Servlet context attribute name for a shared instance
-     * of {@link ResourceChecksumSource}.
+     * Servlet context attribute name for a shared instance of {@link ResourceChecksumSource}.
+     *
      * @since 3.0.3
      */
     protected static final String RESOURCE_CHECKSUM_SOURCE_NAME =
             "org.apache.tapestry.ResourceChecksumSource";
 
     /**
-     *  The source for pages, which acts as a pool, but is capable of
-     *  creating pages as needed.  Stored in the
-     *  {@link ServletContext}, like {@link #_templateSource}.
-     *
-     **/
+     * The source for pages, which acts as a pool, but is capable of creating pages as needed.  Stored in the {@link
+     * ServletContext}, like {@link #_templateSource}.
+     */
 
     private transient IPageSource _pageSource;
 
     /**
-     *  If true (set from JVM system parameter
-     *  <code>org.apache.tapestry.enable-reset-service</code>)
-     *  then the reset service will be enabled, allowing
-     *  the cache of pages, specifications and template
-     *  to be cleared on demand.
-     *
-     **/
+     * If true (set from JVM system parameter <code>org.apache.tapestry.enable-reset-service</code>) then the reset
+     * service will be enabled, allowing the cache of pages, specifications and template to be cleared on demand.
+     */
 
     private static final boolean _resetServiceEnabled =
             Boolean.getBoolean("org.apache.tapestry.enable-reset-service");
 
     /**
-     * If true (set from the JVM system parameter
-     * <code>org.apache.tapestry.disable-caching</code>)
-     * then the cache of pages, specifications and template
-     * will be cleared after each request.
-     *
-     **/
+     * If true (set from the JVM system parameter <code>org.apache.tapestry.disable-caching</code>) then the cache of
+     * pages, specifications and template will be cleared after each request.
+     */
 
     private static final boolean _disableCaching =
             Boolean.getBoolean("org.apache.tapestry.disable-caching");
@@ -330,65 +270,58 @@
     private transient IResourceResolver _resolver;
 
     /**
-     *  Constant used to store a {@link org.apache.tapestry.util.IPropertyHolder}
-     *  in the servlet context.
+     * Constant used to store a {@link org.apache.tapestry.util.IPropertyHolder} in the servlet context.
      *
-     *  @since 2.3
-     *
-     **/
+     * @since 2.3
+     */
 
     protected static final String PROPERTY_SOURCE_NAME = "org.apache.tapestry.PropertySource";
 
     /**
-     *  A shared instance of {@link IPropertySource}
+     * A shared instance of {@link IPropertySource}
      *
-     *  @since 3.0
-     *  @see #createPropertySource(RequestContext)
-     *
-     **/
+     * @see #createPropertySource(RequestContext)
+     * @since 3.0
+     */
 
     private transient IPropertySource _propertySource;
 
     /**
-     *  Map from service name to service instance.
+     * Map from service name to service instance.
      *
-     *  @since 1.0.9
-     *
-     **/
+     * @since 1.0.9
+     */
 
     private transient Map _serviceMap;
 
     protected static final String SERVICE_MAP_NAME = "org.apache.tapestry.ServiceMap";
 
     /**
-     *  A shared instance of {@link Pool}.
+     * A shared instance of {@link Pool}.
      *
-     *  @since 3.0
-     *  @see #createPool(RequestContext)
-     *
-     **/
+     * @see #createPool(RequestContext)
+     * @since 3.0
+     */
 
     private transient Pool _pool;
 
     protected static final String POOL_NAME = "org.apache.tapestry.Pool";
 
     /**
-     *  Name of a shared instance of {@link org.apache.tapestry.engine.IComponentClassEnhancer}
-     *  stored in the {@link ServletContext}.
+     * Name of a shared instance of {@link org.apache.tapestry.engine.IComponentClassEnhancer} stored in the {@link
+     * ServletContext}.
      *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     protected static final String ENHANCER_NAME = "org.apache.tapestry.ComponentClassEnhancer";
 
     /**
-     *  A shared instance of {@link org.apache.tapestry.engine.IComponentClassEnhancer}.
+     * A shared instance of {@link org.apache.tapestry.engine.IComponentClassEnhancer}.
      *
-     *  @since 3.0
-     *  @see #createComponentClassEnhancer(RequestContext)
-     *
-     **/
+     * @see #createComponentClassEnhancer(RequestContext)
+     * @since 3.0
+     */
 
     private transient IComponentClassEnhancer _enhancer;
 
@@ -397,14 +330,11 @@
     private transient IEnhancedClassFactory _classFactory;
 
     /**
-     *  Set to true when there is a (potential)
-     *  change to the internal state of the engine, set
-     *  to false when the engine is stored into the
-     *  {@link HttpSession}.
+     * Set to true when there is a (potential) change to the internal state of the engine, set to false when the engine
+     * is stored into the {@link HttpSession}.
      *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     private transient boolean _dirty;
 
@@ -418,14 +348,15 @@
 
     /**
      * Used to obtain resource checksums for the asset service.
+     *
      * @since 3.0.3
      */
     private transient ResourceChecksumSource _resourceChecksumSource;
 
     /**
-     *  The name of the context attribute for the {@link ExpressionEvaluator} instance.
-     *  The application's name is appended.
-     **/
+     * The name of the context attribute for the {@link ExpressionEvaluator} instance. The application's name is
+     * appended.
+     */
     protected static final String EXPRESSION_EVALUATOR_NAME = "org.apache.tapestry.engine.ExpressionEvaluator";
 
     private transient ExpressionEvaluator _expressionEvaluator;
@@ -435,12 +366,11 @@
     private transient String _outputEncoding;
 
     /**
-     *  Sets the Exception page's exception property, then renders the Exception page.
-     *
-     *  <p>If the render throws an exception, then copious output is sent to
-     *  <code>System.err</code> and a {@link ServletException} is thrown.
-     *
-     **/
+     * Sets the Exception page's exception property, then renders the Exception page.
+     * <p/>
+     * <p>If the render throws an exception, then copious output is sent to <code>System.err</code> and a {@link
+     * ServletException} is thrown.
+     */
 
     protected void activateExceptionPage(
             IRequestCycle cycle,
@@ -482,9 +412,8 @@
     }
 
     /**
-     *  Writes a detailed report of the exception to <code>System.err</code>.
-     *
-     **/
+     * Writes a detailed report of the exception to <code>System.err</code>.
+     */
 
     public void reportException(String reportTitle, Throwable ex)
     {
@@ -496,10 +425,10 @@
 
         System.err.println(
                 "\n\n      Session id: "
-                + _sessionId
-                + "\n  Client address: "
-                + _clientAddress
-                + "\n\nExceptions:\n");
+                        + _sessionId
+                        + "\n  Client address: "
+                        + _clientAddress
+                        + "\n\nExceptions:\n");
 
         new ExceptionAnalyzer().reportException(ex, System.err);
 
@@ -508,22 +437,18 @@
     }
 
     /**
-     *  Invoked at the end of the request cycle to release any resources specific
-     *  to the request cycle.
-     *
-     **/
+     * Invoked at the end of the request cycle to release any resources specific to the request cycle.
+     */
 
     protected abstract void cleanupAfterRequest(IRequestCycle cycle);
 
     /**
-     *  Extends the description of the class generated by {@link #toString()}.
-     *  If a subclass adds additional instance variables that should be described
-     *  in the instance description, it may overide this method. This implementation
-     *  does nothing.
+     * Extends the description of the class generated by {@link #toString()}. If a subclass adds additional instance
+     * variables that should be described in the instance description, it may overide this method. This implementation
+     * does nothing.
      *
-     *  @see #toString()
-     *
-     **/
+     * @see #toString()
+     */
 
     protected void extendDescription(ToStringBuilder builder)
     {
@@ -531,11 +456,9 @@
     }
 
     /**
-     *  Returns the locale for the engine.  This is initially set
-     *  by the {@link ApplicationServlet} but may be updated
-     *  by the application.
-     *
-     **/
+     * Returns the locale for the engine.  This is initially set by the {@link ApplicationServlet} but may be updated by
+     * the application.
+     */
 
     public Locale getLocale()
     {
@@ -543,20 +466,15 @@
     }
 
     /**
-     * Overriden in subclasses that support monitoring.  Should create and return
-     * an instance of {@link IMonitor} that is appropriate for the request cycle described
-     * by the {@link RequestContext}.
-     *
+     * Overriden in subclasses that support monitoring.  Should create and return an instance of {@link IMonitor} that
+     * is appropriate for the request cycle described by the {@link RequestContext}.
+     * <p/>
      * <p>The monitor is used to create a {@link RequestCycle}.
-     *
-     * <p>This implementation uses a {@link IMonitorFactory}
-     * to create the monitor instance.  The factory
-     * is provided as an application extension.  If the application
-     * extension does not exist, {@link DefaultMonitorFactory} is used.
-     *
+     * <p/>
+     * <p>This implementation uses a {@link IMonitorFactory} to create the monitor instance.  The factory is provided as
+     * an application extension.  If the application extension does not exist, {@link DefaultMonitorFactory} is used.
+     * <p/>
      * <p>As of release 3.0, this method should <em>not</em> return null.
-     *
-     *
      */
 
     public IMonitor getMonitor(RequestContext context)
@@ -581,9 +499,9 @@
     }
 
     /**
-     *  Returns a service with the given name.  Services are created by the
-     *  first call to {@link #setupForRequest(RequestContext)}.
-     **/
+     * Returns a service with the given name.  Services are created by the first call to {@link
+     * #setupForRequest(RequestContext)}.
+     */
 
     public IEngineService getService(String name)
     {
@@ -602,12 +520,11 @@
     }
 
     /**
-     * Returns the context path, the prefix to apply to any URLs so that they
-     * are recognized as belonging to the Servlet 2.2 context.
+     * Returns the context path, the prefix to apply to any URLs so that they are recognized as belonging to the Servlet
+     * 2.2 context.
      *
-     *  @see org.apache.tapestry.asset.ContextAsset
-     *
-     **/
+     * @see org.apache.tapestry.asset.ContextAsset
+     */
 
     public String getContextPath()
     {
@@ -615,15 +532,12 @@
     }
 
     /**
-     *  Returns the specification, if available, or null otherwise.
-     *
-     *  <p>To facilitate deployment across multiple servlet containers, the
-     *  application is serializable.  However, the reference to the specification
-     *  is transient.   When an application instance is deserialized, it reconnects
-     *  with the application specification by locating it in the {@link ServletContext}
-     *  or parsing it fresh.
-     *
-     **/
+     * Returns the specification, if available, or null otherwise.
+     * <p/>
+     * <p>To facilitate deployment across multiple servlet containers, the application is serializable.  However, the
+     * reference to the specification is transient.   When an application instance is deserialized, it reconnects with
+     * the application specification by locating it in the {@link ServletContext} or parsing it fresh.
+     */
 
     public IApplicationSpecification getSpecification()
     {
@@ -641,11 +555,11 @@
     }
 
     /**
-     *  Reads the state serialized by {@link #writeExternal(ObjectOutput)}.
-     *
-     *  <p>This always set the stateful flag.  By default, a deserialized
-     *  session is stateful (else, it would not have been serialized).
-     **/
+     * Reads the state serialized by {@link #writeExternal(ObjectOutput)}.
+     * <p/>
+     * <p>This always set the stateful flag.  By default, a deserialized session is stateful (else, it would not have
+     * been serialized).
+     */
 
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
     {
@@ -658,14 +572,10 @@
     }
 
     /**
-     *  Writes the following properties:
-     *
-     *  <ul>
-     *  <li>locale name ({@link Locale#toString()})
-     *  <li>visit
-     *  </ul>
-     *
-     **/
+     * Writes the following properties:
+     * <p/>
+     * <ul> <li>locale name ({@link Locale#toString()}) <li>visit </ul>
+     */
 
     public void writeExternal(ObjectOutput out) throws IOException
     {
@@ -674,10 +584,9 @@
     }
 
     /**
-     *  Invoked, typically, when an exception occurs while servicing the request.
-     *  This method resets the output, sets the new page and renders it.
-     *
-     **/
+     * Invoked, typically, when an exception occurs while servicing the request. This method resets the output, sets the
+     * new page and renders it.
+     */
 
     protected void redirect(
             String pageName,
@@ -753,13 +662,11 @@
     }
 
     /**
-     * Invalidates the session, then redirects the client web browser to
-     * the servlet's prefix, starting a new visit.
-     *
-     * <p>Subclasses should perform their own restart (if necessary, which is
-     * rarely) before invoking this implementation.
-     *
-     **/
+     * Invalidates the session, then redirects the client web browser to the servlet's prefix, starting a new visit.
+     * <p/>
+     * <p>Subclasses should perform their own restart (if necessary, which is rarely) before invoking this
+     * implementation.
+     */
 
     public void restart(IRequestCycle cycle) throws IOException
     {
@@ -793,9 +700,8 @@
     }
 
     /**
-     *  Delegate method for the servlet.  Services the request.
-     *
-     **/
+     * Delegate method for the servlet.  Services the request.
+     */
 
     public boolean service(RequestContext context) throws ServletException, IOException
     {
@@ -959,14 +865,13 @@
     }
 
     /**
-     *  Handles {@link PageRedirectException} which involves
-     *  executing {@link IPage#validate(IRequestCycle)} on the target page
-     *  (of the exception), until either a loop is found, or a page
-     *  succesfully validates and can be activated.
+     * Handles {@link PageRedirectException} which involves executing {@link IPage#validate(IRequestCycle)} on the
+     * target page (of the exception), until either a loop is found, or a page succesfully validates and can be
+     * activated.
+     * <p/>
+     * <p>This should generally not be overriden in subclasses.
      *
-     *  <p>This should generally not be overriden in subclasses.
-     *
-     *  @since 3.0
+     * @since 3.0
      */
 
     protected void handlePageRedirectException(
@@ -1029,13 +934,11 @@
     }
 
     /**
-     *  Invoked from {@link #service(RequestContext)} to create an instance of
-     *  {@link IRequestCycle} for the current request.  This implementation creates
-     *  an returns an instance of {@link RequestCycle}.
+     * Invoked from {@link #service(RequestContext)} to create an instance of {@link IRequestCycle} for the current
+     * request.  This implementation creates an returns an instance of {@link RequestCycle}.
      *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     protected IRequestCycle createRequestCycle(
             RequestContext context,
@@ -1046,29 +949,20 @@
     }
 
     /**
-     *  Invoked by {@link #service(RequestContext)} if a {@link StaleLinkException}
-     *  is thrown by the {@link IEngineService service}.  This implementation
-     *  sets the message property of the StaleLink page to the
-     *  message provided in the exception,
-     *  then invokes
-     *  {@link #redirect(String, IRequestCycle, ResponseOutputStream, ApplicationRuntimeException)}
-     *  to render the StaleLink page.
+     * Invoked by {@link #service(RequestContext)} if a {@link StaleLinkException} is thrown by the {@link
+     * IEngineService service}.  This implementation sets the message property of the StaleLink page to the message
+     * provided in the exception, then invokes {@link #redirect(String, IRequestCycle, ResponseOutputStream,
+     * ApplicationRuntimeException)} to render the StaleLink page.
+     * <p/>
+     * <p>Subclasses may overide this method (without invoking this implementation).  A common practice is to present an
+     * error message on the application's Home page.
+     * <p/>
+     * <p>Alternately, the application may provide its own version of the StaleLink page, overriding the framework's
+     * implementation (probably a good idea, because the default page hints at "application errors" and isn't
+     * localized). The overriding StaleLink implementation must implement a message property of type String.
      *
-     *  <p>Subclasses may overide this method (without
-     *  invoking this implementation).  A common practice
-     *  is to present an error message on the application's
-     *  Home page.
-     *
-     *  <p>Alternately, the application may provide its own version of
-     *  the StaleLink page, overriding
-     *  the framework's implementation (probably a good idea, because the
-     *  default page hints at "application errors" and isn't localized).
-     *  The overriding StaleLink implementation must
-     *  implement a message property of type String.
-     *
-     *  @since 0.2.10
-     *
-     **/
+     * @since 0.2.10
+     */
 
     protected void handleStaleLinkException(
             StaleLinkException ex,
@@ -1085,19 +979,15 @@
     }
 
     /**
-     *  Invoked by {@link #service(RequestContext)} if a {@link StaleSessionException}
-     *  is thrown by the {@link IEngineService service}.  This implementation
-     *  invokes
-     *  {@link #redirect(String, IRequestCycle, ResponseOutputStream, ApplicationRuntimeException)}
-     *  to render the StaleSession page.
+     * Invoked by {@link #service(RequestContext)} if a {@link StaleSessionException} is thrown by the {@link
+     * IEngineService service}.  This implementation invokes {@link #redirect(String, IRequestCycle,
+     * ResponseOutputStream, ApplicationRuntimeException)} to render the StaleSession page.
+     * <p/>
+     * <p>Subclasses may overide this method (without invoking this implementation).  A common practice is to present an
+     * eror message on the application's Home page.
      *
-     *  <p>Subclasses may overide this method (without
-     *  invoking this implementation).  A common practice
-     *  is to present an eror message on the application's
-     *  Home page.
-     *
-     *  @since 0.2.10
-     **/
+     * @since 0.2.10
+     */
 
     protected void handleStaleSessionException(
             StaleSessionException ex,
@@ -1109,13 +999,11 @@
     }
 
     /**
-     *  Discards all cached pages, component specifications and templates.
-     *  Subclasses who override this method should invoke this implementation
-     *  as well.
+     * Discards all cached pages, component specifications and templates. Subclasses who override this method should
+     * invoke this implementation as well.
      *
-     *  @since 1.0.1
-     *
-     **/
+     * @since 1.0.1
+     */
 
     public void clearCachedData()
     {
@@ -1133,9 +1021,8 @@
     }
 
     /**
-     *  Changes the locale for the engine.
-     *
-     **/
+     * Changes the locale for the engine.
+     */
 
     public void setLocale(Locale value)
     {
@@ -1154,44 +1041,30 @@
     }
 
     /**
-     *  Invoked from {@link #service(RequestContext)} to ensure that the engine's
-     *  instance variables are setup.  This allows the application a chance to
-     *  restore transient variables that will not have survived deserialization.
-     *
-     *  Determines the servlet prefix:  this is the base URL used by
-     *  {@link IEngineService services} to build URLs.  It consists
-     *  of two parts:  the context path and the servlet path.
-     *
-     *  <p>The servlet path is retrieved from {@link HttpServletRequest#getServletPath()}.
-     *
-     *  <p>The context path is retrieved from {@link HttpServletRequest#getContextPath()}.
-     *
-     *  <p>The global object is retrieved from {@link IEngine#getGlobal()} method.
-     *
-     *  <p>The final path is available via the {@link #getServletPath()} method.
-     *
-     *  <p>In addition, this method locates and/or creates the:
-     *  <ul>
-     *  <li>{@link IComponentClassEnhancer}
-     *  <li>{@link Pool}
-     *  <li>{@link ITemplateSource}
-     *  <li>{@link ISpecificationSource}
-     *  <li>{@link IPageSource}
-     *  <li>{@link IEngineService} {@link Map}
-     *  <ll>{@link IScriptSource}
-     *  <li>{@link IComponentMessagesSource}
-     *  <li>{@link IPropertySource}
-     *  </ul>
-     *
-     *  <p>This order is important, because some of the later shared objects
-     *  depend on some of the earlier shared objects already having
-     *  been located or created
-     *  (especially {@link #getPool() pool}).
-     *
-     *  <p>Subclasses should invoke this implementation first, then perform their
-     *  own setup.
-     *
-     **/
+     * Invoked from {@link #service(RequestContext)} to ensure that the engine's instance variables are setup.  This
+     * allows the application a chance to restore transient variables that will not have survived deserialization.
+     * <p/>
+     * Determines the servlet prefix:  this is the base URL used by {@link IEngineService services} to build URLs.  It
+     * consists of two parts:  the context path and the servlet path.
+     * <p/>
+     * <p>The servlet path is retrieved from {@link HttpServletRequest#getServletPath()}.
+     * <p/>
+     * <p>The context path is retrieved from {@link HttpServletRequest#getContextPath()}.
+     * <p/>
+     * <p>The global object is retrieved from {@link IEngine#getGlobal()} method.
+     * <p/>
+     * <p>The final path is available via the {@link #getServletPath()} method.
+     * <p/>
+     * <p>In addition, this method locates and/or creates the: <ul> <li>{@link IComponentClassEnhancer} <li>{@link Pool}
+     * <li>{@link ITemplateSource} <li>{@link ISpecificationSource} <li>{@link IPageSource} <li>{@link IEngineService}
+     * {@link Map} <ll>{@link IScriptSource} <li>{@link IComponentMessagesSource} <li>{@link IPropertySource} </ul>
+     * <p/>
+     * <p>This order is important, because some of the later shared objects depend on some of the earlier shared objects
+     * already having been located or created (especially {@link #getPool() pool}).
+     * <p/>
+     * <p>Subclasses should invoke this implementation first, then perform their own setup. They must also synchronize
+     * on the {@link org.apache.tapestry.request.RequestContext#getServlet() application servlet}.
+     */
 
     protected void setupForRequest(RequestContext context)
     {
@@ -1200,6 +1073,7 @@
         HttpServletRequest request = context.getRequest();
         HttpSession session = context.getSession();
 
+
         if (session != null)
             _sessionId = context.getSession().getId();
         else
@@ -1243,386 +1117,216 @@
 
         String servletName = context.getServlet().getServletName();
 
-        if (_propertySource == null)
+        // Synchronize on the servlet to make sure that two different IEngine instances
+        // do not try ot create some of the common dependencies simulataneously. We enclose
+        // all the code that uses the ServletContext as a cache.  This is the motivation for
+        // adding an IoC container to Tapestry 4.
+
+        // Note: by borrowing ConcurrentBarrier from Tapestry 5, we could perhaps optimize this
+        // a bit ... but in most cases, we'll "flit" into the synchronized block, see non-nulls
+        // for all the fields, and "flit" back out with virtually no chance of contention.
+
+        synchronized (servlet)
         {
-            String name = PROPERTY_SOURCE_NAME + ":" + servletName;
-
-            _propertySource = (IPropertySource) servletContext.getAttribute(name);
-
             if (_propertySource == null)
             {
-                try
+                String name = PROPERTY_SOURCE_NAME + ":" + servletName;
+
+                _propertySource = (IPropertySource) servletContext.getAttribute(name);
+
+                if (_propertySource == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _propertySource = createPropertySource(context);
 
-                    _propertySource = (IPropertySource) servletContext.getAttribute(name);
-
-                    if (_propertySource == null)
-                    {
-                        _propertySource = createPropertySource(context);
-
-                        servletContext.setAttribute(name, _propertySource);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _propertySource);
                 }
             }
-        }
-
-        if (_classFactory == null)
-        {
-            String name = CLASS_FACTORY_NAME + ":" + servletName;
-
-            _classFactory = (IEnhancedClassFactory) servletContext.getAttribute(name);
 
             if (_classFactory == null)
             {
-                try
+                String name = CLASS_FACTORY_NAME + ":" + servletName;
+
+                _classFactory = (IEnhancedClassFactory) servletContext.getAttribute(name);
+
+                if (_classFactory == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _classFactory = createClassFactory();
 
-                    _classFactory = (IEnhancedClassFactory) servletContext.getAttribute(name);
-
-                    if (_classFactory == null)
-                    {
-                        _classFactory = createClassFactory();
-
-                        servletContext.setAttribute(name, _classFactory);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _classFactory);
                 }
             }
-        }
-
-        if (_enhancer == null)
-        {
-            String name = ENHANCER_NAME + ":" + servletName;
-
-            _enhancer = (IComponentClassEnhancer) servletContext.getAttribute(name);
 
             if (_enhancer == null)
             {
-                try
+                String name = ENHANCER_NAME + ":" + servletName;
+
+                _enhancer = (IComponentClassEnhancer) servletContext.getAttribute(name);
+
+                if (_enhancer == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _enhancer = createComponentClassEnhancer(context);
 
-                    _enhancer = (IComponentClassEnhancer) servletContext.getAttribute(name);
-
-                    if (_enhancer == null)
-                    {
-                        _enhancer = createComponentClassEnhancer(context);
-
-                        servletContext.setAttribute(name, _enhancer);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _enhancer);
                 }
             }
-        }
-
-        if (_pool == null)
-        {
-            String name = POOL_NAME + ":" + servletName;
-
-            _pool = (Pool) servletContext.getAttribute(name);
 
             if (_pool == null)
             {
-                try
-                {
-                    context.getServlet().getLock().lock();
+                String name = POOL_NAME + ":" + servletName;
 
-                    _pool = (Pool) servletContext.getAttribute(name);
+                _pool = (Pool) servletContext.getAttribute(name);
 
-                    if (_pool == null)
-                    {
-                        _pool = createPool(context);
+                _pool = createPool(context);
 
-                        servletContext.setAttribute(name, _pool);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
-                }
             }
-        }
-
-        if (_templateSource == null)
-        {
-            String name = TEMPLATE_SOURCE_NAME + ":" + servletName;
-
-            _templateSource = (ITemplateSource) servletContext.getAttribute(name);
 
             if (_templateSource == null)
             {
-                try
+                String name = TEMPLATE_SOURCE_NAME + ":" + servletName;
+
+                _templateSource = (ITemplateSource) servletContext.getAttribute(name);
+
+                if (_templateSource == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _templateSource = createTemplateSource(context);
 
-                    _templateSource = (ITemplateSource) servletContext.getAttribute(name);
-
-                    if (_templateSource == null)
-                    {
-                        _templateSource = createTemplateSource(context);
-
-                        servletContext.setAttribute(name, _templateSource);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _templateSource);
                 }
             }
-        }
-
-        if (_specificationSource == null)
-        {
-            String name = SPECIFICATION_SOURCE_NAME + ":" + servletName;
-
-            _specificationSource = (ISpecificationSource) servletContext.getAttribute(name);
 
             if (_specificationSource == null)
             {
-                try
+                String name = SPECIFICATION_SOURCE_NAME + ":" + servletName;
+
+                _specificationSource = (ISpecificationSource) servletContext.getAttribute(name);
+
+                if (_specificationSource == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _specificationSource = createSpecificationSource(context);
 
-                    _specificationSource = (ISpecificationSource) servletContext.getAttribute(name);
-
-                    if (_specificationSource == null)
-                    {
-                        _specificationSource = createSpecificationSource(context);
-
-                        servletContext.setAttribute(name, _specificationSource);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _specificationSource);
                 }
             }
-        }
-
-        if (_pageSource == null)
-        {
-            String name = PAGE_SOURCE_NAME + ":" + servletName;
-
-            _pageSource = (IPageSource) servletContext.getAttribute(name);
 
             if (_pageSource == null)
             {
-                try
+                String name = PAGE_SOURCE_NAME + ":" + servletName;
+
+                _pageSource = (IPageSource) servletContext.getAttribute(name);
+
+                if (_pageSource == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _pageSource = createPageSource(context);
 
-                    _pageSource = (IPageSource) servletContext.getAttribute(name);
-
-                    if (_pageSource == null)
-                    {
-                        _pageSource = createPageSource(context);
-
-                        servletContext.setAttribute(name, _pageSource);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _pageSource);
                 }
             }
-        }
-
-        if (_scriptSource == null)
-        {
-            String name = SCRIPT_SOURCE_NAME + ":" + servletName;
-
-            _scriptSource = (IScriptSource) servletContext.getAttribute(name);
 
             if (_scriptSource == null)
             {
-                try
+                String name = SCRIPT_SOURCE_NAME + ":" + servletName;
+
+                _scriptSource = (IScriptSource) servletContext.getAttribute(name);
+
+                if (_scriptSource == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _scriptSource = createScriptSource(context);
 
-                    _scriptSource = (IScriptSource) servletContext.getAttribute(name);
-
-                    if (_scriptSource == null)
-                    {
-                        _scriptSource = createScriptSource(context);
-
-                        servletContext.setAttribute(name, _scriptSource);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _scriptSource);
                 }
             }
-        }
-
-        if (_serviceMap == null)
-        {
-            String name = SERVICE_MAP_NAME + ":" + servletName;
-
-            _serviceMap = (Map) servletContext.getAttribute(name);
 
             if (_serviceMap == null)
             {
-                try
+                String name = SERVICE_MAP_NAME + ":" + servletName;
+
+                _serviceMap = (Map) servletContext.getAttribute(name);
+
+                if (_serviceMap == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _serviceMap = createServiceMap();
 
-                    _serviceMap = (Map) servletContext.getAttribute(name);
-
-                    if (_serviceMap == null)
-                    {
-                        _serviceMap = createServiceMap();
-
-                        servletContext.setAttribute(name, _serviceMap);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _serviceMap);
                 }
             }
-        }
-
-        if (_stringsSource == null)
-        {
-            String name = STRINGS_SOURCE_NAME + ":" + servletName;
-
-            _stringsSource = (IComponentMessagesSource) servletContext.getAttribute(name);
 
             if (_stringsSource == null)
             {
-                try
+                String name = STRINGS_SOURCE_NAME + ":" + servletName;
+
+                _stringsSource = (IComponentMessagesSource) servletContext.getAttribute(name);
+
+                if (_stringsSource == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _stringsSource = createComponentStringsSource(context);
 
-                    _stringsSource = (IComponentMessagesSource) servletContext.getAttribute(name);
-
-                    if (_stringsSource == null)
-                    {
-                        _stringsSource = createComponentStringsSource(context);
-
-                        servletContext.setAttribute(name, _stringsSource);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _stringsSource);
                 }
             }
-        }
-
-        if (_dataSqueezer == null)
-        {
-            String name = DATA_SQUEEZER_NAME + ":" + servletName;
-
-            _dataSqueezer = (DataSqueezer) servletContext.getAttribute(name);
 
             if (_dataSqueezer == null)
             {
-                try
+                String name = DATA_SQUEEZER_NAME + ":" + servletName;
+
+                _dataSqueezer = (DataSqueezer) servletContext.getAttribute(name);
+
+                if (_dataSqueezer == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _dataSqueezer = createDataSqueezer();
 
-                    _dataSqueezer = (DataSqueezer) servletContext.getAttribute(name);
-
-                    if (_dataSqueezer == null)
-                    {
-                        _dataSqueezer = createDataSqueezer();
-
-                        servletContext.setAttribute(name, _dataSqueezer);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _dataSqueezer);
                 }
             }
-        }
-
-        if (_global == null)
-        {
-            String name = GLOBAL_NAME + ":" + servletName;
-
-            _global = servletContext.getAttribute(name);
 
             if (_global == null)
             {
-                try
+                String name = GLOBAL_NAME + ":" + servletName;
+
+                _global = servletContext.getAttribute(name);
+
+                if (_global == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _global = createGlobal(context);
 
-                    _global = servletContext.getAttribute(name);
-
-                    if (_global == null)
-                    {
-                        _global = createGlobal(context);
-
-                        servletContext.setAttribute(name, _global);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _global);
                 }
             }
-        }
-
-        if (_resourceChecksumSource == null)
-        {
-            String name = RESOURCE_CHECKSUM_SOURCE_NAME + ":" + servletName;
-
-            _resourceChecksumSource = (ResourceChecksumSource) servletContext.getAttribute(name);
 
             if (_resourceChecksumSource == null)
             {
-                try
+                String name = RESOURCE_CHECKSUM_SOURCE_NAME + ":" + servletName;
+
+                _resourceChecksumSource = (ResourceChecksumSource) servletContext.getAttribute(name);
+
+                if (_resourceChecksumSource == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _resourceChecksumSource = createResourceChecksumSource();
 
-                    _resourceChecksumSource = (ResourceChecksumSource) servletContext.getAttribute(name);
-
-                    if (_resourceChecksumSource == null)
-                    {
-                        _resourceChecksumSource = createResourceChecksumSource();
-
-                        servletContext.setAttribute(name, _resourceChecksumSource);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _resourceChecksumSource);
                 }
             }
-        }
-
-        if (_expressionEvaluator == null)
-        {
-            String name = EXPRESSION_EVALUATOR_NAME + ":" + servletName;
-
-            _expressionEvaluator = (ExpressionEvaluator) servletContext.getAttribute(name);
 
             if (_expressionEvaluator == null)
             {
-                try
+                String name = EXPRESSION_EVALUATOR_NAME + ":" + servletName;
+
+                _expressionEvaluator = (ExpressionEvaluator) servletContext.getAttribute(name);
+
+                if (_expressionEvaluator == null)
                 {
-                    context.getServlet().getLock().lock();
+                    _expressionEvaluator = createExpressionEvaluator();
 
-                    _expressionEvaluator = (ExpressionEvaluator) servletContext.getAttribute(name);
-
-                    if (_expressionEvaluator == null)
-                    {
-                        _expressionEvaluator = createExpressionEvaluator();
-
-                        servletContext.setAttribute(name, _expressionEvaluator);
-                    }
-                } finally
-                {
-                    context.getServlet().getLock().unlock();
+                    servletContext.setAttribute(name, _expressionEvaluator);
                 }
             }
+
+            // That's the end of reading to and from the servlet context, so we can leave the block
+            // synchronized against the servlet.
         }
 
         String encoding = request.getCharacterEncoding();
         if (encoding == null)
+
         {
             encoding = getOutputEncoding();
             try
@@ -1647,14 +1351,12 @@
     }
 
     /**
+     * Invoked from {@link #setupForRequest(RequestContext)} to provide a new instance of {@link
+     * IComponentMessagesSource}.
      *
-     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
-     *  a new instance of {@link IComponentMessagesSource}.
-     *
-     *  @return an instance of {@link DefaultComponentMessagesSource}
-     *  @since 2.0.4
-     *
-     **/
+     * @return an instance of {@link DefaultComponentMessagesSource}
+     * @since 2.0.4
+     */
 
     public IComponentMessagesSource createComponentStringsSource(RequestContext context)
     {
@@ -1662,16 +1364,13 @@
     }
 
     /**
-     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
-     *  an instance of {@link IScriptSource} that will be stored into
-     *  the {@link ServletContext}.  Subclasses may override this method
-     *  to provide a different implementation.
+     * Invoked from {@link #setupForRequest(RequestContext)} to provide an instance of {@link IScriptSource} that will
+     * be stored into the {@link ServletContext}.  Subclasses may override this method to provide a different
+     * implementation.
      *
-     *
-     *  @return an instance of {@link DefaultScriptSource}
-     *  @since 1.0.9
-     *
-     **/
+     * @return an instance of {@link DefaultScriptSource}
+     * @since 1.0.9
+     */
 
     protected IScriptSource createScriptSource(RequestContext context)
     {
@@ -1679,15 +1378,13 @@
     }
 
     /**
-     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
-     *  an instance of {@link IPageSource} that will be stored into
-     *  the {@link ServletContext}.  Subclasses may override this method
-     *  to provide a different implementation.
+     * Invoked from {@link #setupForRequest(RequestContext)} to provide an instance of {@link IPageSource} that will be
+     * stored into the {@link ServletContext}.  Subclasses may override this method to provide a different
+     * implementation.
      *
-     *  @return an instance of {@link PageSource}
-     *  @since 1.0.9
-     *
-     **/
+     * @return an instance of {@link PageSource}
+     * @since 1.0.9
+     */
 
     protected IPageSource createPageSource(RequestContext context)
     {
@@ -1695,14 +1392,13 @@
     }
 
     /**
-     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
-     *  an instance of {@link ISpecificationSource} that will be stored into
-     *  the {@link ServletContext}.  Subclasses may override this method
-     *  to provide a different implementation.
+     * Invoked from {@link #setupForRequest(RequestContext)} to provide an instance of {@link ISpecificationSource} that
+     * will be stored into the {@link ServletContext}.  Subclasses may override this method to provide a different
+     * implementation.
      *
-     *  @return an instance of {@link DefaultSpecificationSource}
-     *  @since 1.0.9
-     **/
+     * @return an instance of {@link DefaultSpecificationSource}
+     * @since 1.0.9
+     */
 
     protected ISpecificationSource createSpecificationSource(RequestContext context)
     {
@@ -1710,15 +1406,13 @@
     }
 
     /**
-     *  Invoked from {@link #setupForRequest(RequestContext)} to provide
-     *  an instance of {@link ITemplateSource} that will be stored into
-     *  the {@link ServletContext}.  Subclasses may override this method
-     *  to provide a different implementation.
+     * Invoked from {@link #setupForRequest(RequestContext)} to provide an instance of {@link ITemplateSource} that will
+     * be stored into the {@link ServletContext}.  Subclasses may override this method to provide a different
+     * implementation.
      *
-     *  @return an instance of {@link DefaultTemplateSource}
-     *  @since 1.0.9
-     *
-     **/
+     * @return an instance of {@link DefaultTemplateSource}
+     * @since 1.0.9
+     */
 
     protected ITemplateSource createTemplateSource(RequestContext context)
     {
@@ -1726,10 +1420,10 @@
     }
 
     /**
-     * Invoked from {@link #setupForRequest(RequestContext)} to provide
-     * an instance of {@link ResourceChecksumSource} that will be stored into
-     * the {@link ServletContext}.  Subclasses may override this method
-     * to provide a different implementation.
+     * Invoked from {@link #setupForRequest(RequestContext)} to provide an instance of {@link ResourceChecksumSource}
+     * that will be stored into the {@link ServletContext}.  Subclasses may override this method to provide a different
+     * implementation.
+     *
      * @return an instance of {@link ResourceChecksumSourceImpl} that uses MD5 and Hex encoding.
      * @since 3.0.3
      */
@@ -1737,7 +1431,7 @@
     {
         return new ResourceChecksumSourceImpl("MD5", new Hex());
     }
-    
+
     protected ExpressionEvaluator createExpressionEvaluator()
     {
         _expressionCache = (ExpressionCacheImpl) createExpressionCache();
@@ -1751,9 +1445,8 @@
     }
 
     /**
-     *  Returns an object which can find resources and classes.
-     *
-     **/
+     * Returns an object which can find resources and classes.
+     */
 
     public IResourceResolver getResourceResolver()
     {
@@ -1766,13 +1459,11 @@
     }
 
     /**
-     *  Generates a description of the instance.
-     *  Invokes {@link #extendDescription(ToStringBuilder)}
-     *  to fill in details about the instance.
+     * Generates a description of the instance. Invokes {@link #extendDescription(ToStringBuilder)} to fill in details
+     * about the instance.
      *
-     *  @see #extendDescription(ToStringBuilder)
-     *
-     **/
+     * @see #extendDescription(ToStringBuilder)
+     */
 
     public String toString()
     {
@@ -1781,8 +1472,8 @@
         builder.append(
                 "name",
                 _specification == null
-                        ? Tapestry.getMessage("AbstractEngine.unknown-specification")
-                        : _specification.getName());
+                ? Tapestry.getMessage("AbstractEngine.unknown-specification")
+                : _specification.getName());
 
         builder.append("dirty", _dirty);
         builder.append("locale", _locale);
@@ -1795,9 +1486,8 @@
     }
 
     /**
-     *  Returns true if the reset service is curently enabled.
-     *
-     **/
+     * Returns true if the reset service is curently enabled.
+     */
 
     public boolean isResetServiceEnabled()
     {
@@ -1805,24 +1495,19 @@
     }
 
     /**
-     *  Implemented by subclasses to return the names of the active pages
-     *  (pages for which recorders exist).  May return the empty list,
-     *  but should not return null.
-     *
-     **/
+     * Implemented by subclasses to return the names of the active pages (pages for which recorders exist).  May return
+     * the empty list, but should not return null.
+     */
 
     abstract public Collection getActivePageNames();
 
     /**
-     *  Gets the visit object, if it has been created already.
-     *
-     *  <p>
-     *  If the visit is non-null then
-     *  the {@link #isDirty()} flag is set (because
-     *  the engine can't tell what the caller will
-     *  <i>do</i> with the visit).
-     *
-     **/
+     * Gets the visit object, if it has been created already.
+     * <p/>
+     * <p/>
+     * If the visit is non-null then the {@link #isDirty()} flag is set (because the engine can't tell what the caller
+     * will <i>do</i> with the visit).
+     */
 
     public Object getVisit()
     {
@@ -1833,20 +1518,16 @@
     }
 
     /**
-     *  Gets the visit object, invoking {@link #createVisit(IRequestCycle)} to create
-     *  it lazily if needed.  If cycle is null, the visit will not be lazily created.
-     *
-     *  <p>
-     *  After creating the visit, but before returning,
-     *  the {@link HttpSession} will be created, and
-     *  {@link #setStateful()} will be invoked.
-     *
-     *  <p>
-     *  Sets the {@link #isDirty()} flag, if the return value
-     *  is not null.
-     *
-     *
-     **/
+     * Gets the visit object, invoking {@link #createVisit(IRequestCycle)} to create it lazily if needed.  If cycle is
+     * null, the visit will not be lazily created.
+     * <p/>
+     * <p/>
+     * After creating the visit, but before returning, the {@link HttpSession} will be created, and {@link
+     * #setStateful()} will be invoked.
+     * <p/>
+     * <p/>
+     * Sets the {@link #isDirty()} flag, if the return value is not null.
+     */
 
     public Object getVisit(IRequestCycle cycle)
     {
@@ -1854,8 +1535,8 @@
         {
             _visit = createVisit(cycle);
 
-            // Now that a visit object exists, we need to force the creation
-            // of a HttpSession.
+// Now that a visit object exists, we need to force the creation
+// of a HttpSession.
 
             cycle.getRequestContext().createSession();
 
@@ -1869,10 +1550,8 @@
     }
 
     /**
-     *  Updates the visit object and
-     *  sets the {@link #isDirty() dirty flag}.
-     *
-     **/
+     * Updates the visit object and sets the {@link #isDirty() dirty flag}.
+     */
 
     public void setVisit(Object value)
     {
@@ -1887,14 +1566,12 @@
     }
 
     /**
-     *  Invoked to lazily create a new visit object when it is first
-     *  referenced (by {@link #getVisit(IRequestCycle)}).  This implementation works
-     *  by looking up the name of the class to instantiate
-     *  in the {@link #getPropertySource() configuration}.
-     *
-     *  <p>Subclasses may want to overide this method if some other means
-     *  of instantiating a visit object is required.
-     **/
+     * Invoked to lazily create a new visit object when it is first referenced (by {@link #getVisit(IRequestCycle)}).
+     * This implementation works by looking up the name of the class to instantiate in the {@link #getPropertySource()
+     * configuration}.
+     * <p/>
+     * <p>Subclasses may want to overide this method if some other means of instantiating a visit object is required.
+     */
 
     protected Object createVisit(IRequestCycle cycle)
     {
@@ -1924,18 +1601,13 @@
     }
 
     /**
-     *  Returns the global object for the application.  The global object is created at the start
-     *  of the request ({@link #setupForRequest(RequestContext)} invokes
-     *  {@link #createGlobal(RequestContext)} if needed),
-     *  and is stored into the {@link ServletContext}.  All instances of the engine for
-     *  the application share
-     *  the global object; however, the global object is explicitly <em>not</em>
-     *  replicated to other servers within
-     *  a cluster.
+     * Returns the global object for the application.  The global object is created at the start of the request ({@link
+     * #setupForRequest(RequestContext)} invokes {@link #createGlobal(RequestContext)} if needed), and is stored into
+     * the {@link ServletContext}.  All instances of the engine for the application share the global object; however,
+     * the global object is explicitly <em>not</em> replicated to other servers within a cluster.
      *
-     *  @since 2.3
-     *
-     **/
+     * @since 2.3
+     */
 
     public Object getGlobal()
     {
@@ -1953,14 +1625,12 @@
     }
 
     /**
-     *  Invoked by subclasses to indicate that some state must now be stored
-     *  in the engine (and that the engine should now be stored in the
-     *  HttpSession).  The caller is responsible for actually creating
-     *  the HttpSession (it will have access to the {@link RequestContext}).
+     * Invoked by subclasses to indicate that some state must now be stored in the engine (and that the engine should
+     * now be stored in the HttpSession).  The caller is responsible for actually creating the HttpSession (it will have
+     * access to the {@link RequestContext}).
      *
-     *  @since 1.0.2
-     *
-     **/
+     * @since 1.0.2
+     */
 
     protected void setStateful()
     {
@@ -1968,10 +1638,10 @@
     }
 
     /**
-     *  Allows subclasses to include listener methods easily.
+     * Allows subclasses to include listener methods easily.
      *
      * @since 1.0.2
-     **/
+     */
 
     public ListenerMap getListeners()
     {
@@ -2061,15 +1731,13 @@
     }
 
     /**
-     *  Invoked when a {@link RedirectException} is thrown during the processing of a request.
+     * Invoked when a {@link RedirectException} is thrown during the processing of a request.
      *
-     *  @throws ApplicationRuntimeException if an {@link IOException},
-     *  {@link ServletException} is thrown by the redirect, or if no
-     *  {@link RequestDispatcher} can be found for local resource.
-     *
-     *  @since 2.2
-     *
-     **/
+     * @throws ApplicationRuntimeException if an {@link IOException}, {@link ServletException} is thrown by the
+     *                                     redirect, or if no {@link RequestDispatcher} can be found for local
+     *                                     resource.
+     * @since 2.2
+     */
 
     protected void handleRedirectException(IRequestCycle cycle, RedirectException ex)
     {
@@ -2084,12 +1752,11 @@
     }
 
     /**
-     *  Creates a Map of all the services available to the application.
-     *
-     *  <p>Note: the Map returned is not synchronized, on the theory that returned
-     *  map is not further modified and therefore threadsafe.
-     *
-     **/
+     * Creates a Map of all the services available to the application.
+     * <p/>
+     * <p>Note: the Map returned is not synchronized, on the theory that returned map is not further modified and
+     * therefore threadsafe.
+     */
 
     private Map createServiceMap()
     {
@@ -2098,16 +1765,16 @@
 
         ISpecificationSource source = getSpecificationSource();
 
-        // Build the initial version of the result map,
-        // where each value is the *name* of a class.
+// Build the initial version of the result map,
+// where each value is the *name* of a class.
 
         Map result = new HashMap();
 
-        // Do the framework first.
+// Do the framework first.
 
         addServices(source.getFrameworkNamespace(), result);
 
-        // And allow the application to override the framework.
+// And allow the application to override the framework.
 
         addServices(source.getApplicationNamespace(), result);
 
@@ -2140,8 +1807,8 @@
                                     className,
                                     serviceName));
 
-                // Replace the class name with an instance
-                // of the named class.
+// Replace the class name with an instance
+// of the named class.
 
                 entry.setValue(service);
             }
@@ -2178,14 +1845,11 @@
     }
 
     /**
-     *  Locates all services in the namespace and adds key/value
-     *  pairs to the map (name and class name).  Then recursively
-     *  descendends into child namespaces to collect more
-     *  service names.
+     * Locates all services in the namespace and adds key/value pairs to the map (name and class name).  Then
+     * recursively descendends into child namespaces to collect more service names.
      *
-     *  @since 2.2
-     *
-     **/
+     * @since 2.2
+     */
 
     private void addServices(INamespace namespace, Map map)
     {
@@ -2211,9 +1875,8 @@
     }
 
     /**
-     *  @since 2.0.4
-     *
-     **/
+     * @since 2.0.4
+     */
 
     public IComponentMessagesSource getComponentMessagesSource()
     {
@@ -2221,9 +1884,8 @@
     }
 
     /**
-     *  @since 2.2
-     *
-     **/
+     * @since 2.2
+     */
 
     public DataSqueezer getDataSqueezer()
     {
@@ -2231,14 +1893,11 @@
     }
 
     /**
+     * Invoked from {@link #setupForRequest(RequestContext)} to create a {@link DataSqueezer} when needed (typically,
+     * just the very first time). This implementation returns a standard, new instance.
      *
-     *  Invoked from {@link #setupForRequest(RequestContext)} to create
-     *  a {@link DataSqueezer} when needed (typically, just the very first time).
-     *  This implementation returns a standard, new instance.
-     *
-     *  @since 2.2
-     *
-     **/
+     * @since 2.2
+     */
 
     public DataSqueezer createDataSqueezer()
     {
@@ -2246,27 +1905,22 @@
     }
 
     /**
-     *  Invoked from {@link #service(RequestContext)} to extract, from the URL,
-     *  the name of the service.  The current implementation expects the first
-     *  pathInfo element to be the service name.  At some point in the future,
-     *  the method of constructing and parsing URLs may be abstracted into
-     *  a developer-selected class.
+     * Invoked from {@link #service(RequestContext)} to extract, from the URL, the name of the service.  The current
+     * implementation expects the first pathInfo element to be the service name.  At some point in the future, the
+     * method of constructing and parsing URLs may be abstracted into a developer-selected class.
+     * <p/>
+     * <p>Subclasses may override this method if the application defines specific services with unusual URL encoding
+     * rules.
+     * <p/>
+     * <p>This implementation simply extracts the value for query parameter {@link Tapestry#SERVICE_QUERY_PARAMETER_NAME}
+     * and extracts the service name from that.
+     * <p/>
+     * <p/>
+     * For supporting the JSP tags, this method first checks for attribute {@link Tapestry#TAG_SUPPORT_SERVICE_ATTRIBUTE}.
+     * If non-null, then {@link Tapestry#TAGSUPPORT_SERVICE} is returned.
      *
-     *  <p>Subclasses may override this method if the application defines
-     *  specific services with unusual URL encoding rules.
-     *
-     *  <p>This implementation simply extracts the value for
-     *  query parameter {@link Tapestry#SERVICE_QUERY_PARAMETER_NAME}
-     *  and extracts the service name from that.
-     *
-     *  <p>
-     *  For supporting the JSP tags, this method first
-     *  checks for attribute {@link Tapestry#TAG_SUPPORT_SERVICE_ATTRIBUTE}.  If non-null,
-     *  then {@link Tapestry#TAGSUPPORT_SERVICE} is returned.
-     *
-     *  @since 2.2
-     *
-     **/
+     * @since 2.2
+     */
 
     protected String extractServiceName(RequestContext context)
     {
@@ -2278,8 +1932,8 @@
         if (serviceData == null)
             return Tapestry.HOME_SERVICE;
 
-        // The service name is anything before the first slash,
-        // if there is one.
+// The service name is anything before the first slash,
+// if there is one.
 
         int slashx = serviceData.indexOf('/');
 
@@ -2289,35 +1943,45 @@
         return serviceData.substring(0, slashx);
     }
 
-    /** @since 2.3 **/
+    /**
+     * @since 2.3 *
+     */
 
     public IPropertySource getPropertySource()
     {
         return _propertySource;
     }
 
-    /** @since 3.0.3 */
+    /**
+     * @since 3.0.3
+     */
 
     public ResourceChecksumSource getResourceChecksumSource()
     {
         return _resourceChecksumSource;
     }
 
-    /** @since 3.0 **/
+    /**
+     * @since 3.0 *
+     */
 
     protected String getExceptionPageName()
     {
         return EXCEPTION_PAGE;
     }
 
-    /** @since 3.0 **/
+    /**
+     * @since 3.0 *
+     */
 
     protected String getStaleLinkPageName()
     {
         return STALE_LINK_PAGE;
     }
 
-    /** @since 3.0 **/
+    /**
+     * @since 3.0 *
+     */
 
     protected String getStaleSessionPageName()
     {
@@ -2325,36 +1989,26 @@
     }
 
     /**
-     *  Name of an application extension that can provide configuration properties.
+     * Name of an application extension that can provide configuration properties.
      *
-     *  @see #createPropertySource(RequestContext)
-     *  @since 2.3
-     *
-     **/
+     * @see #createPropertySource(RequestContext)
+     * @since 2.3
+     */
 
     private static final String EXTENSION_PROPERTY_SOURCE_NAME =
             "org.apache.tapestry.property-source";
 
     /**
-     *  Creates a shared property source that will be stored into
-     *  the servlet context.
-     *  Subclasses may override this method to build thier
-     *  own search path.
+     * Creates a shared property source that will be stored into the servlet context. Subclasses may override this
+     * method to build thier own search path.
+     * <p/>
+     * <p>If the application specification contains an extension named "org.apache.tapestry.property-source" it is
+     * inserted in the search path just before the property source for JVM System Properties.  This is a simple hook at
+     * allow application-specific methods of obtaining configuration values (typically, from a database or from JMX, in
+     * some way). Alternately, subclasses may override this method to provide whatever search path is appropriate.
      *
-     *  <p>If the application specification contains an extension
-     *  named "org.apache.tapestry.property-source" it is inserted
-     *  in the search path just before
-     *  the property source for JVM System Properties.  This is a simple
-     *  hook at allow application-specific methods of obtaining
-     *  configuration values (typically, from a database or from JMX,
-     *  in some way).  Alternately, subclasses may
-     *  override this method to provide whatever search path
-     *  is appropriate.
-     *
-     *
-     *  @since 2.3
-     *
-     **/
+     * @since 2.3
+     */
 
     protected IPropertySource createPropertySource(RequestContext context)
     {
@@ -2379,7 +2033,7 @@
 
         result.addSource(SystemPropertiesPropertySource.getInstance());
 
-        // Lastly, add a final source to handle "factory defaults".
+// Lastly, add a final source to handle "factory defaults".
 
         ResourceBundle bundle =
                 ResourceBundle.getBundle("org.apache.tapestry.ConfigurationDefaults");
@@ -2390,15 +2044,12 @@
     }
 
     /**
-     *  Creates the shared Global object.  This implementation looks for an configuration
-     *  property, <code>org.apache.tapestry.global-class</code>, and instantiates that class
-     *  using a no-arguments
-     *  constructor.  If the property is not defined, a synchronized
-     *  {@link java.util.HashMap} is created.
+     * Creates the shared Global object.  This implementation looks for an configuration property,
+     * <code>org.apache.tapestry.global-class</code>, and instantiates that class using a no-arguments constructor.  If
+     * the property is not defined, a synchronized {@link java.util.HashMap} is created.
      *
-     *  @since 2.3
-     *
-     **/
+     * @since 2.3
+     */
 
     protected Object createGlobal(RequestContext context)
     {
@@ -2422,16 +2073,13 @@
     }
 
     /**
-     *  Returns an new instance of {@link Pool}, with the standard
-     *  set of adaptors, plus {@link BSFManagerPoolableAdaptor} for
-     *  {@link BSFManager}.
+     * Returns an new instance of {@link Pool}, with the standard set of adaptors, plus {@link
+     * BSFManagerPoolableAdaptor} for {@link BSFManager}.
+     * <p/>
+     * <p>Subclasses may override this method to configure the Pool differently.
      *
-     *  <p>Subclasses may override this
-     *  method to configure the Pool differently.
-     *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     protected Pool createPool(RequestContext context)
     {
@@ -2442,7 +2090,9 @@
         return result;
     }
 
-    /** @since 3.0 **/
+    /**
+     * @since 3.0 *
+     */
 
     public Pool getPool()
     {
@@ -2450,16 +2100,13 @@
     }
 
     /**
-     *
-     * Invoked from {@link #setupForRequest(RequestContext)}.  Creates
-     * a new instance of {@link DefaultComponentClassEnhancer}.  Subclasses
-     * may override to return a different object.
-     *
-     * <p>
-     * Check the property <code>org.apache.tapestry.enhance.disable-abstract-method-validation</code>
-     * and, if true, disables abstract method validation. This is used  in some
-     * errant JDK's (such as IBM's 1.3.1) that incorrectly report concrete methods from
-     * abstract classes as abstract.
+     * Invoked from {@link #setupForRequest(RequestContext)}.  Creates a new instance of {@link
+     * DefaultComponentClassEnhancer}.  Subclasses may override to return a different object.
+     * <p/>
+     * <p/>
+     * Check the property <code>org.apache.tapestry.enhance.disable-abstract-method-validation</code> and, if true,
+     * disables abstract method validation. This is used  in some errant JDK's (such as IBM's 1.3.1) that incorrectly
+     * report concrete methods from abstract classes as abstract.
      *
      * @since 3.0
      */
@@ -2470,7 +2117,7 @@
                 "true".equals(
                         _propertySource.getPropertyValue(
                                 "org.apache.tapestry.enhance.disable-abstract-method-validation"));
-        
+
         return new DefaultComponentClassEnhancer(_resolver, disableValidation, _classFactory);
     }
 
@@ -2478,8 +2125,10 @@
     {
         return new EnhancedClassFactory(_resolver);
     }
-    
-    /** @since 3.0 **/
+
+    /**
+     * @since 3.0 *
+     */
 
     public IComponentClassEnhancer getComponentClassEnhancer()
     {
@@ -2487,14 +2136,11 @@
     }
 
     /**
-     *  Returns true if the engine has (potentially) changed
-     *  state since the last time it was stored
-     *  into the {@link javax.servlet.http.HttpSession}.  Various
-     *  events set this property to true.
+     * Returns true if the engine has (potentially) changed state since the last time it was stored into the {@link
+     * javax.servlet.http.HttpSession}.  Various events set this property to true.
      *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     public boolean isDirty()
     {
@@ -2502,14 +2148,11 @@
     }
 
     /**
-     *  Invoked to set the dirty flag, indicating that the
-     *  engine should be stored into the
-     *  {@link javax.servlet.http.HttpSession}.
+     * Invoked to set the dirty flag, indicating that the engine should be stored into the {@link
+     * javax.servlet.http.HttpSession}.
      *
-     *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     protected void markDirty()
     {
@@ -2520,14 +2163,10 @@
     }
 
     /**
+     * Clears the dirty flag when a engine is stored into the {@link HttpSession}.
      *
-     *  Clears the dirty flag when a engine is stored into the
-     *  {@link HttpSession}.
-     *
-     *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     public void valueBound(HttpSessionBindingEvent arg0)
     {
@@ -2537,47 +2176,40 @@
     }
 
     /**
-     *  Does nothing.
+     * Does nothing.
      *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     public void valueUnbound(HttpSessionBindingEvent arg0)
     {
     }
 
     /**
+     * The encoding to be used if none has been defined using the output encoding property. Override this method to
+     * change the default.
      *
-     *  The encoding to be used if none has been defined using the output encoding property.
-     *  Override this method to change the default.
-     *
-     *  @return the default output encoding
-     *  @since 3.0
-     *
-     **/
+     * @return the default output encoding
+     * @since 3.0
+     */
     protected String getDefaultOutputEncoding()
     {
         return DEFAULT_OUTPUT_ENCODING;
     }
 
     /**
+     * Returns the encoding to be used to generate the servlet responses and accept the servlet requests.
+     * <p/>
+     * The encoding is defined using the org.apache.tapestry.output-encoding and is UTF-8 by default
      *
-     *  Returns the encoding to be used to generate the servlet responses and
-     *  accept the servlet requests.
-     *
-     *  The encoding is defined using the org.apache.tapestry.output-encoding
-     *  and is UTF-8 by default
-     *
-     *  @since 3.0
-     *  @see org.apache.tapestry.IEngine#getOutputEncoding()
-     *
-     **/
+     * @see org.apache.tapestry.IEngine#getOutputEncoding()
+     * @since 3.0
+     */
     public String getOutputEncoding()
     {
         if (_outputEncoding != null)
             return _outputEncoding;
-        
+
         IPropertySource source = getPropertySource();
 
         String encoding = source.getPropertyValue(OUTPUT_ENCODING_PROPERTY_NAME);
diff --git a/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java b/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java
index 412bc0c..46ac179 100644
--- a/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java
+++ b/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java
@@ -26,33 +26,26 @@
 import java.util.*;
 
 /**
- *  Concrete implementation of {@link org.apache.tapestry.IEngine} used for ordinary
- *  applications.  All page state information is maintained in
- *  the {@link javax.servlet.http.HttpSession} using
- *  instances of {@link org.apache.tapestry.record.SessionPageRecorder}.
+ * Concrete implementation of {@link org.apache.tapestry.IEngine} used for ordinary applications.  All page state
+ * information is maintained in the {@link javax.servlet.http.HttpSession} using instances of {@link
+ * org.apache.tapestry.record.SessionPageRecorder}.
  *
- *  @author Howard Lewis Ship
- *  @version $Id$
- *
- **/
+ * @author Howard Lewis Ship
+ * @version $Id$
+ */
 
 public class BaseEngine extends AbstractEngine
 {
     private static final long serialVersionUID = -7051050643746333380L;
 
-    private final static int MAP_SIZE = 3;
-
     private transient Map _recorders;
 
     private transient Set _activePageNames;
 
     /**
-     *  Removes all page recorders that contain no changes, or
-     *  are marked for discard.  Subclasses
-     *  should invoke this implementation in addition to providing
-     *  thier own.
-     *
-     **/
+     * Removes all page recorders that contain no changes, or are marked for discard.  Subclasses should invoke this
+     * implementation in addition to providing thier own.
+     */
 
     protected void cleanupAfterRequest(IRequestCycle cycle)
     {
@@ -105,11 +98,8 @@
     }
 
     /**
-     *  Returns an unmodifiable {@link Collection} of the page names for which
-     *  {@link IPageRecorder} instances exist.
-     *
-     *
-     **/
+     * Returns an unmodifiable {@link Collection} of the page names for which {@link IPageRecorder} instances exist.
+     */
 
     public Collection getActivePageNames()
     {
@@ -170,10 +160,8 @@
     }
 
     /**
-     *  Reconstructs the list of active page names
-     *  written by {@link #writeExternal(ObjectOutput)}.
-     *
-     **/
+     * Reconstructs the list of active page names written by {@link #writeExternal(ObjectOutput)}.
+     */
 
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
     {
@@ -194,11 +182,9 @@
     }
 
     /**
-     *  Writes the engine's persistent state; this is simply the list of active page
-     *  names.  For efficiency, this is written as a count followed by each name
-     *  as a UTF String.
-     *
-     **/
+     * Writes the engine's persistent state; this is simply the list of active page names.  For efficiency, this is
+     * written as a count followed by each name as a UTF String.
+     */
 
     public void writeExternal(ObjectOutput out) throws IOException
     {
diff --git a/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java b/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java
index ceaf150..a9ed24c 100644
--- a/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java
+++ b/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java
@@ -15,7 +15,6 @@
 package org.apache.tapestry.engine;
 
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
-import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -27,6 +26,7 @@
 import org.apache.tapestry.spec.ILibrarySpecification;
 import org.apache.tapestry.spec.LibrarySpecification;
 import org.apache.tapestry.util.IRenderDescription;
+import org.apache.tapestry.util.ResourceLockManager;
 import org.apache.tapestry.util.pool.Pool;
 import org.apache.tapestry.util.xml.DocumentParseException;
 
@@ -35,31 +35,26 @@
 import java.util.Set;
 
 /**
- *  Default implementation of {@link ISpecificationSource} that
- *  expects to use the normal class loader to locate component
- *  specifications from within the classpath.
- *
+ * Default implementation of {@link ISpecificationSource} that expects to use the normal class loader to locate
+ * component specifications from within the classpath.
+ * <p/>
  * <p>Caches specifications in memory forever, or until {@link #reset()} is invoked.
- *
- * <p>An instance of this class acts like a singleton and is shared by multiple sessions,
- * so it must be threadsafe.
+ * <p/>
+ * <p>An instance of this class acts like a singleton and is shared by multiple sessions, so it must be threadsafe.
  *
  * @author Howard Lewis Ship
  * @version $Id$
- *
- **/
+ */
 
 public class DefaultSpecificationSource implements ISpecificationSource, IRenderDescription
 {
     private static final Log LOG = LogFactory.getLog(DefaultSpecificationSource.class);
 
     /**
-     *  Key used to get and store {@link SpecificationParser} instances
-     *  from the Pool.
+     * Key used to get and store {@link SpecificationParser} instances from the Pool.
      *
-     *  @since 3.0
-     *
-     **/
+     * @since 3.0
+     */
 
     private static final String PARSER_POOL_KEY = "org.apache.tapestry.SpecificationParser";
 
@@ -70,60 +65,42 @@
     private INamespace _frameworkNamespace;
 
     /**
-     *  Contains previously parsed component specifications.
-     *
-     **/
+     * Contains previously parsed component specifications.
+     */
 
-    private Map _componentCache = new ConcurrentHashMap();
+    private final Map _componentCache = new ConcurrentHashMap();
 
     /**
-     *  Contains previously parsed page specifications.
+     * Contains previously parsed page specifications.
      *
-     *  @since 2.2
-     *
-     **/
+     * @since 2.2
+     */
 
-    private Map _pageCache = new ConcurrentHashMap();
+    private final Map _pageCache = new ConcurrentHashMap();
 
     /**
-     *  Contains previously parsed library specifications, keyed
-     *  on specification resource path.
+     * Contains previously parsed library specifications, keyed on specification resource path.
      *
-     *  @since 2.2
-     *
-     **/
+     * @since 2.2
+     */
 
-    private Map _libraryCache = new ConcurrentHashMap();
+    private final Map _libraryCache = new ConcurrentHashMap();
 
-    /**
-     *  Contains {@link INamespace} instances, keyed on id (which will
-     *  be null for the application specification).
-     *
-     **/
-
-    private Map _namespaceCache = new ConcurrentHashMap();
 
     /**
      * Used to synchronize concurrent operations on specific resources.
      */
-    private ConcurrentHashMap _lockCache = new ConcurrentHashMap();
+    private final ResourceLockManager _resourceLockManager = new ResourceLockManager();
 
     /**
-     *  Reference to the shared {@link org.apache.tapestry.util.pool.Pool}.
+     * Reference to the shared {@link org.apache.tapestry.util.pool.Pool}.
      *
-     *  @see org.apache.tapestry.IEngine#getPool()
-     *
-     *  @since 3.0
-     *
-     **/
+     * @see org.apache.tapestry.IEngine#getPool()
+     * @since 3.0
+     */
 
     private Pool _pool;
 
-    /**
-     * Used to synchronize global member access.
-     */
-    private ReentrantLock _monitor = new ReentrantLock();
-
     public DefaultSpecificationSource(
             IResourceResolver resolver,
             IApplicationSpecification specification,
@@ -135,28 +112,18 @@
     }
 
     /**
-     *  Clears the specification cache.  This is used during debugging.
-     *
-     **/
+     * Clears the specification cache.  This is used during debugging.
+     */
 
-    public void reset()
+    public synchronized void reset()
     {
-        _monitor.lock();
+        _componentCache.clear();
+        _pageCache.clear();
+        _libraryCache.clear();
+        _resourceLockManager.clear();
 
-        try
-        {
-            _componentCache.clear();
-            _pageCache.clear();
-            _libraryCache.clear();
-            _namespaceCache.clear();
-            _lockCache.clear();
-
-            _applicationNamespace = null;
-            _frameworkNamespace = null;
-        } finally
-        {
-            _monitor.unlock();
-        }
+        _applicationNamespace = null;
+        _frameworkNamespace = null;
     }
 
     protected IComponentSpecification parseSpecification(
@@ -224,7 +191,9 @@
         return builder.toString();
     }
 
-    /** @since 1.0.6 **/
+    /**
+     * @since 1.0.6 *
+     */
 
     public void renderDescription(IMarkupWriter writer)
     {
@@ -273,12 +242,11 @@
     }
 
     /**
-     *  Gets a component specification.
+     * Gets a component specification.
      *
-     *  @param resourceLocation the complete resource path to the specification.
-     *  @throws ApplicationRuntimeException if the specification cannot be obtained.
-     *
-     **/
+     * @param resourceLocation the complete resource path to the specification.
+     * @throws ApplicationRuntimeException if the specification cannot be obtained.
+     */
 
     public IComponentSpecification getComponentSpecification(IResourceLocation resourceLocation)
     {
@@ -288,9 +256,7 @@
         if (result != null)
             return result;
 
-        ReentrantLock lock = getLock(resourceLocation);
-
-        lock.lock();
+        _resourceLockManager.lock(resourceLocation);
 
         try
         {
@@ -302,9 +268,11 @@
             result = parseSpecification(resourceLocation, false);
 
             _componentCache.put(resourceLocation, result);
-        } finally
+        }
+        finally
         {
-            lock.unlock();
+            _resourceLockManager.unlock(resourceLocation);
+
         }
 
         return result;
@@ -317,23 +285,27 @@
         if (result != null)
             return result;
 
-        ReentrantLock lock = getLock(resourceLocation);
-
-        lock.lock();
+        _resourceLockManager.lock(resourceLocation);
 
         try
         {
+            // In a race condition, one thread may be parsing the specification while others block.
+            // The specification is in the cache once they un-block.
+
             result = (IComponentSpecification) _pageCache.get(resourceLocation);
 
+
             if (result != null)
                 return result;
 
             result = parseSpecification(resourceLocation, true);
 
             _pageCache.put(resourceLocation, result);
-        } finally
+        }
+        finally
         {
-            lock.unlock();
+            _resourceLockManager.unlock(resourceLocation);
+
         }
 
         return result;
@@ -346,12 +318,13 @@
         if (result != null)
             return result;
 
-        ReentrantLock lock = getLock(resourceLocation);
-
-        lock.lock();
+        _resourceLockManager.lock(resourceLocation);
 
         try
         {
+            // In a race condition, one thread may be parsing the specification while others block.
+            // The specification is in the cache once they un-block.
+
             result = (LibrarySpecification) _libraryCache.get(resourceLocation);
 
             if (result != null)
@@ -359,15 +332,19 @@
 
             result = parseLibrarySpecification(resourceLocation);
             _libraryCache.put(resourceLocation, result);
-        } finally
+        }
+        finally
         {
-            lock.unlock();
+            _resourceLockManager.unlock(resourceLocation);
+
         }
 
         return result;
     }
 
-    /** @since 2.2 **/
+    /**
+     * @since 2.2 *
+     */
 
     protected SpecificationParser getParser()
     {
@@ -379,59 +356,35 @@
         return result;
     }
 
-    /** @since 3.0 **/
+    /**
+     * @since 3.0 *
+     */
 
     protected void discardParser(SpecificationParser parser)
     {
         _pool.store(PARSER_POOL_KEY, parser);
     }
 
-    public INamespace getApplicationNamespace()
+    public synchronized INamespace getApplicationNamespace()
     {
-        _monitor.lock();
+        if (_applicationNamespace == null)
+            _applicationNamespace = new Namespace(null, null, _specification, this);
 
-        try
+        return _applicationNamespace;
+    }
+
+    public synchronized INamespace getFrameworkNamespace()
+    {
+        if (_frameworkNamespace == null)
         {
-            if (_applicationNamespace == null)
-                _applicationNamespace = new Namespace(null, null, _specification, this);
+            IResourceLocation frameworkLocation =
+                    new ClasspathResourceLocation(_resolver, "/org/apache/tapestry/Framework.library");
 
-            return _applicationNamespace;
+            ILibrarySpecification ls = getLibrarySpecification(frameworkLocation);
 
-        } finally
-        {
-            _monitor.unlock();
+            _frameworkNamespace = new Namespace(INamespace.FRAMEWORK_NAMESPACE, null, ls, this);
         }
+
+        return _frameworkNamespace;
     }
-
-    public INamespace getFrameworkNamespace()
-    {
-        _monitor.lock();
-
-        try
-        {
-            if (_frameworkNamespace == null)
-            {
-                IResourceLocation frameworkLocation =
-                        new ClasspathResourceLocation(_resolver, "/org/apache/tapestry/Framework.library");
-
-                ILibrarySpecification ls = getLibrarySpecification(frameworkLocation);
-
-                _frameworkNamespace = new Namespace(INamespace.FRAMEWORK_NAMESPACE, null, ls, this);
-            }
-
-            return _frameworkNamespace;
-
-        } finally
-        {
-            _monitor.unlock();
-        }
-    }
-
-    private ReentrantLock getLock(Object key)
-    {
-        _lockCache.putIfAbsent(key, new ReentrantLock());
-
-        return (ReentrantLock) _lockCache.get(key);
-    }
-
 }
\ No newline at end of file
diff --git a/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java b/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java
index 538d475..8ba40c5 100644
--- a/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java
+++ b/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java
@@ -15,7 +15,6 @@
 package org.apache.tapestry.engine;
 
 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
-import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -35,22 +34,18 @@
 import java.util.Map;
 
 /**
- *  Default implementation of {@link ITemplateSource}.  Templates, once parsed,
- *  stay in memory until explicitly cleared.
+ * Default implementation of {@link ITemplateSource}.  Templates, once parsed, stay in memory until explicitly cleared.
+ * <p/>
+ * <p>An instance of this class acts as a singleton shared by all sessions, so it must be threadsafe.
  *
- *  <p>An instance of this class acts as a singleton shared by all sessions, so it
- *  must be threadsafe.
- *
- *  @author Howard Lewis Ship
- *  @version $Id$
- *
- **/
+ * @author Howard Lewis Ship
+ * @version $Id$
+ */
 
 public class DefaultTemplateSource implements ITemplateSource, IRenderDescription
 {
     private static final Log LOG = LogFactory.getLog(DefaultTemplateSource.class);
 
-
     // The name of the component/application/etc property that will be used to
     // determine the encoding to use when loading the template
 
@@ -60,20 +55,18 @@
     // specification resource path and locale (local may be null), value
     // is the ComponentTemplate.
 
-    private Map _cache = new ConcurrentHashMap();
+    private final Map _cache = new ConcurrentHashMap();
 
     // Previously read templates; key is the IResourceLocation, value
     // is the ComponentTemplate.
 
-    private Map _templates = new ConcurrentHashMap();
+    private final Map _templates = new ConcurrentHashMap();
 
-    // Used to synchronize access to specific templates
-    private ConcurrentHashMap _lockCache = new ConcurrentHashMap();
+    private final ResourceLockManager _resourceLockManager = new ResourceLockManager();
 
     /**
-     *  Number of tokens (each template contains multiple tokens).
-     *
-     **/
+     * Number of tokens (each template contains multiple tokens).
+     */
 
     private int _tokenCount;
 
@@ -81,34 +74,36 @@
 
     private TemplateParser _parser;
 
-    /** @since 2.2 **/
+    /**
+     * @since 2.2 *
+     */
 
     private IResourceLocation _applicationRootLocation;
 
-    /** @since 3.0 **/
+    /**
+     * @since 3.0 *
+     */
 
     private ITemplateSourceDelegate _delegate;
 
     /**
-     *  Clears the template cache.  This is used during debugging.
-     *
-     **/
+     * Clears the template cache.  This is used during debugging.
+     */
 
     public void reset()
     {
         _cache.clear();
         _templates.clear();
-        _lockCache.clear();
+        _resourceLockManager.clear();
 
         _tokenCount = 0;
     }
 
     /**
-     *  Reads the template for the component.
-     *
-     *  <p>Returns null if the template can't be found.
-     *
-     **/
+     * Reads the template for the component.
+     * <p/>
+     * <p>Returns null if the template can't be found.
+     */
 
     public ComponentTemplate getTemplate(IRequestCycle cycle, IComponent component)
     {
@@ -117,17 +112,14 @@
 
         Locale locale = component.getPage().getLocale();
 
-        Object key = new MultiKey(new Object[] { specificationLocation, locale }, false);
+        Object key = new MultiKey(new Object[]{specificationLocation, locale}, false);
 
         ComponentTemplate result = searchCache(key);
         if (result != null)
             return result;
 
-        _lockCache.putIfAbsent(key, new ReentrantLock());
+        _resourceLockManager.lock(key);
 
-        ReentrantLock lock = (ReentrantLock)_lockCache.get(key);
-
-        lock.lock();
         try
         {
             result = searchCache(key);
@@ -145,8 +137,8 @@
 
                 String stringKey =
                         component.getSpecification().isPageSpecification()
-                                ? "DefaultTemplateSource.no-template-for-page"
-                                : "DefaultTemplateSource.no-template-for-component";
+                        ? "DefaultTemplateSource.no-template-for-page"
+                        : "DefaultTemplateSource.no-template-for-component";
 
                 throw new ApplicationRuntimeException(
                         Tapestry.format(stringKey, component.getExtendedId(), locale),
@@ -156,11 +148,14 @@
             }
 
             saveToCache(key, result);
-        } finally
-        {
-            lock.unlock();
+
+            return result;
         }
-        return result;
+        finally
+        {
+            _resourceLockManager.unlock(key);
+        }
+
     }
 
     private ComponentTemplate searchCache(Object key)
@@ -198,17 +193,12 @@
     }
 
     /**
-     *  Finds the template for the given component, using the following rules:
-     *  <ul>
-     *  <li>If the component has a $template asset, use that
-     *  <li>Look for a template in the same folder as the component
-     *  <li>If a page in the application namespace, search in the application root
-     *  <li>Fail!
-     *  </ul>
+     * Finds the template for the given component, using the following rules: <ul> <li>If the component has a $template
+     * asset, use that <li>Look for a template in the same folder as the component <li>If a page in the application
+     * namespace, search in the application root <li>Fail! </ul>
      *
-     *  @return the template, or null if not found
-     *
-     **/
+     * @return the template, or null if not found
+     */
 
     private ComponentTemplate findTemplate(
             IRequestCycle cycle,
@@ -229,8 +219,8 @@
                 findStandardTemplate(cycle, location, component, templateBaseName, locale);
 
         if (result == null
-            && component.getSpecification().isPageSpecification()
-            && component.getNamespace().isApplicationNamespace())
+                && component.getSpecification().isPageSpecification()
+                && component.getNamespace().isApplicationNamespace())
             result = findPageTemplateInApplicationRoot(cycle, component, templateBaseName, locale);
 
         return result;
@@ -259,9 +249,8 @@
     }
 
     /**
-     *  Reads an asset to get the template.
-     *
-     **/
+     * Reads an asset to get the template.
+     */
 
     private ComponentTemplate readTemplateFromAsset(
             IRequestCycle cycle,
@@ -293,13 +282,11 @@
     }
 
     /**
-     *  Search for the template corresponding to the resource and the locale.
-     *  This may be in the template map already, or may involve reading and
-     *  parsing the template.
+     * Search for the template corresponding to the resource and the locale. This may be in the template map already, or
+     * may involve reading and parsing the template.
      *
-     *  @return the template, or null if not found.
-     *
-     **/
+     * @return the template, or null if not found.
+     */
 
     private ComponentTemplate findStandardTemplate(
             IRequestCycle cycle,
@@ -311,9 +298,9 @@
         if (LOG.isDebugEnabled())
             LOG.debug(
                     "Searching for localized version of template for "
-                    + location
-                    + " in locale "
-                    + locale.getDisplayName());
+                            + location
+                            + " in locale "
+                            + locale.getDisplayName());
 
         IResourceLocation baseTemplateLocation = location.getRelativeLocation(templateBaseName);
 
@@ -327,11 +314,9 @@
     }
 
     /**
-     *  Returns a previously parsed template at the specified location (which must already
-     *  be localized).  If not already in the template Map, then the
-     *  location is parsed and stored into the templates Map, then returned.
-     *
-     **/
+     * Returns a previously parsed template at the specified location (which must already be localized).  If not already
+     * in the template Map, then the location is parsed and stored into the templates Map, then returned.
+     */
 
     private ComponentTemplate getOrParseTemplate(
             IRequestCycle cycle,
@@ -354,12 +339,9 @@
     }
 
     /**
-     *  Reads the template for the given resource; returns null if the
-     *  resource doesn't exist.  Note that this method is only invoked
-     *  from a synchronized block, so there shouldn't be threading
-     *  issues here.
-     *
-     **/
+     * Reads the template for the given resource; returns null if the resource doesn't exist.  Note that this method is
+     * only invoked from a synchronized block, so there shouldn't be threading issues here.
+     */
 
     private ComponentTemplate parseTemplate(
             IRequestCycle cycle,
@@ -376,12 +358,9 @@
     }
 
     /**
-     *  This method is currently synchronized, because
-     *  {@link TemplateParser} is not threadsafe.  Another good candidate
-     *  for a pooling mechanism, especially because parsing a template
-     *  may take a while.
-     *
-     **/
+     * This method is currently synchronized, because {@link TemplateParser} is not threadsafe.  Another good candidate
+     * for a pooling mechanism, especially because parsing a template may take a while.
+     */
 
     private synchronized ComponentTemplate constructTemplateInstance(
             IRequestCycle cycle,
@@ -416,10 +395,8 @@
     }
 
     /**
-     *  Reads the template, given the complete path to the
-     *  resource.  Returns null if the resource doesn't exist.
-     *
-     **/
+     * Reads the template, given the complete path to the resource.  Returns null if the resource doesn't exist.
+     */
 
     private char[] readTemplate(IResourceLocation location, String encoding)
     {
@@ -461,9 +438,8 @@
     }
 
     /**
-     *  Reads a Stream into memory as an array of characters.
-     *
-     **/
+     * Reads a Stream into memory as an array of characters.
+     */
 
     private char[] readTemplateStream(InputStream stream, String encoding) throws IOException
     {
@@ -520,11 +496,10 @@
     }
 
     /**
-     *  Checks for the {@link Tapestry#TEMPLATE_EXTENSION_PROPERTY} in the component's
-     *  specification, then in the component's namespace's specification.  Returns
-     *  {@link Tapestry#DEFAULT_TEMPLATE_EXTENSION} if not otherwise overriden.
-     *
-     **/
+     * Checks for the {@link Tapestry#TEMPLATE_EXTENSION_PROPERTY} in the component's specification, then in the
+     * component's namespace's specification.  Returns {@link Tapestry#DEFAULT_TEMPLATE_EXTENSION} if not otherwise
+     * overriden.
+     */
 
     private String getTemplateExtension(IComponent component)
     {
@@ -544,7 +519,9 @@
         return Tapestry.DEFAULT_TEMPLATE_EXTENSION;
     }
 
-    /** @since 1.0.6 **/
+    /**
+     * @since 1.0.6 *
+     */
 
     public synchronized void renderDescription(IMarkupWriter writer)
     {
diff --git a/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java b/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java
index 46466bd..b7198a7 100644
--- a/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java
+++ b/tapestry-framework/src/org/apache/tapestry/engine/ExpressionCacheImpl.java
@@ -14,7 +14,6 @@
 
 package org.apache.tapestry.engine;
 
-import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
 import ognl.ClassCacheInspector;
 import ognl.Node;
 import ognl.OgnlRuntime;
@@ -27,9 +26,8 @@
  * @author Howard M. Lewis Ship
  * @since 4.0
  */
-public class ExpressionCacheImpl implements ExpressionCache, ClassCacheInspector {
-
-    private final ReentrantLock _lock = new ReentrantLock();
+public class ExpressionCacheImpl implements ExpressionCache, ClassCacheInspector
+{
 
     private final Map _compiledExpressionCache = new HashMap();
 
@@ -50,77 +48,53 @@
         }
     }
 
-    public void reset()
+    public synchronized void reset()
     {
-        try
-        {
-            _lock.lock();
-
-            _compiledExpressionCache.clear();
-            _expressionCache.clear();
-        } finally
-        {
-            _lock.unlock();
-        }
+        _compiledExpressionCache.clear();
+        _expressionCache.clear();
     }
 
     public boolean shouldCache(Class type)
     {
         if (!_cachingDisabled || type == null
-            || AbstractComponent.class.isAssignableFrom(type))
+                || AbstractComponent.class.isAssignableFrom(type))
             return false;
 
         return true;
     }
 
-    public Object get(Object target, String expression)
+    public synchronized Object get(Object target, String expression)
     {
-        try
+        Map cached = (Map) _compiledExpressionCache.get(target.getClass());
+        if (cached == null)
         {
-            _lock.lock();
-
-            Map cached = (Map)_compiledExpressionCache.get(target.getClass());
-            if (cached == null)
-            {
-                return _expressionCache.get(expression);
-            } else
-            {
-                return cached.get(expression);
-            }
-
-        } finally
+            return _expressionCache.get(expression);
+        }
+        else
         {
-            _lock.unlock();
+            return cached.get(expression);
         }
     }
 
-    public void cache(Object target, String expression, Node node)
+    public synchronized void cache(Object target, String expression, Node node)
     {
-        try
+        if (node.getAccessor() != null)
         {
-            _lock.lock();
+            Map cached = (Map) _compiledExpressionCache.get(target.getClass());
 
-            if (node.getAccessor() != null)
+            if (cached == null)
             {
-                Map cached = (Map)_compiledExpressionCache.get(target.getClass());
-
-                if (cached == null)
-                {
-                    cached = new HashMap();
-                    _compiledExpressionCache.put(target.getClass(), cached);
-                }
-
-                cached.put(expression, node);
-
-                _expressionCache.remove(target.getClass());
-            } else
-            {
-                _expressionCache.put(expression, node);
+                cached = new HashMap();
+                _compiledExpressionCache.put(target.getClass(), cached);
             }
 
-        } finally
+            cached.put(expression, node);
+
+            _expressionCache.remove(target.getClass());
+        }
+        else
         {
-            _lock.unlock();
+            _expressionCache.put(expression, node);
         }
     }
 }
diff --git a/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java b/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java
index 785f5fb..3c56696 100644
--- a/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java
+++ b/tapestry-framework/src/org/apache/tapestry/engine/ExpressionEvaluatorImpl.java
@@ -29,7 +29,8 @@
 /**
  * @since 4.0
  */
-public class ExpressionEvaluatorImpl implements ExpressionEvaluator {
+public class ExpressionEvaluatorImpl implements ExpressionEvaluator
+{
 
     private static final long POOL_MIN_IDLE_TIME = 1000 * 60 * 50;
 
@@ -72,7 +73,8 @@
     void initializeService()
     {
         if (_applicationSpecification.checkExtension(Tapestry.OGNL_TYPE_CONVERTER))
-            _typeConverter = (TypeConverter) _applicationSpecification.getExtension(Tapestry.OGNL_TYPE_CONVERTER, TypeConverter.class);
+            _typeConverter = (TypeConverter) _applicationSpecification.getExtension(Tapestry.OGNL_TYPE_CONVERTER,
+                                                                                    TypeConverter.class);
 
         _defaultContext = Ognl.createDefaultContext(null, _ognlResolver, _typeConverter);
 
@@ -88,17 +90,19 @@
 
     public Node parse(Object target, String expression)
     {
-        Node node = (Node)_expressionCache.get(target, expression);
+        Node node = (Node) _expressionCache.get(target, expression);
 
         if (node == null)
         {
             try
             {
-                node = (Node)Ognl.parseExpression(expression);
+                node = (Node) Ognl.parseExpression(expression);
                 _expressionCache.cache(target, expression, node);
-            } catch (OgnlException ex)
+            }
+            catch (OgnlException ex)
             {
-                throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
+                throw new ApplicationRuntimeException(
+                        Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
             }
         }
 
@@ -120,33 +124,57 @@
         OgnlContext context = null;
         try
         {
-            context = (OgnlContext)_contextPool.borrowObject();
+            context = (OgnlContext) _contextPool.borrowObject();
             context.setRoot(target);
-            
+
             return Ognl.getValue(expression, context, target);
         }
         catch (Exception ex)
         {
-            throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
-        } finally {
-            try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+            throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex),
+                                                  target, null, ex);
+        }
+        finally
+        {
+            discardContext(context);
+        }
+    }
+
+    /**
+     * Invoked from various finally blocks to discard a OgnlContext used during an operation.
+     */
+    private void discardContext(OgnlContext context)
+    {
+        if (context == null) return;
+
+        try
+        {
+            _contextPool.returnObject(context);
+        }
+        catch (Exception ex)
+        {
+            // Ignored.  Should be logged?
         }
     }
 
     public Object read(Object target, ExpressionAccessor expression)
     {
         OgnlContext context = null;
+
         try
         {
-            context = (OgnlContext)_contextPool.borrowObject();
+            context = (OgnlContext) _contextPool.borrowObject();
 
             return expression.get(context, target);
         }
         catch (Exception ex)
         {
-            throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
-        } finally {
-            try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+            throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex),
+                                                  target, null, ex);
+        }
+        finally
+        {
+            discardContext(context);
         }
     }
 
@@ -160,7 +188,7 @@
         OgnlContext context = null;
         try
         {
-            context = (OgnlContext)_contextPool.borrowObject();
+            context = (OgnlContext) _contextPool.borrowObject();
 
             // set up context
             context.setRoot(target);
@@ -170,10 +198,12 @@
         catch (Exception ex)
         {
             throw new ApplicationRuntimeException(Tapestry.format("unable-to-write-expression",
-                                                                  new Object[] {expression, target, value, ex}),
+                                                                  new Object[]{expression, target, value, ex}),
                                                   target, null, ex);
-        } finally {
-            try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+        }
+        finally
+        {
+            discardContext(context);
         }
     }
 
@@ -182,17 +212,19 @@
         OgnlContext context = null;
         try
         {
-            context = (OgnlContext)_contextPool.borrowObject();
+            context = (OgnlContext) _contextPool.borrowObject();
 
             Ognl.setValue(expression, context, target, value);
         }
         catch (Exception ex)
         {
             throw new ApplicationRuntimeException(Tapestry.format("unable-to-write-expression",
-                                                                  new Object[] {expression, target, value, ex}),
+                                                                  new Object[]{expression, target, value, ex}),
                                                   target, null, ex);
-        } finally {
-            try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+        }
+        finally
+        {
+            discardContext(context);
         }
     }
 
@@ -218,10 +250,10 @@
     public void compileExpression(Object target, Node node, String expression)
     {
         OgnlContext context = null;
-        
+
         try
         {
-            context = (OgnlContext)_contextPool.borrowObject();
+            context = (OgnlContext) _contextPool.borrowObject();
 
             // set up context
             context.setRoot(target);
@@ -230,11 +262,15 @@
 
             _expressionCache.cache(target, expression, node);
 
-        } catch (Exception ex)
+        }
+        catch (Exception ex)
         {
-            throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex), target, null, ex);
-        } finally {
-            try { if (context != null) _contextPool.returnObject(context); } catch (Exception e) {}
+            throw new ApplicationRuntimeException(Tapestry.format("unable-to-read-expression", expression, target, ex),
+                                                  target, null, ex);
+        }
+        finally
+        {
+            discardContext(context);
         }
     }
 
@@ -246,7 +282,9 @@
 
             OgnlRuntime.clearCache();
             Introspector.flushCaches();
-        } catch (Exception et) {
+        }
+        catch (Exception et)
+        {
             // ignore
         }
     }
diff --git a/tapestry-framework/src/org/apache/tapestry/util/ResourceLockManager.java b/tapestry-framework/src/org/apache/tapestry/util/ResourceLockManager.java
new file mode 100644
index 0000000..1cec27d
--- /dev/null
+++ b/tapestry-framework/src/org/apache/tapestry/util/ResourceLockManager.java
@@ -0,0 +1,57 @@
+//  Copyright 2008 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.util;
+
+import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
+import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentMap;
+import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * Manages {@link edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock}s keyed on some arbitrary object.
+ */
+public class ResourceLockManager
+{
+    /**
+     * Map from some object (which should be a proper key) to a ReentrantLock.
+     */
+    private final ConcurrentMap resourceToLock = new ConcurrentHashMap();
+
+    public void clear()
+    {
+        resourceToLock.clear();
+    }
+
+    private ReentrantLock get(Object object)
+    {
+        if (!resourceToLock.containsKey(object))
+        {
+            // Watch out for a race condition where two threads may put conflicting locks
+            // for the name resource.
+            resourceToLock.putIfAbsent(object, new ReentrantLock());
+        }
+
+        return (ReentrantLock) resourceToLock.get(object);
+    }
+
+    public void lock(Object object)
+    {
+        get(object).lock();
+    }
+
+    public void unlock(Object object)
+    {
+        get(object).unlock();
+    }
+}