You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by jk...@apache.org on 2008/06/25 23:14:12 UTC

svn commit: r671663 - in /tapestry/tapestry3/trunk: ./ tapestry-contrib/ tapestry-examples/Vlib/ tapestry-examples/VlibBeans/ tapestry-examples/tapestry-workbench/ tapestry-examples/wap/ tapestry-framework/ tapestry-framework/src/org/apache/tapestry/ t...

Author: jkuhnert
Date: Wed Jun 25 14:14:11 2008
New Revision: 671663

URL: http://svn.apache.org/viewvc?rev=671663&view=rev
Log:
-) Refactored most of the concurrent sensitive hot spot portions of the framework to use the more robust libraries provided by the backport util library - eventually resuliting in roughly 80-90% cold startup time performance in contructing and initializing a sample page. (workbench table page, with 4 simultaneous jmeter threads hitting it on a quad core cpu )

-) Upgraded most of the common libraries used by the framework.

-) Fixed race condition with AbstractEngine initializing common shared services and dumping them in servlet context...which under certain conditions could cause those shared resources to be created for each concurrent thread hitting a cold started app.

Removed:
    tapestry/tapestry3/trunk/.cvsignore
    tapestry/tapestry3/trunk/tapestry-contrib/.cvsignore
    tapestry/tapestry3/trunk/tapestry-examples/Vlib/.cvsignore
    tapestry/tapestry3/trunk/tapestry-examples/VlibBeans/.cvsignore
    tapestry/tapestry3/trunk/tapestry-examples/wap/.cvsignore
    tapestry/tapestry3/trunk/tapestry-framework/.cvsignore
Modified:
    tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml
    tapestry/tapestry3/trunk/tapestry-framework/pom.xml
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/Namespace.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClassFactory.java
    tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/pageload/PageSource.java

Modified: tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml (original)
+++ tapestry/tapestry3/trunk/tapestry-examples/tapestry-workbench/pom.xml Wed Jun 25 14:14:11 2008
@@ -80,7 +80,7 @@
                     <systemProperties>
                         <systemProperty>
                             <name>org.apache.tapestry.disable-caching</name>
-                            <value>true</value>
+                            <value>false</value>
                         </systemProperty>
                     </systemProperties>
                 </configuration>

Modified: tapestry/tapestry3/trunk/tapestry-framework/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/pom.xml?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/pom.xml (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/pom.xml Wed Jun 25 14:14:11 2008
@@ -79,6 +79,10 @@
             <groupId>commons-fileupload</groupId>
             <artifactId>commons-fileupload</artifactId>
         </dependency>
+        <dependency>
+            <groupId>backport-util-concurrent</groupId>
+            <artifactId>backport-util-concurrent</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/AbstractComponent.java Wed Jun 25 14:14:11 2008
@@ -14,24 +14,11 @@
 
 package org.apache.tapestry;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
 import ognl.OgnlRuntime;
-
 import org.apache.tapestry.bean.BeanProvider;
 import org.apache.tapestry.bean.BeanProviderPropertyAccessor;
 import org.apache.tapestry.engine.IPageLoader;
-import org.apache.tapestry.event.ChangeObserver;
-import org.apache.tapestry.event.PageDetachListener;
-import org.apache.tapestry.event.PageEvent;
-import org.apache.tapestry.event.PageRenderListener;
-import org.apache.tapestry.event.PageValidateListener;
+import org.apache.tapestry.event.*;
 import org.apache.tapestry.listener.ListenerMap;
 import org.apache.tapestry.param.ParameterManager;
 import org.apache.tapestry.spec.BaseLocatable;
@@ -40,6 +27,8 @@
 import org.apache.tapestry.util.prop.PropertyFinder;
 import org.apache.tapestry.util.prop.PropertyInfo;
 
+import java.util.*;
+
 /**
  *  Abstract base class implementing the {@link IComponent} interface.
  *
@@ -689,8 +678,7 @@
         if (_components == null)
             return EMPTY_MAP;
 
-        return Collections.unmodifiableMap(_components);
-
+        return _components;
     }
 
     public Map getAssets()
@@ -698,7 +686,7 @@
         if (_assets == null)
             return EMPTY_MAP;
 
-        return Collections.unmodifiableMap(_assets);
+        return _assets;
     }
 
     public IAsset getAsset(String name)

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/ApplicationServlet.java Wed Jun 25 14:14:11 2008
@@ -14,19 +14,7 @@
 
 package org.apache.tapestry;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Locale;
-
-import javax.servlet.ServletConfig;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
+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;
@@ -37,16 +25,19 @@
 import org.apache.tapestry.resource.ContextResourceLocation;
 import org.apache.tapestry.spec.ApplicationSpecification;
 import org.apache.tapestry.spec.IApplicationSpecification;
-import org.apache.tapestry.util.DefaultResourceResolver;
-import org.apache.tapestry.util.DelegatingPropertySource;
-import org.apache.tapestry.util.JanitorThread;
-import org.apache.tapestry.util.ServletContextPropertySource;
-import org.apache.tapestry.util.ServletPropertySource;
-import org.apache.tapestry.util.SystemPropertiesPropertySource;
+import org.apache.tapestry.util.*;
 import org.apache.tapestry.util.exception.ExceptionAnalyzer;
 import org.apache.tapestry.util.pool.Pool;
 import org.apache.tapestry.util.xml.DocumentParseException;
 
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.*;
+import java.io.IOException;
+import java.io.InputStream;
+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
@@ -147,6 +138,12 @@
     private IPropertySource _propertySource;
 
     /**
+     * Global lock used to synchronize global thread access to commonly shared
+     * services / data structures.
+     */
+    private ReentrantLock _lock = new ReentrantLock();
+
+    /**
      *  Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
      *
      *  @since 1.0.6
@@ -182,7 +179,6 @@
 
         try
         {
-
             // Create a context from the various bits and pieces.
 
             context = createRequestContext(request, response);
@@ -339,6 +335,16 @@
     }
 
     /**
+     * Used internally to synchronize access to creation of shared services.
+     *
+     * @return The global shared lock.
+     */
+    public ReentrantLock getLock()
+    {
+        return _lock;
+    }
+
+    /**
      *  Retrieves the {@link IEngine engine} that will process this
      *  request.  This comes from one of the following places:
      *  <ul>
@@ -724,7 +730,20 @@
     protected String searchConfiguration(String propertyName)
     {
         if (_propertySource == null)
-            _propertySource = createPropertySource();
+        {
+            _lock.lock();
+
+            try
+            {
+                if (_propertySource == null)
+                {
+                    _propertySource = createPropertySource();
+                }
+            } finally
+            {
+                _lock.unlock();
+            }
+        }
 
         return _propertySource.getPropertyValue(propertyName);
     }

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/AbstractEngine.java Wed Jun 25 14:14:11 2008
@@ -14,49 +14,12 @@
 
 package org.apache.tapestry.engine;
 
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.ResourceBundle;
-
-import javax.servlet.RequestDispatcher;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-import javax.servlet.http.HttpSessionBindingEvent;
-import javax.servlet.http.HttpSessionBindingListener;
-
 import org.apache.bsf.BSFManager;
 import org.apache.commons.codec.binary.Hex;
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.tapestry.ApplicationRuntimeException;
-import org.apache.tapestry.ApplicationServlet;
-import org.apache.tapestry.IEngine;
-import org.apache.tapestry.IMarkupWriter;
-import org.apache.tapestry.INamespace;
-import org.apache.tapestry.IPage;
-import org.apache.tapestry.IRequestCycle;
-import org.apache.tapestry.IResourceResolver;
-import org.apache.tapestry.PageRedirectException;
-import org.apache.tapestry.RedirectException;
-import org.apache.tapestry.StaleLinkException;
-import org.apache.tapestry.StaleSessionException;
-import org.apache.tapestry.Tapestry;
+import org.apache.tapestry.*;
 import org.apache.tapestry.asset.ResourceChecksumSource;
 import org.apache.tapestry.asset.ResourceChecksumSourceImpl;
 import org.apache.tapestry.enhance.DefaultComponentClassEnhancer;
@@ -65,16 +28,18 @@
 import org.apache.tapestry.request.RequestContext;
 import org.apache.tapestry.request.ResponseOutputStream;
 import org.apache.tapestry.spec.IApplicationSpecification;
-import org.apache.tapestry.util.DelegatingPropertySource;
-import org.apache.tapestry.util.PropertyHolderPropertySource;
-import org.apache.tapestry.util.ResourceBundlePropertySource;
-import org.apache.tapestry.util.ServletContextPropertySource;
-import org.apache.tapestry.util.ServletPropertySource;
-import org.apache.tapestry.util.SystemPropertiesPropertySource;
+import org.apache.tapestry.util.*;
 import org.apache.tapestry.util.exception.ExceptionAnalyzer;
 import org.apache.tapestry.util.io.DataSqueezer;
 import org.apache.tapestry.util.pool.Pool;
 
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.*;
+import java.io.*;
+import java.util.*;
+
 /**
  *  Basis for building real Tapestry applications.  Immediate subclasses
  *  provide different strategies for managing page state and other resources
@@ -128,7 +93,7 @@
  **/
 
 public abstract class AbstractEngine
-    implements IEngine, IEngineServiceView, Externalizable, HttpSessionBindingListener
+        implements IEngine, IEngineServiceView, Externalizable, HttpSessionBindingListener
 {
     private static final Log LOG = LogFactory.getLog(AbstractEngine.class);
 
@@ -186,7 +151,7 @@
      **/
 
     public static final String OUTPUT_ENCODING_PROPERTY_NAME =
-        "org.apache.tapestry.output-encoding";
+            "org.apache.tapestry.output-encoding";
 
     /**
      *  The default encoding that will be used when generating the output.
@@ -298,7 +263,7 @@
      **/
 
     protected static final String SPECIFICATION_SOURCE_NAME =
-        "org.apache.tapestry.SpecificationSource";
+            "org.apache.tapestry.SpecificationSource";
 
     /**
      *  Servlet context attribute name for the {@link IPageSource}
@@ -325,9 +290,9 @@
      * of {@link ResourceChecksumSource}.
      * @since 3.0.3
      */
-    protected static final String RESOURCE_CHECKSUM_SOURCE_NAME = 
-        "org.apache.tapestry.ResourceChecksumSource";
-    
+    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
@@ -347,7 +312,7 @@
      **/
 
     private static final boolean _resetServiceEnabled =
-        Boolean.getBoolean("org.apache.tapestry.enable-reset-service");
+            Boolean.getBoolean("org.apache.tapestry.enable-reset-service");
 
     /**
      * If true (set from the JVM system parameter
@@ -358,7 +323,7 @@
      **/
 
     private static final boolean _disableCaching =
-        Boolean.getBoolean("org.apache.tapestry.disable-caching");
+            Boolean.getBoolean("org.apache.tapestry.disable-caching");
 
     private transient IResourceResolver _resolver;
 
@@ -450,7 +415,7 @@
      * @since 3.0.3
      */
     private transient ResourceChecksumSource _resourceChecksumSource;
-    
+
     /**
      *  Sets the Exception page's exception property, then renders the Exception page.
      *
@@ -460,10 +425,10 @@
      **/
 
     protected void activateExceptionPage(
-        IRequestCycle cycle,
-        ResponseOutputStream output,
-        Throwable cause)
-        throws ServletException
+            IRequestCycle cycle,
+            ResponseOutputStream output,
+            Throwable cause)
+            throws ServletException
     {
         try
         {
@@ -482,15 +447,15 @@
             // us with no option but to write the cause to the output.
 
             reportException(
-                Tapestry.getMessage("AbstractEngine.unable-to-process-client-request"),
-                cause);
+                    Tapestry.getMessage("AbstractEngine.unable-to-process-client-request"),
+                    cause);
 
             // Also, write the exception thrown when redendering the exception
             // page, so that can get fixed as well.
 
             reportException(
-                Tapestry.getMessage("AbstractEngine.unable-to-present-exception-page"),
-                ex);
+                    Tapestry.getMessage("AbstractEngine.unable-to-present-exception-page"),
+                    ex);
 
             // And throw the exception.
 
@@ -512,7 +477,7 @@
         System.err.println(reportTitle);
 
         System.err.println(
-            "\n\n      Session id: "
+                "\n\n      Session id: "
                 + _sessionId
                 + "\n  Client address: "
                 + _clientAddress
@@ -582,9 +547,9 @@
         {
             if (_specification.checkExtension(Tapestry.MONITOR_FACTORY_EXTENSION_NAME))
                 _monitorFactory =
-                    (IMonitorFactory) _specification.getExtension(
-                        Tapestry.MONITOR_FACTORY_EXTENSION_NAME,
-                        IMonitorFactory.class);
+                        (IMonitorFactory) _specification.getExtension(
+                                Tapestry.MONITOR_FACTORY_EXTENSION_NAME,
+                                IMonitorFactory.class);
             else
                 _monitorFactory = DefaultMonitorFactory.SHARED;
         }
@@ -608,7 +573,7 @@
 
         if (result == null)
             throw new ApplicationRuntimeException(
-                Tapestry.format("AbstractEngine.unknown-service", name));
+                    Tapestry.format("AbstractEngine.unknown-service", name));
 
         return result;
     }
@@ -697,11 +662,11 @@
      **/
 
     protected void redirect(
-        String pageName,
-        IRequestCycle cycle,
-        ResponseOutputStream out,
-        ApplicationRuntimeException exception)
-        throws IOException, ServletException
+            String pageName,
+            IRequestCycle cycle,
+            ResponseOutputStream out,
+            ApplicationRuntimeException exception)
+            throws IOException, ServletException
     {
         // Discard any output from the previous page.
 
@@ -715,7 +680,7 @@
     }
 
     public void renderResponse(IRequestCycle cycle, ResponseOutputStream output)
-        throws ServletException, IOException
+            throws ServletException, IOException
     {
         if (LOG.isDebugEnabled())
             LOG.debug("Begin render response.");
@@ -948,10 +913,10 @@
             {
                 reportException(Tapestry.getMessage("AbstractEngine.exception-during-cleanup"), ex);
             }
-			finally
-			{
+            finally
+            {
                 cleanupAfterRequest(cycle);
-			}
+            }
 
             if (_disableCaching)
             {
@@ -962,8 +927,8 @@
                 catch (Exception ex)
                 {
                     reportException(
-                        Tapestry.getMessage("AbstractEngine.exception-during-cache-clear"),
-                        ex);
+                            Tapestry.getMessage("AbstractEngine.exception-during-cache-clear"),
+                            ex);
                 }
             }
 
@@ -987,10 +952,10 @@
      */
 
     protected void handlePageRedirectException(
-        PageRedirectException ex,
-        IRequestCycle cycle,
-        ResponseOutputStream output)
-        throws IOException, ServletException
+            PageRedirectException ex,
+            IRequestCycle cycle,
+            ResponseOutputStream output)
+            throws IOException, ServletException
     {
         List pageNames = new ArrayList();
 
@@ -1017,7 +982,7 @@
                 }
 
                 throw new ApplicationRuntimeException(
-                    Tapestry.format("AbstractEngine.validate-cycle", buffer.toString()));
+                        Tapestry.format("AbstractEngine.validate-cycle", buffer.toString()));
             }
 
             // Record that this page has been a target.
@@ -1055,9 +1020,9 @@
      **/
 
     protected IRequestCycle createRequestCycle(
-        RequestContext context,
-        IEngineService service,
-        IMonitor monitor)
+            RequestContext context,
+            IEngineService service,
+            IMonitor monitor)
     {
         return new RequestCycle(this, context, service, monitor);
     }
@@ -1088,10 +1053,10 @@
      **/
 
     protected void handleStaleLinkException(
-        StaleLinkException ex,
-        IRequestCycle cycle,
-        ResponseOutputStream output)
-        throws IOException, ServletException
+            StaleLinkException ex,
+            IRequestCycle cycle,
+            ResponseOutputStream output)
+            throws IOException, ServletException
     {
         String staleLinkPageName = getStaleLinkPageName();
         IPage page = cycle.getPage(staleLinkPageName);
@@ -1117,10 +1082,10 @@
      **/
 
     protected void handleStaleSessionException(
-        StaleSessionException ex,
-        IRequestCycle cycle,
-        ResponseOutputStream output)
-        throws IOException, ServletException
+            StaleSessionException ex,
+            IRequestCycle cycle,
+            ResponseOutputStream output)
+            throws IOException, ServletException
     {
         redirect(getStaleSessionPageName(), cycle, output, ex);
     }
@@ -1242,7 +1207,7 @@
             // will inform us.
 
             String path =
-                (String) request.getAttribute(Tapestry.TAG_SUPPORT_SERVLET_PATH_ATTRIBUTE);
+                    (String) request.getAttribute(Tapestry.TAG_SUPPORT_SERVLET_PATH_ATTRIBUTE);
 
             if (path == null)
                 path = request.getServletPath();
@@ -1265,9 +1230,22 @@
 
             if (_propertySource == null)
             {
-                _propertySource = createPropertySource(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
 
-                servletContext.setAttribute(name, _propertySource);
+                    _propertySource = (IPropertySource) servletContext.getAttribute(name);
+
+                    if (_propertySource == null)
+                    {
+                        _propertySource = createPropertySource(context);
+
+                        servletContext.setAttribute(name, _propertySource);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1279,9 +1257,22 @@
 
             if (_enhancer == null)
             {
-                _enhancer = createComponentClassEnhancer(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
 
-                servletContext.setAttribute(name, _enhancer);
+                    _enhancer = (IComponentClassEnhancer) servletContext.getAttribute(name);
+
+                    if (_enhancer == null)
+                    {
+                        _enhancer = createComponentClassEnhancer(context);
+
+                        servletContext.setAttribute(name, _enhancer);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1293,9 +1284,22 @@
 
             if (_pool == null)
             {
-                _pool = createPool(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
+
+                    _pool = (Pool) servletContext.getAttribute(name);
 
-                servletContext.setAttribute(name, _pool);
+                    if (_pool == null)
+                    {
+                        _pool = createPool(context);
+
+                        servletContext.setAttribute(name, _pool);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1307,9 +1311,22 @@
 
             if (_templateSource == null)
             {
-                _templateSource = createTemplateSource(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
+
+                    _templateSource = (ITemplateSource) servletContext.getAttribute(name);
 
-                servletContext.setAttribute(name, _templateSource);
+                    if (_templateSource == null)
+                    {
+                        _templateSource = createTemplateSource(context);
+
+                        servletContext.setAttribute(name, _templateSource);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1321,9 +1338,22 @@
 
             if (_specificationSource == null)
             {
-                _specificationSource = createSpecificationSource(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
+
+                    _specificationSource = (ISpecificationSource) servletContext.getAttribute(name);
 
-                servletContext.setAttribute(name, _specificationSource);
+                    if (_specificationSource == null)
+                    {
+                        _specificationSource = createSpecificationSource(context);
+
+                        servletContext.setAttribute(name, _specificationSource);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1335,9 +1365,22 @@
 
             if (_pageSource == null)
             {
-                _pageSource = createPageSource(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
+
+                    _pageSource = (IPageSource) servletContext.getAttribute(name);
 
-                servletContext.setAttribute(name, _pageSource);
+                    if (_pageSource == null)
+                    {
+                        _pageSource = createPageSource(context);
+
+                        servletContext.setAttribute(name, _pageSource);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1349,9 +1392,22 @@
 
             if (_scriptSource == null)
             {
-                _scriptSource = createScriptSource(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
+
+                    _scriptSource = (IScriptSource) servletContext.getAttribute(name);
+
+                    if (_scriptSource == null)
+                    {
+                        _scriptSource = createScriptSource(context);
 
-                servletContext.setAttribute(name, _scriptSource);
+                        servletContext.setAttribute(name, _scriptSource);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1363,9 +1419,22 @@
 
             if (_serviceMap == null)
             {
-                _serviceMap = createServiceMap();
+                try
+                {
+                    context.getServlet().getLock().lock();
+
+                    _serviceMap = (Map) servletContext.getAttribute(name);
+
+                    if (_serviceMap == null)
+                    {
+                        _serviceMap = createServiceMap();
 
-                servletContext.setAttribute(name, _serviceMap);
+                        servletContext.setAttribute(name, _serviceMap);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1377,9 +1446,22 @@
 
             if (_stringsSource == null)
             {
-                _stringsSource = createComponentStringsSource(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
+
+                    _stringsSource = (IComponentMessagesSource) servletContext.getAttribute(name);
 
-                servletContext.setAttribute(name, _stringsSource);
+                    if (_stringsSource == null)
+                    {
+                        _stringsSource = createComponentStringsSource(context);
+
+                        servletContext.setAttribute(name, _stringsSource);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1391,9 +1473,22 @@
 
             if (_dataSqueezer == null)
             {
-                _dataSqueezer = createDataSqueezer();
+                try
+                {
+                    context.getServlet().getLock().lock();
 
-                servletContext.setAttribute(name, _dataSqueezer);
+                    _dataSqueezer = (DataSqueezer) servletContext.getAttribute(name);
+
+                    if (_dataSqueezer == null)
+                    {
+                        _dataSqueezer = createDataSqueezer();
+
+                        servletContext.setAttribute(name, _dataSqueezer);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1405,12 +1500,25 @@
 
             if (_global == null)
             {
-                _global = createGlobal(context);
+                try
+                {
+                    context.getServlet().getLock().lock();
 
-                servletContext.setAttribute(name, _global);
+                    _global = servletContext.getAttribute(name);
+
+                    if (_global == null)
+                    {
+                        _global = createGlobal(context);
+
+                        servletContext.setAttribute(name, _global);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
-        
+
         if (_resourceChecksumSource == null)
         {
             String name = RESOURCE_CHECKSUM_SOURCE_NAME + ":" + servletName;
@@ -1419,9 +1527,22 @@
 
             if (_resourceChecksumSource == null)
             {
-                _resourceChecksumSource = createResourceChecksumSource();
+                try
+                {
+                    context.getServlet().getLock().lock();
 
-                servletContext.setAttribute(name, _resourceChecksumSource);
+                    _resourceChecksumSource = (ResourceChecksumSource) servletContext.getAttribute(name);
+
+                    if (_resourceChecksumSource == null)
+                    {
+                        _resourceChecksumSource = createResourceChecksumSource();
+
+                        servletContext.setAttribute(name, _resourceChecksumSource);
+                    }
+                } finally
+                {
+                    context.getServlet().getLock().unlock();
+                }
             }
         }
 
@@ -1541,7 +1662,7 @@
     {
         return new ResourceChecksumSourceImpl("MD5", new Hex());
     }
-    
+
     /**
      *  Returns an object which can find resources and classes.
      *
@@ -1566,10 +1687,10 @@
         ToStringBuilder builder = new ToStringBuilder(this);
 
         builder.append(
-            "name",
-            _specification == null
-                ? Tapestry.getMessage("AbstractEngine.unknown-specification")
-                : _specification.getName());
+                "name",
+                _specification == null
+                        ? Tapestry.getMessage("AbstractEngine.unknown-specification")
+                        : _specification.getName());
 
         builder.append("dirty", _dirty);
         builder.append("locale", _locale);
@@ -1703,8 +1824,8 @@
         catch (Throwable t)
         {
             throw new ApplicationRuntimeException(
-                Tapestry.format("AbstractEngine.unable-to-instantiate-visit", visitClassName),
-                t);
+                    Tapestry.format("AbstractEngine.unable-to-instantiate-visit", visitClassName),
+                    t);
         }
 
         return result;
@@ -1807,7 +1928,7 @@
 
             if (dispatcher == null)
                 throw new ApplicationRuntimeException(
-                    Tapestry.format("AbstractEngine.unable-to-find-dispatcher", _location));
+                        Tapestry.format("AbstractEngine.unable-to-find-dispatcher", _location));
 
             try
             {
@@ -1816,14 +1937,14 @@
             catch (ServletException ex)
             {
                 throw new ApplicationRuntimeException(
-                    Tapestry.format("AbstractEngine.unable-to-forward", _location),
-                    ex);
+                        Tapestry.format("AbstractEngine.unable-to-forward", _location),
+                        ex);
             }
             catch (IOException ex)
             {
                 throw new ApplicationRuntimeException(
-                    Tapestry.format("AbstractEngine.unable-to-forward", _location),
-                    ex);
+                        Tapestry.format("AbstractEngine.unable-to-forward", _location),
+                        ex);
             }
         }
 
@@ -1840,8 +1961,8 @@
             catch (IOException ex)
             {
                 throw new ApplicationRuntimeException(
-                    Tapestry.format("AbstractEngine.unable-to-redirect", _location),
-                    ex);
+                        Tapestry.format("AbstractEngine.unable-to-redirect", _location),
+                        ex);
             }
         }
 
@@ -1921,11 +2042,11 @@
 
                 if (!service.getName().equals(name))
                     throw new ApplicationRuntimeException(
-                        Tapestry.format(
-                            "AbstractEngine.service-name-mismatch",
-                            name,
-                            className,
-                            serviceName));
+                            Tapestry.format(
+                                    "AbstractEngine.service-name-mismatch",
+                                    name,
+                                    className,
+                                    serviceName));
 
                 // Replace the class name with an instance
                 // of the named class.
@@ -1935,10 +2056,10 @@
             catch (InstantiationException ex)
             {
                 String message =
-                    Tapestry.format(
-                        "AbstractEngine.unable-to-instantiate-service",
-                        name,
-                        className);
+                        Tapestry.format(
+                                "AbstractEngine.unable-to-instantiate-service",
+                                name,
+                                className);
 
                 LOG.error(message, ex);
 
@@ -1947,10 +2068,10 @@
             catch (IllegalAccessException ex)
             {
                 String message =
-                    Tapestry.format(
-                        "AbstractEngine.unable-to-instantiate-service",
-                        name,
-                        className);
+                        Tapestry.format(
+                                "AbstractEngine.unable-to-instantiate-service",
+                                name,
+                                className);
 
                 LOG.error(message, ex);
 
@@ -2084,12 +2205,12 @@
     }
 
     /** @since 3.0.3 */
-    
+
     public ResourceChecksumSource getResourceChecksumSource()
     {
         return _resourceChecksumSource;
     }
-    
+
     /** @since 3.0 **/
 
     protected String getExceptionPageName()
@@ -2120,7 +2241,7 @@
      **/
 
     private static final String EXTENSION_PROPERTY_SOURCE_NAME =
-        "org.apache.tapestry.property-source";
+            "org.apache.tapestry.property-source";
 
     /**
      *  Creates a shared property source that will be stored into
@@ -2157,9 +2278,9 @@
         if (spec.checkExtension(EXTENSION_PROPERTY_SOURCE_NAME))
         {
             IPropertySource source =
-                (IPropertySource) spec.getExtension(
-                    EXTENSION_PROPERTY_SOURCE_NAME,
-                    IPropertySource.class);
+                    (IPropertySource) spec.getExtension(
+                            EXTENSION_PROPERTY_SOURCE_NAME,
+                            IPropertySource.class);
 
             result.addSource(source);
         }
@@ -2169,7 +2290,7 @@
         // Lastly, add a final source to handle "factory defaults".
 
         ResourceBundle bundle =
-            ResourceBundle.getBundle("org.apache.tapestry.ConfigurationDefaults");
+                ResourceBundle.getBundle("org.apache.tapestry.ConfigurationDefaults");
 
         result.addSource(new ResourceBundlePropertySource(bundle));
 
@@ -2203,8 +2324,8 @@
         catch (Exception ex)
         {
             throw new ApplicationRuntimeException(
-                Tapestry.format("AbstractEngine.unable-to-instantiate-global", className),
-                ex);
+                    Tapestry.format("AbstractEngine.unable-to-instantiate-global", className),
+                    ex);
         }
     }
 
@@ -2241,7 +2362,7 @@
      * 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
@@ -2254,9 +2375,9 @@
     protected IComponentClassEnhancer createComponentClassEnhancer(RequestContext context)
     {
         boolean disableValidation =
-            "true".equals(
-                _propertySource.getPropertyValue(
-                    "org.apache.tapestry.enhance.disable-abstract-method-validation"));
+                "true".equals(
+                        _propertySource.getPropertyValue(
+                                "org.apache.tapestry.enhance.disable-abstract-method-validation"));
 
         return new DefaultComponentClassEnhancer(_resolver, disableValidation);
     }

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/BaseEngine.java Wed Jun 25 14:14:11 2008
@@ -14,23 +14,17 @@
 
 package org.apache.tapestry.engine;
 
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
 import org.apache.commons.lang.builder.ToStringBuilder;
 import org.apache.tapestry.ApplicationRuntimeException;
 import org.apache.tapestry.IRequestCycle;
 import org.apache.tapestry.Tapestry;
 import org.apache.tapestry.record.SessionPageRecorder;
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.util.*;
+
 /**
  *  Concrete implementation of {@link org.apache.tapestry.IEngine} used for ordinary
  *  applications.  All page state information is maintained in
@@ -39,7 +33,7 @@
  *
  *  @author Howard Lewis Ship
  *  @version $Id$
- * 
+ *
  **/
 
 public class BaseEngine extends AbstractEngine
@@ -65,7 +59,7 @@
         if (Tapestry.isEmpty(_recorders))
             return;
 
-		boolean markDirty = false;
+        boolean markDirty = false;
         Iterator i = _recorders.entrySet().iterator();
 
         while (i.hasNext())
@@ -81,13 +75,13 @@
                 i.remove();
 
                 _activePageNames.remove(pageName);
-      	
-      			markDirty = true;
+
+                markDirty = true;
             }
         }
-        
+
         if (markDirty)
-        	markDirty();
+            markDirty();
     }
 
     public void forgetPage(String name)
@@ -101,19 +95,19 @@
 
         if (recorder.isDirty())
             throw new ApplicationRuntimeException(
-                Tapestry.format("BaseEngine.recorder-has-uncommited-changes", name));
+                    Tapestry.format("BaseEngine.recorder-has-uncommited-changes", name));
 
         recorder.discard();
         _recorders.remove(name);
         _activePageNames.remove(name);
-        
+
         markDirty();
     }
 
     /**
      *  Returns an unmodifiable {@link Collection} of the page names for which
      *  {@link IPageRecorder} instances exist.
-     * 
+     *
      *
      **/
 
@@ -147,19 +141,18 @@
     public IPageRecorder createPageRecorder(String pageName, IRequestCycle cycle)
     {
         if (_recorders == null)
-            _recorders = new HashMap(MAP_SIZE);
+            _recorders = new HashMap();
         else
         {
             if (_recorders.containsKey(pageName))
                 throw new ApplicationRuntimeException(
-                    Tapestry.format("BaseEngine.duplicate-page-recorder", pageName));
+                        Tapestry.format("BaseEngine.duplicate-page-recorder", pageName));
         }
 
         // Force the creation of the HttpSession
 
         cycle.getRequestContext().createSession();
         setStateful();
-       
 
         IPageRecorder result = new SessionPageRecorder();
         result.initialize(pageName, cycle);
@@ -170,7 +163,7 @@
             _activePageNames = new HashSet();
 
         _activePageNames.add(pageName);
-        
+
         markDirty();
 
         return result;
@@ -179,7 +172,7 @@
     /**
      *  Reconstructs the list of active page names
      *  written by {@link #writeExternal(ObjectOutput)}.
-     * 
+     *
      **/
 
     public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
@@ -204,7 +197,7 @@
      *  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
@@ -233,7 +226,7 @@
 
     public void extendDescription(ToStringBuilder builder)
     {
-		builder.append("activePageNames", _activePageNames);
+        builder.append("activePageNames", _activePageNames);
     }
 
 }
\ No newline at end of file

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultSpecificationSource.java Wed Jun 25 14:14:11 2008
@@ -14,20 +14,12 @@
 
 package org.apache.tapestry.engine;
 
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
+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;
-import org.apache.tapestry.ApplicationRuntimeException;
-import org.apache.tapestry.IMarkupWriter;
-import org.apache.tapestry.INamespace;
-import org.apache.tapestry.IResourceLocation;
-import org.apache.tapestry.IResourceResolver;
-import org.apache.tapestry.Tapestry;
+import org.apache.tapestry.*;
 import org.apache.tapestry.parse.SpecificationParser;
 import org.apache.tapestry.resource.ClasspathResourceLocation;
 import org.apache.tapestry.spec.IApplicationSpecification;
@@ -38,6 +30,10 @@
 import org.apache.tapestry.util.pool.Pool;
 import org.apache.tapestry.util.xml.DocumentParseException;
 
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
 /**
  *  Default implementation of {@link ISpecificationSource} that
  *  expects to use the normal class loader to locate component
@@ -50,7 +46,7 @@
  *
  * @author Howard Lewis Ship
  * @version $Id$
- * 
+ *
  **/
 
 public class DefaultSpecificationSource implements ISpecificationSource, IRenderDescription
@@ -60,9 +56,9 @@
     /**
      *  Key used to get and store {@link SpecificationParser} instances
      *  from the Pool.
-     * 
+     *
      *  @since 3.0
-     * 
+     *
      **/
 
     private static final String PARSER_POOL_KEY = "org.apache.tapestry.SpecificationParser";
@@ -78,50 +74,60 @@
      *
      **/
 
-    private Map _componentCache = new HashMap();
+    private Map _componentCache = new ConcurrentHashMap();
 
     /**
      *  Contains previously parsed page specifications.
-     * 
+     *
      *  @since 2.2
-     * 
+     *
      **/
 
-    private Map _pageCache = new HashMap();
+    private Map _pageCache = new ConcurrentHashMap();
 
     /**
      *  Contains previously parsed library specifications, keyed
      *  on specification resource path.
-     * 
+     *
      *  @since 2.2
-     * 
+     *
      **/
 
-    private Map _libraryCache = new HashMap();
+    private Map _libraryCache = new ConcurrentHashMap();
 
     /**
      *  Contains {@link INamespace} instances, keyed on id (which will
      *  be null for the application specification).
-     * 
+     *
      **/
 
-    private Map _namespaceCache = new HashMap();
+    private Map _namespaceCache = new ConcurrentHashMap();
+
+    /**
+     * Used to synchronize concurrent operations on specific resources.
+     */
+    private ConcurrentHashMap _lockCache = new ConcurrentHashMap();
 
     /**
      *  Reference to the shared {@link org.apache.tapestry.util.pool.Pool}.
-     * 
+     *
      *  @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,
-        Pool pool)
+            IResourceResolver resolver,
+            IApplicationSpecification specification,
+            Pool pool)
     {
         _resolver = resolver;
         _specification = specification;
@@ -133,20 +139,29 @@
      *
      **/
 
-    public synchronized void reset()
+    public void reset()
     {
-        _componentCache.clear();
-        _pageCache.clear();
-        _libraryCache.clear();
-        _namespaceCache.clear();
+        _monitor.lock();
 
-        _applicationNamespace = null;
-        _frameworkNamespace = null;
+        try
+        {
+            _componentCache.clear();
+            _pageCache.clear();
+            _libraryCache.clear();
+            _namespaceCache.clear();
+            _lockCache.clear();
+
+            _applicationNamespace = null;
+            _frameworkNamespace = null;
+        } finally
+        {
+            _monitor.unlock();
+        }
     }
 
     protected IComponentSpecification parseSpecification(
-        IResourceLocation resourceLocation,
-        boolean asPage)
+            IResourceLocation resourceLocation,
+            boolean asPage)
     {
         IComponentSpecification result = null;
 
@@ -165,10 +180,10 @@
         catch (DocumentParseException ex)
         {
             throw new ApplicationRuntimeException(
-                Tapestry.format(
-                    "DefaultSpecificationSource.unable-to-parse-specification",
-                    resourceLocation),
-                ex);
+                    Tapestry.format(
+                            "DefaultSpecificationSource.unable-to-parse-specification",
+                            resourceLocation),
+                    ex);
         }
         finally
         {
@@ -190,15 +205,15 @@
         catch (DocumentParseException ex)
         {
             throw new ApplicationRuntimeException(
-                Tapestry.format(
-                    "DefaultSpecificationSource.unable-to-parse-specification",
-                    resourceLocation),
-                ex);
+                    Tapestry.format(
+                            "DefaultSpecificationSource.unable-to-parse-specification",
+                            resourceLocation),
+                    ex);
         }
 
     }
 
-    public synchronized String toString()
+    public String toString()
     {
         ToStringBuilder builder = new ToStringBuilder(this);
 
@@ -211,7 +226,7 @@
 
     /** @since 1.0.6 **/
 
-    public synchronized void renderDescription(IMarkupWriter writer)
+    public void renderDescription(IMarkupWriter writer)
     {
         writer.print("DefaultSpecificationSource[");
 
@@ -259,49 +274,94 @@
 
     /**
      *  Gets a component specification.
-     * 
+     *
      *  @param resourceLocation the complete resource path to the specification.
      *  @throws ApplicationRuntimeException if the specification cannot be obtained.
-     * 
+     *
      **/
 
-    public synchronized IComponentSpecification getComponentSpecification(IResourceLocation resourceLocation)
+    public IComponentSpecification getComponentSpecification(IResourceLocation resourceLocation)
     {
         IComponentSpecification result =
-            (IComponentSpecification) _componentCache.get(resourceLocation);
+                (IComponentSpecification) _componentCache.get(resourceLocation);
 
-        if (result == null)
+        if (result != null)
+            return result;
+
+        ReentrantLock lock = getLock(resourceLocation);
+
+        lock.lock();
+
+        try
         {
+            result = (IComponentSpecification) _componentCache.get(resourceLocation);
+
+            if (result != null)
+                return result;
+
             result = parseSpecification(resourceLocation, false);
 
             _componentCache.put(resourceLocation, result);
+        } finally
+        {
+            lock.unlock();
         }
 
         return result;
     }
 
-    public synchronized IComponentSpecification getPageSpecification(IResourceLocation resourceLocation)
+    public IComponentSpecification getPageSpecification(IResourceLocation resourceLocation)
     {
         IComponentSpecification result = (IComponentSpecification) _pageCache.get(resourceLocation);
 
-        if (result == null)
+        if (result != null)
+            return result;
+
+        ReentrantLock lock = getLock(resourceLocation);
+
+        lock.lock();
+
+        try
         {
+            result = (IComponentSpecification) _pageCache.get(resourceLocation);
+
+            if (result != null)
+                return result;
+
             result = parseSpecification(resourceLocation, true);
 
             _pageCache.put(resourceLocation, result);
+        } finally
+        {
+            lock.unlock();
         }
 
         return result;
     }
 
-    public synchronized ILibrarySpecification getLibrarySpecification(IResourceLocation resourceLocation)
+    public ILibrarySpecification getLibrarySpecification(IResourceLocation resourceLocation)
     {
         ILibrarySpecification result = (LibrarySpecification) _libraryCache.get(resourceLocation);
 
-        if (result == null)
+        if (result != null)
+            return result;
+
+        ReentrantLock lock = getLock(resourceLocation);
+
+        lock.lock();
+
+        try
         {
+            result = (LibrarySpecification) _libraryCache.get(resourceLocation);
+
+            if (result != null)
+                return result;
+
             result = parseLibrarySpecification(resourceLocation);
             _libraryCache.put(resourceLocation, result);
+        } finally
+        {
+            lock.unlock();
         }
 
         return result;
@@ -326,27 +386,52 @@
         _pool.store(PARSER_POOL_KEY, parser);
     }
 
-    public synchronized INamespace getApplicationNamespace()
+    public INamespace getApplicationNamespace()
     {
-        if (_applicationNamespace == null)
-            _applicationNamespace = new Namespace(null, null, _specification, this);
+        _monitor.lock();
+
+        try
+        {
+            if (_applicationNamespace == null)
+                _applicationNamespace = new Namespace(null, null, _specification, this);
+
+            return _applicationNamespace;
 
-        return _applicationNamespace;
+        } finally
+        {
+            _monitor.unlock();
+        }
     }
 
-    public synchronized INamespace getFrameworkNamespace()
+    public INamespace getFrameworkNamespace()
     {
-        if (_frameworkNamespace == null)
+        _monitor.lock();
+
+        try
         {
-            IResourceLocation frameworkLocation =
-                new ClasspathResourceLocation(_resolver, "/org/apache/tapestry/Framework.library");
+            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);
+            }
 
-            ILibrarySpecification ls = getLibrarySpecification(frameworkLocation);
+            return _frameworkNamespace;
 
-            _frameworkNamespace = new Namespace(INamespace.FRAMEWORK_NAMESPACE, null, ls, this);
+        } finally
+        {
+            _monitor.unlock();
         }
+    }
+
+    private ReentrantLock getLock(Object key)
+    {
+        _lockCache.putIfAbsent(key, new ReentrantLock());
 
-        return _frameworkNamespace;
+        return (ReentrantLock) _lockCache.get(key);
     }
 
 }
\ No newline at end of file

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java Wed Jun 25 14:14:11 2008
@@ -14,44 +14,26 @@
 
 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;
+import org.apache.tapestry.*;
+import org.apache.tapestry.parse.*;
+import org.apache.tapestry.spec.IApplicationSpecification;
+import org.apache.tapestry.spec.IComponentSpecification;
+import org.apache.tapestry.util.*;
+
 import java.io.BufferedInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
-import java.util.Collections;
-import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Locale;
 import java.util.Map;
 
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.tapestry.ApplicationRuntimeException;
-import org.apache.tapestry.IAsset;
-import org.apache.tapestry.IComponent;
-import org.apache.tapestry.IEngine;
-import org.apache.tapestry.ILocation;
-import org.apache.tapestry.IMarkupWriter;
-import org.apache.tapestry.INamespace;
-import org.apache.tapestry.IRequestCycle;
-import org.apache.tapestry.IResourceLocation;
-import org.apache.tapestry.Tapestry;
-import org.apache.tapestry.parse.ComponentTemplate;
-import org.apache.tapestry.parse.ITemplateParserDelegate;
-import org.apache.tapestry.parse.TemplateParseException;
-import org.apache.tapestry.parse.TemplateParser;
-import org.apache.tapestry.parse.TemplateToken;
-import org.apache.tapestry.resolver.ComponentSpecificationResolver;
-import org.apache.tapestry.spec.IApplicationSpecification;
-import org.apache.tapestry.spec.IComponentSpecification;
-import org.apache.tapestry.util.DelegatingPropertySource;
-import org.apache.tapestry.util.IRenderDescription;
-import org.apache.tapestry.util.LocalizedPropertySource;
-import org.apache.tapestry.util.MultiKey;
-import org.apache.tapestry.util.PropertyHolderPropertySource;
-
 /**
  *  Default implementation of {@link ITemplateSource}.  Templates, once parsed,
  *  stay in memory until explicitly cleared.
@@ -61,7 +43,7 @@
  *
  *  @author Howard Lewis Ship
  *  @version $Id$
- * 
+ *
  **/
 
 public class DefaultTemplateSource implements ITemplateSource, IRenderDescription
@@ -71,19 +53,22 @@
 
     // The name of the component/application/etc property that will be used to
     // determine the encoding to use when loading the template
-         
-    private static final String TEMPLATE_ENCODING_PROPERTY_NAME = "org.apache.tapestry.template-encoding"; 
+
+    private static final String TEMPLATE_ENCODING_PROPERTY_NAME = "org.apache.tapestry.template-encoding";
 
     // Cache of previously retrieved templates.  Key is a multi-key of 
     // specification resource path and locale (local may be null), value
     // is the ComponentTemplate.
 
-    private Map _cache = Collections.synchronizedMap(new HashMap());
+    private Map _cache = new ConcurrentHashMap();//Collections.synchronizedMap(new HashMap());
 
     // Previously read templates; key is the IResourceLocation, value
     // is the ComponentTemplate.
 
-    private Map _templates = Collections.synchronizedMap(new HashMap());
+    private Map _templates = new ConcurrentHashMap(); //Collections.synchronizedMap(new HashMap());
+
+    // Used to synchronize access to specific templates
+    private ConcurrentHashMap _lockCache = new ConcurrentHashMap();
 
     /**
      *  Number of tokens (each template contains multiple tokens).
@@ -113,6 +98,7 @@
     {
         _cache.clear();
         _templates.clear();
+        _lockCache.clear();
 
         _tokenCount = 0;
     }
@@ -121,7 +107,7 @@
      *  Reads the template for the component.
      *
      *  <p>Returns null if the template can't be found.
-     * 
+     *
      **/
 
     public ComponentTemplate getTemplate(IRequestCycle cycle, IComponent component)
@@ -137,29 +123,43 @@
         if (result != null)
             return result;
 
-        result = findTemplate(cycle, specificationLocation, component, locale);
+        _lockCache.putIfAbsent(key, new ReentrantLock());
 
-        if (result == null)
-        {
-            result = getTemplateFromDelegate(cycle, component, locale);
+        ReentrantLock lock = (ReentrantLock)_lockCache.get(key);
 
+        lock.lock();
+        try
+        {
+            result = searchCache(key);
             if (result != null)
                 return result;
 
-            String stringKey =
-                component.getSpecification().isPageSpecification()
-                    ? "DefaultTemplateSource.no-template-for-page"
-                    : "DefaultTemplateSource.no-template-for-component";
+            result = findTemplate(cycle, specificationLocation, component, locale);
 
-            throw new ApplicationRuntimeException(
-                Tapestry.format(stringKey, component.getExtendedId(), locale),
-                component,
-                component.getLocation(),
-                null);
-        }
+            if (result == null)
+            {
+                result = getTemplateFromDelegate(cycle, component, locale);
+
+                if (result != null)
+                    return result;
 
-        saveToCache(key, result);
+                String stringKey =
+                        component.getSpecification().isPageSpecification()
+                                ? "DefaultTemplateSource.no-template-for-page"
+                                : "DefaultTemplateSource.no-template-for-component";
+
+                throw new ApplicationRuntimeException(
+                        Tapestry.format(stringKey, component.getExtendedId(), locale),
+                        component,
+                        component.getLocation(),
+                        null);
+            }
 
+            saveToCache(key, result);
+        } finally
+        {
+            lock.unlock();
+        }
         return result;
     }
 
@@ -175,9 +175,9 @@
     }
 
     private ComponentTemplate getTemplateFromDelegate(
-        IRequestCycle cycle,
-        IComponent component,
-        Locale locale)
+            IRequestCycle cycle,
+            IComponent component,
+            Locale locale)
     {
         if (_delegate == null)
         {
@@ -186,9 +186,9 @@
 
             if (spec.checkExtension(Tapestry.TEMPLATE_SOURCE_DELEGATE_EXTENSION_NAME))
                 _delegate =
-                    (ITemplateSourceDelegate) spec.getExtension(
-                        Tapestry.TEMPLATE_SOURCE_DELEGATE_EXTENSION_NAME,
-                        ITemplateSourceDelegate.class);
+                        (ITemplateSourceDelegate) spec.getExtension(
+                                Tapestry.TEMPLATE_SOURCE_DELEGATE_EXTENSION_NAME,
+                                ITemplateSourceDelegate.class);
             else
                 _delegate = NullTemplateSourceDelegate.getSharedInstance();
 
@@ -205,16 +205,16 @@
      *  <li>If a page in the application namespace, search in the application root
      *  <li>Fail!
      *  </ul>
-     * 
+     *
      *  @return the template, or null if not found
-     * 
+     *
      **/
 
     private ComponentTemplate findTemplate(
-        IRequestCycle cycle,
-        IResourceLocation location,
-        IComponent component,
-        Locale locale)
+            IRequestCycle cycle,
+            IResourceLocation location,
+            IComponent component,
+            Locale locale)
     {
         IAsset templateAsset = component.getAsset(TEMPLATE_ASSET_NAME);
 
@@ -226,7 +226,7 @@
         String templateBaseName = name.substring(0, dotx + 1) + getTemplateExtension(component);
 
         ComponentTemplate result =
-            findStandardTemplate(cycle, location, component, templateBaseName, locale);
+                findStandardTemplate(cycle, location, component, templateBaseName, locale);
 
         if (result == null
             && component.getSpecification().isPageSpecification()
@@ -237,10 +237,10 @@
     }
 
     private ComponentTemplate findPageTemplateInApplicationRoot(
-        IRequestCycle cycle,
-        IComponent component,
-        String templateBaseName,
-        Locale locale)
+            IRequestCycle cycle,
+            IComponent component,
+            String templateBaseName,
+            Locale locale)
     {
         if (LOG.isDebugEnabled())
             LOG.debug("Checking for " + templateBaseName + " in application root");
@@ -249,7 +249,7 @@
             _applicationRootLocation = Tapestry.getApplicationRootLocation(cycle);
 
         IResourceLocation baseLocation =
-            _applicationRootLocation.getRelativeLocation(templateBaseName);
+                _applicationRootLocation.getRelativeLocation(templateBaseName);
         IResourceLocation localizedLocation = baseLocation.getLocalization(locale);
 
         if (localizedLocation == null)
@@ -260,13 +260,13 @@
 
     /**
      *  Reads an asset to get the template.
-     * 
+     *
      **/
 
     private ComponentTemplate readTemplateFromAsset(
-        IRequestCycle cycle,
-        IComponent component,
-        IAsset asset)
+            IRequestCycle cycle,
+            IComponent component,
+            IAsset asset)
     {
         InputStream stream = asset.getResourceAsStream(cycle);
 
@@ -275,7 +275,7 @@
         try
         {
             String encoding = getTemplateEncoding(cycle, component, null);
-            
+
             templateData = readTemplateStream(stream, encoding);
 
             stream.close();
@@ -283,8 +283,8 @@
         catch (IOException ex)
         {
             throw new ApplicationRuntimeException(
-                Tapestry.format("DefaultTemplateSource.unable-to-read-template", asset),
-                ex);
+                    Tapestry.format("DefaultTemplateSource.unable-to-read-template", asset),
+                    ex);
         }
 
         IResourceLocation resourceLocation = asset.getResourceLocation();
@@ -298,19 +298,19 @@
      *  parsing the template.
      *
      *  @return the template, or null if not found.
-     * 
+     *
      **/
 
     private ComponentTemplate findStandardTemplate(
-        IRequestCycle cycle,
-        IResourceLocation location,
-        IComponent component,
-        String templateBaseName,
-        Locale locale)
+            IRequestCycle cycle,
+            IResourceLocation location,
+            IComponent component,
+            String templateBaseName,
+            Locale locale)
     {
         if (LOG.isDebugEnabled())
             LOG.debug(
-                "Searching for localized version of template for "
+                    "Searching for localized version of template for "
                     + location
                     + " in locale "
                     + locale.getDisplayName());
@@ -330,13 +330,13 @@
      *  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,
-        IResourceLocation location,
-        IComponent component)
+            IRequestCycle cycle,
+            IResourceLocation location,
+            IComponent component)
     {
 
         ComponentTemplate result = (ComponentTemplate) _templates.get(location);
@@ -362,12 +362,12 @@
      **/
 
     private ComponentTemplate parseTemplate(
-        IRequestCycle cycle,
-        IResourceLocation location,
-        IComponent component)
+            IRequestCycle cycle,
+            IResourceLocation location,
+            IComponent component)
     {
         String encoding = getTemplateEncoding(cycle, component, location.getLocale());
-        
+
         char[] templateData = readTemplate(location, encoding);
         if (templateData == null)
             return null;
@@ -375,19 +375,19 @@
         return constructTemplateInstance(cycle, templateData, location, component);
     }
 
-    /** 
+    /**
      *  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,
-        char[] templateData,
-        IResourceLocation location,
-        IComponent component)
+            IRequestCycle cycle,
+            char[] templateData,
+            IResourceLocation location,
+            IComponent component)
     {
         if (_parser == null)
             _parser = new TemplateParser();
@@ -403,8 +403,8 @@
         catch (TemplateParseException ex)
         {
             throw new ApplicationRuntimeException(
-                Tapestry.format("DefaultTemplateSource.unable-to-parse-template", location),
-                ex);
+                    Tapestry.format("DefaultTemplateSource.unable-to-parse-template", location),
+                    ex);
         }
 
         if (LOG.isDebugEnabled())
@@ -450,8 +450,8 @@
         catch (IOException ex)
         {
             throw new ApplicationRuntimeException(
-                Tapestry.format("DefaultTemplateSource.unable-to-read-template", location),
-                ex);
+                    Tapestry.format("DefaultTemplateSource.unable-to-read-template", location),
+                    ex);
         }
         finally
         {
@@ -523,20 +523,20 @@
      *  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)
     {
         String extension =
-            component.getSpecification().getProperty(Tapestry.TEMPLATE_EXTENSION_PROPERTY);
+                component.getSpecification().getProperty(Tapestry.TEMPLATE_EXTENSION_PROPERTY);
 
         if (extension != null)
             return extension;
 
         extension =
-            component.getNamespace().getSpecification().getProperty(
-                Tapestry.TEMPLATE_EXTENSION_PROPERTY);
+                component.getNamespace().getSpecification().getProperty(
+                        Tapestry.TEMPLATE_EXTENSION_PROPERTY);
 
         if (extension != null)
             return extension;
@@ -592,7 +592,7 @@
         writer.print("]");
 
     }
-    
+
     private String getTemplateEncoding(IRequestCycle cycle, IComponent component, Locale locale)
     {
         IPropertySource source = getComponentPropertySource(cycle, component);
@@ -602,7 +602,7 @@
 
         return getTemplateEncodingProperty(source);
     }
-    
+
     private IPropertySource getComponentPropertySource(IRequestCycle cycle, IComponent component)
     {
         DelegatingPropertySource source = new DelegatingPropertySource();
@@ -616,13 +616,13 @@
 
         // Then search the rest of the standard path
         source.addSource(cycle.getEngine().getPropertySource());
-        
+
         return source;
     }
-    
+
     private String getTemplateEncodingProperty(IPropertySource source)
     {
         return source.getPropertyValue(TEMPLATE_ENCODING_PROPERTY_NAME);
     }
-    
+
 }

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/Namespace.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/Namespace.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/Namespace.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/engine/Namespace.java Wed Jun 25 14:14:11 2008
@@ -14,23 +14,14 @@
 
 package org.apache.tapestry.engine;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.tapestry.ApplicationRuntimeException;
-import org.apache.tapestry.ILocation;
-import org.apache.tapestry.INamespace;
-import org.apache.tapestry.IResourceLocation;
-import org.apache.tapestry.Tapestry;
+import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
+import org.apache.tapestry.*;
 import org.apache.tapestry.resource.ClasspathResourceLocation;
 import org.apache.tapestry.spec.IComponentSpecification;
 import org.apache.tapestry.spec.ILibrarySpecification;
 
+import java.util.*;
+
 /**
  *  Implementation of {@link org.apache.tapestry.INamespace}
  *  that works with a {@link ISpecificationSource} to
@@ -60,7 +51,7 @@
      * 
      **/
 
-    private Map _pages = Collections.synchronizedMap(new HashMap());
+    private Map _pages = new ConcurrentHashMap();
 
     /**
      *  Map of {@link org.apache.tapestry.spec.ComponentSpecification} keyed on
@@ -68,14 +59,14 @@
      * 
      **/
 
-    private Map _components = Collections.synchronizedMap(new HashMap());
+    private Map _components = new ConcurrentHashMap();
 
     /**
      *  Map, keyed on id, of {@link INamespace}.
      * 
      **/
 
-    private Map _children = Collections.synchronizedMap(new HashMap());
+    private Map _children = new ConcurrentHashMap();
 
     public Namespace(
         String id,

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/DefaultComponentClassEnhancer.java Wed Jun 25 14:14:11 2008
@@ -14,14 +14,7 @@
 
 package org.apache.tapestry.enhance;
 
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
+import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.tapestry.ApplicationRuntimeException;
@@ -31,6 +24,12 @@
 import org.apache.tapestry.enhance.javassist.EnhancedClassFactory;
 import org.apache.tapestry.spec.IComponentSpecification;
 
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
 /**
  *  Default implementation of {@link IComponentClassEnhancer}.
  *
@@ -61,7 +60,7 @@
      */
     public DefaultComponentClassEnhancer(IResourceResolver resolver, boolean disableValidation)
     {
-        _cachedClasses = Collections.synchronizedMap(new HashMap());
+        _cachedClasses = new ConcurrentHashMap();
         _resolver = resolver;
         _factory = createEnhancedClassFactory();
         _disableValidation = disableValidation;

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClassFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClassFactory.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClassFactory.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/enhance/javassist/EnhancedClassFactory.java Wed Jun 25 14:14:11 2008
@@ -18,7 +18,6 @@
 import javassist.CtClass;
 import javassist.LoaderClassPath;
 import javassist.NotFoundException;
-
 import org.apache.tapestry.IResourceResolver;
 import org.apache.tapestry.enhance.CodeGenerationException;
 import org.apache.tapestry.enhance.EnhancedClassLoader;
@@ -29,7 +28,7 @@
  *  This class defines the factory for creation of new Javassist enhanced classes. 
  *  There is typically only one object of this class in the system. 
  *  Common functionality objects for Javassist enhancement are stored here.
- * 
+ *
  *  @author Mindbridge
  *  @version $Id$
  *  @since 3.0
@@ -48,18 +47,18 @@
 
         reset();
     }
-    
+
     protected ClassPool createClassPool()
     {
         ClassLoader loader = _resourceResolver.getClassLoader();
-        
+
         // create a new ClassPool and make sure it uses the application resource resolver 
         ClassPool classPool = new ClassPool(null);
         classPool.insertClassPath(new LoaderClassPath(loader));
-        
+
         return classPool;
     }
-    
+
     /**
      * @see org.apache.tapestry.enhance.IEnhancedClassFactory#reset()
      */
@@ -72,7 +71,7 @@
         ClassLoader loader = _resourceResolver.getClassLoader();
         _enhancedClassLoader = new EnhancedClassLoader(loader);
     }
-   
+
 
     /**
      * @see org.apache.tapestry.enhance.IEnhancedClassFactory#createEnhancedClass(java.lang.String, java.lang.Class)
@@ -96,29 +95,29 @@
      *  Given the java class, returns the equivalent {@link CtClass type}.  In addition,
      *  knows about scalar types, arrays of scalar types, java.lang.Object[] and
      *  java.lang.String[].
-     * 
+     *
      **/
 
     public CtClass getObjectType(String type)
     {
 
-            synchronized (this) {
-                CtClass result = getClassMapping().getType(type);
+        synchronized (this) {
+            CtClass result = getClassMapping().getType(type);
 
-                if (result == null)
+            if (result == null)
+            {
+                try
+                {
+                    result = _classPool.get(type);
+                    getClassMapping().recordType(type, result);
+                }
+                catch (NotFoundException e)
                 {
-                    try
-                    {
-                        result = _classPool.get(type);
-                        getClassMapping().recordType(type, result);
-                    }
-                    catch (NotFoundException e)
-                    {
-                        throw new CodeGenerationException(e);
-                    }
+                    throw new CodeGenerationException(e);
                 }
-                return result;
             }
+            return result;
+        }
 
     }
 

Modified: tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/pageload/PageSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/pageload/PageSource.java?rev=671663&r1=671662&r2=671663&view=diff
==============================================================================
--- tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/pageload/PageSource.java (original)
+++ tapestry/tapestry3/trunk/tapestry-framework/src/org/apache/tapestry/pageload/PageSource.java Wed Jun 25 14:14:11 2008
@@ -15,11 +15,7 @@
 package org.apache.tapestry.pageload;
 
 import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.tapestry.IEngine;
-import org.apache.tapestry.IPage;
-import org.apache.tapestry.IRequestCycle;
-import org.apache.tapestry.IResourceResolver;
-import org.apache.tapestry.Tapestry;
+import org.apache.tapestry.*;
 import org.apache.tapestry.engine.IMonitor;
 import org.apache.tapestry.engine.IPageSource;
 import org.apache.tapestry.resolver.PageSpecificationResolver;
@@ -138,8 +134,7 @@
             // Resolvers are not threadsafe, so we get one from
             // the pool or create as needed.
 
-            PageSpecificationResolver pageSpecificationResolver =
-                getPageSpecificationResolver(cycle);
+            PageSpecificationResolver pageSpecificationResolver = getPageSpecificationResolver(cycle);
 
             pageSpecificationResolver.resolve(cycle, pageName);