You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2011/10/20 02:32:29 UTC

svn commit: r1186581 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry5/ tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ tapestry-core/src/main/java/org/apache/tapestry5/services/ tapestry-core/src/test...

Author: hlship
Date: Thu Oct 20 00:32:28 2011
New Revision: 1186581

URL: http://svn.apache.org/viewvc?rev=1186581&view=rev
Log:
TAP5-1710: AssetSource service can retain large numbers of Asset and Resource objects

Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/CollectionFactory.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java?rev=1186581&r1=1186580&r2=1186581&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java Thu Oct 20 00:32:28 2011
@@ -25,6 +25,8 @@ import org.apache.tapestry5.ioc.Resource
  * <p/>
  * Release 5.1.0.0 introduced {@link org.apache.tapestry5.Asset2}, which extends this interface with an additional
  * method.
+ *
+ * @see org.apache.tapestry5.services.AssetPathConverter
  */
 public interface Asset
 {
@@ -34,7 +36,7 @@ public interface Asset
      * <p/>
      * Tapestry's built-in asset types (context and classpath) always incorporate a version number as part of the path,
      * and alternate implementations are encouraged to do so as well. In addition, Tapestry ensures that context and
-     * classpath assets have a far-future expires header (to ensure aggresive caching by the client).
+     * classpath assets have a far-future expires header (to ensure aggressive caching by the client).
      * <p/>
      */
     String toClientURL();

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java?rev=1186581&r1=1186580&r2=1186581&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java Thu Oct 20 00:32:28 2011
@@ -14,11 +14,9 @@
 
 package org.apache.tapestry5.internal.services;
 
-import java.util.Locale;
-import java.util.Map;
-
 import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.internal.AssetConstants;
+import org.apache.tapestry5.internal.TapestryInternalUtils;
 import org.apache.tapestry5.ioc.Resource;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
@@ -28,6 +26,10 @@ import org.apache.tapestry5.ioc.util.Str
 import org.apache.tapestry5.services.AssetFactory;
 import org.apache.tapestry5.services.AssetSource;
 
+import java.lang.ref.SoftReference;
+import java.util.Locale;
+import java.util.Map;
+
 @SuppressWarnings("all")
 public class AssetSourceImpl implements AssetSource
 {
@@ -37,13 +39,13 @@ public class AssetSourceImpl implements 
 
     private final Map<String, Resource> prefixToRootResource = CollectionFactory.newMap();
 
-    private final Map<Resource, Asset> cache = CollectionFactory.newConcurrentMap();
+    private final Map<Resource, SoftReference<Asset>> cache = CollectionFactory.newWeakHashMap();
 
     private final SymbolSource symbolSource;
 
     public AssetSourceImpl(ThreadLocale threadLocale,
 
-    Map<String, AssetFactory> configuration, SymbolSource symbolSource)
+                           Map<String, AssetFactory> configuration, SymbolSource symbolSource)
     {
         this.threadLocale = threadLocale;
         this.symbolSource = symbolSource;
@@ -137,14 +139,14 @@ public class AssetSourceImpl implements 
         return getAssetForResource(localized);
     }
 
-    private Asset getAssetForResource(Resource resource)
+    private synchronized Asset getAssetForResource(Resource resource)
     {
-        Asset result = cache.get(resource);
+        Asset result = TapestryInternalUtils.getAndDeref(cache, resource);
 
         if (result == null)
         {
             result = createAssetFromResource(resource);
-            cache.put(resource, result);
+            cache.put(resource, new SoftReference(result));
         }
 
         return result;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java?rev=1186581&r1=1186580&r2=1186581&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java Thu Oct 20 00:32:28 2011
@@ -16,14 +16,12 @@ package org.apache.tapestry5.internal.se
 
 import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.annotations.Marker;
 import org.apache.tapestry5.ioc.internal.util.ClasspathResource;
-import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.services.AssetFactory;
 import org.apache.tapestry5.services.AssetPathConverter;
 import org.apache.tapestry5.services.ClasspathAssetAliasManager;
-import org.apache.tapestry5.services.InvalidationListener;
-
-import java.util.Map;
+import org.apache.tapestry5.services.ClasspathProvider;
 
 /**
  * Generates Assets for files on the classpath. Caches generated client URLs internally, and clears that cache when
@@ -31,14 +29,13 @@ import java.util.Map;
  *
  * @see AssetDispatcher
  */
-public class ClasspathAssetFactory implements AssetFactory, InvalidationListener
+@Marker(ClasspathProvider.class)
+public class ClasspathAssetFactory implements AssetFactory
 {
     private final ResourceDigestManager digestManager;
 
     private final ClasspathAssetAliasManager aliasManager;
 
-    private final Map<Resource, String> resourceToDefaultPath = CollectionFactory.newConcurrentMap();
-
     private final ClasspathResource rootResource;
 
     private final AssetPathConverter converter;
@@ -57,21 +54,9 @@ public class ClasspathAssetFactory imple
         invariant = converter.isInvariant();
     }
 
-    public void objectWasInvalidated()
-    {
-        resourceToDefaultPath.clear();
-    }
-
     private String clientURL(Resource resource)
     {
-        String defaultPath = resourceToDefaultPath.get(resource);
-
-        if (defaultPath == null)
-        {
-            defaultPath = buildDefaultPath(resource);
-
-            resourceToDefaultPath.put(resource, defaultPath);
-        }
+        String defaultPath = buildDefaultPath(resource);
 
         return converter.convertAssetPath(defaultPath);
     }
@@ -94,9 +79,22 @@ public class ClasspathAssetFactory imple
         return aliasManager.toClientURL(path);
     }
 
-    public Asset createAsset(final Resource resource)
+    public Asset createAsset(Resource resource)
+    {
+        if (invariant)
+        {
+            return createInvariantAsset(resource);
+        }
+
+        return createVariantAsset(resource);
+    }
+
+    /**
+     * A variant asset must pass the resource through clientURL() all the time; very inefficient.
+     */
+    private Asset createVariantAsset(final Resource resource)
     {
-        return new AbstractAsset(invariant)
+        return new AbstractAsset(false)
         {
             public Resource getResource()
             {
@@ -110,6 +108,32 @@ public class ClasspathAssetFactory imple
         };
     }
 
+    /**
+     * An invariant asset is normal, and only needs to compute the clientURL for the resource once.
+     */
+    private Asset createInvariantAsset(final Resource resource)
+    {
+        return new AbstractAsset(true)
+        {
+            private String clientURL;
+
+            public Resource getResource()
+            {
+                return resource;
+            }
+
+            public synchronized String toClientURL()
+            {
+                if (clientURL == null)
+                {
+                    clientURL = clientURL(resource);
+                }
+
+                return clientURL;
+            }
+        };
+    }
+
     public Resource getRootResource()
     {
         return rootResource;

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java?rev=1186581&r1=1186580&r2=1186581&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java Thu Oct 20 00:32:28 2011
@@ -23,7 +23,7 @@ import org.apache.tapestry5.services.ass
 
 /**
  * Implementation of {@link AssetFactory} for assets that are part of the web application context.
- * 
+ *
  * @see org.apache.tapestry5.internal.services.ContextResource
  */
 public class ContextAssetFactory implements AssetFactory
@@ -38,7 +38,7 @@ public class ContextAssetFactory impleme
 
     public ContextAssetFactory(AssetPathConstructor assetPathConstructor, Context context,
 
-    AssetPathConverter converter)
+                               AssetPathConverter converter)
     {
         this.assetPathConstructor = assetPathConstructor;
         this.converter = converter;
@@ -47,12 +47,44 @@ public class ContextAssetFactory impleme
         invariant = this.converter.isInvariant();
     }
 
-    public Asset createAsset(final Resource resource)
+    public Asset createAsset(Resource resource)
     {
-        final String defaultPath = assetPathConstructor.constructAssetPath(RequestConstants.CONTEXT_FOLDER, resource
-                .getPath());
+        String defaultPath = assetPathConstructor.constructAssetPath(RequestConstants.CONTEXT_FOLDER, resource.getPath());
 
-        return new AbstractAsset(invariant)
+        if (invariant)
+        {
+            return createInvariantAsset(resource, defaultPath);
+        }
+
+        return createVariantAsset(resource, defaultPath);
+    }
+
+    private Asset createInvariantAsset(final Resource resource, final String defaultPath)
+    {
+        return new AbstractAsset(true)
+        {
+            private String clientURL;
+
+            public Resource getResource()
+            {
+                return resource;
+            }
+
+            public synchronized String toClientURL()
+            {
+                if (clientURL == null)
+                {
+                    clientURL = converter.convertAssetPath(defaultPath);
+                }
+
+                return clientURL;
+            }
+        };
+    }
+
+    private Asset createVariantAsset(final Resource resource, final String defaultPath)
+    {
+        return new AbstractAsset(false)
         {
             public Resource getResource()
             {

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java?rev=1186581&r1=1186580&r2=1186581&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java Thu Oct 20 00:32:28 2011
@@ -371,6 +371,7 @@ public final class TapestryModule
         binder.bind(ValidationDecoratorFactory.class, ValidationDecoratorFactoryImpl.class);
         binder.bind(PropertyConduitSource.class, PropertyConduitSourceImpl.class);
         binder.bind(ClientWhitelist.class, ClientWhitelistImpl.class);
+        binder.bind(AssetFactory.class, ClasspathAssetFactory.class).withSimpleId();
     }
 
     // ========================================================================
@@ -1214,17 +1215,6 @@ public final class TapestryModule
         return service;
     }
 
-    @Marker(ClasspathProvider.class)
-    public AssetFactory buildClasspathAssetFactory(ResourceDigestManager resourceDigestManager,
-                                                   ClasspathAssetAliasManager aliasManager, AssetPathConverter converter)
-    {
-        ClasspathAssetFactory factory = new ClasspathAssetFactory(resourceDigestManager, aliasManager, converter);
-
-        resourceDigestManager.addInvalidationListener(factory);
-
-        return factory;
-    }
-
     @Marker(ContextProvider.class)
     public AssetFactory buildContextAssetFactory(ApplicationGlobals globals,
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java?rev=1186581&r1=1186580&r2=1186581&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetFactoryTest.java Thu Oct 20 00:32:28 2011
@@ -54,19 +54,6 @@ public class ClasspathAssetFactoryTest e
         assertEquals(asset.toClientURL(), expectedClientURL);
 
         verify();
-
-        // Now, to test cache clearing:
-        train_requiresDigest(digestManager, r, false);
-
-        train_toClientURL(aliasManager, "foo/Bar.txt", expectedClientURL);
-
-        replay();
-
-        factory.objectWasInvalidated();
-
-        assertEquals(asset.toClientURL(), expectedClientURL);
-
-        verify();
     }
 
     @Test

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/CollectionFactory.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/CollectionFactory.java?rev=1186581&r1=1186580&r2=1186581&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/CollectionFactory.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/util/CollectionFactory.java Thu Oct 20 00:32:28 2011
@@ -86,6 +86,14 @@ public final class CollectionFactory
     }
 
     /**
+     * @since 5.3
+     */
+    public static <K, V> Map<K, V> newWeakHashMap()
+    {
+        return new WeakHashMap<K, V>();
+    }
+
+    /**
      * Contructs and returns a new generic {@link java.util.ArrayList} instance.
      */
     public static <T> List<T> newList()