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/11 23:47:23 UTC

svn commit: r1182107 - in /tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5: internal/event/ internal/services/ internal/services/assets/ services/assets/

Author: hlship
Date: Tue Oct 11 21:47:22 2011
New Revision: 1182107

URL: http://svn.apache.org/viewvc?rev=1182107&view=rev
Log:
Refactor the StreamableResourceSource pipeline to support tracking the dependencies of a Resource (to support "import" or "include" operations inside a ResourceTranslator)

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceDependencies.java
      - copied, changed from r1182106, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/event/InvalidationEventHubImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTracker.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTrackerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCachingInterceptor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCompressingInterceptor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSMinimizingInterceptor.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StreamableResourceSourceImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/event/InvalidationEventHubImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/event/InvalidationEventHubImpl.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/event/InvalidationEventHubImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/event/InvalidationEventHubImpl.java Tue Oct 11 21:47:22 2011
@@ -14,12 +14,12 @@
 
 package org.apache.tapestry5.internal.event;
 
-import java.util.List;
-
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.services.InvalidationEventHub;
 import org.apache.tapestry5.services.InvalidationListener;
 
+import java.util.List;
+
 /**
  * Base implementation class for classes (especially services) that need to manage a list of
  * {@link org.apache.tapestry5.services.InvalidationListener}s.
@@ -33,8 +33,7 @@ public class InvalidationEventHubImpl im
         if (productionMode)
         {
             listeners = null;
-        }
-        else
+        } else
         {
             listeners = CollectionFactory.newThreadSafeList();
         }
@@ -46,7 +45,9 @@ public class InvalidationEventHubImpl im
     protected final void fireInvalidationEvent()
     {
         if (listeners == null)
+        {
             return;
+        }
 
         for (InvalidationListener listener : listeners)
         {
@@ -56,9 +57,9 @@ public class InvalidationEventHubImpl im
 
     public final void addInvalidationListener(InvalidationListener listener)
     {
-        if (listeners == null)
-            return;
-
-        listeners.add(listener);
+        if (listeners != null)
+        {
+            listeners.add(listener);
+        }
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ResourceStreamerImpl.java Tue Oct 11 21:47:22 2011
@@ -14,15 +14,11 @@
 
 package org.apache.tapestry5.internal.services;
 
-import java.io.IOException;
-import java.io.OutputStream;
-
-import javax.servlet.http.HttpServletResponse;
-
 import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.internal.IOOperation;
 import org.apache.tapestry5.internal.InternalConstants;
 import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
 import org.apache.tapestry5.ioc.OperationTracker;
 import org.apache.tapestry5.ioc.Resource;
 import org.apache.tapestry5.ioc.annotations.Symbol;
@@ -34,6 +30,10 @@ import org.apache.tapestry5.services.ass
 import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
 import org.apache.tapestry5.services.assets.StreamableResourceSource;
 
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+
 public class ResourceStreamerImpl implements ResourceStreamer
 {
     static final String IF_MODIFIED_SINCE_HEADER = "If-Modified-Since";
@@ -50,18 +50,20 @@ public class ResourceStreamerImpl implem
 
     private final OperationTracker tracker;
 
+    private final ResourceChangeTracker resourceChangeTracker;
+
     public ResourceStreamerImpl(Request request,
 
-    Response response,
+                                Response response,
 
-    StreamableResourceSource streamableResourceSource,
+                                StreamableResourceSource streamableResourceSource,
 
-    ResponseCompressionAnalyzer analyzer,
+                                ResponseCompressionAnalyzer analyzer,
 
-    OperationTracker tracker,
+                                OperationTracker tracker,
 
-    @Symbol(SymbolConstants.PRODUCTION_MODE)
-    boolean productionMode)
+                                @Symbol(SymbolConstants.PRODUCTION_MODE)
+                                boolean productionMode, ResourceChangeTracker resourceChangeTracker)
     {
         this.request = request;
         this.response = response;
@@ -70,6 +72,7 @@ public class ResourceStreamerImpl implem
         this.analyzer = analyzer;
         this.tracker = tracker;
         this.productionMode = productionMode;
+        this.resourceChangeTracker = resourceChangeTracker;
     }
 
     public void streamResource(final Resource resource) throws IOException
@@ -87,7 +90,7 @@ public class ResourceStreamerImpl implem
                 StreamableResourceProcessing processing = analyzer.isGZipSupported() ? StreamableResourceProcessing.COMPRESSION_ENABLED
                         : StreamableResourceProcessing.COMPRESSION_DISABLED;
 
-                StreamableResource streamable = streamableResourceSource.getStreamableResource(resource, processing);
+                StreamableResource streamable = streamableResourceSource.getStreamableResource(resource, processing, resourceChangeTracker);
 
                 streamResource(streamable);
             }
@@ -103,8 +106,7 @@ public class ResourceStreamerImpl implem
         try
         {
             ifModifiedSince = request.getDateHeader(IF_MODIFIED_SINCE_HEADER);
-        }
-        catch (IllegalArgumentException ex)
+        } catch (IllegalArgumentException ex)
         {
             // Simulate the header being missing if it is poorly formatted.
 
@@ -127,12 +129,16 @@ public class ResourceStreamerImpl implem
         response.setDateHeader("Last-Modified", lastModified);
 
         if (productionMode)
+        {
             response.setDateHeader("Expires", lastModified + InternalConstants.TEN_YEARS);
+        }
 
         response.setContentLength(streamable.getSize());
 
         if (streamable.getCompression() == CompressionStatus.COMPRESSED)
+        {
             response.setHeader(InternalConstants.CONTENT_ENCODING_HEADER, InternalConstants.GZIP_CONTENT_ENCODING);
+        }
 
         OutputStream os = response.getOutputStream(streamable.getContentType());
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTracker.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTracker.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTracker.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTracker.java Tue Oct 11 21:47:22 2011
@@ -19,25 +19,25 @@ import org.apache.tapestry5.ioc.internal
 import org.apache.tapestry5.services.InvalidationEventHub;
 import org.apache.tapestry5.services.InvalidationListener;
 import org.apache.tapestry5.services.UpdateListener;
+import org.apache.tapestry5.services.assets.ResourceDependencies;
 
 /**
  * Tracks resources (at least, resources that can change because they are on the file system) and
  * acts as an {@link UpdateListener} to check for changes and notify its listeners.
- * 
+ *
  * @since 5.3
  */
-public interface ResourceChangeTracker extends InvalidationEventHub
+public interface ResourceChangeTracker extends InvalidationEventHub, ResourceDependencies
 {
     /**
      * Start tracking the resource (or return the last modified time of an already tracked resource). Only file system
      * resources are tracked. Resources are tracked until <em>any</em> resource changes, at which points
      * {@linkplain InvalidationListener listeners} are notified and the internal state
      * is cleared.
-     * 
-     * @see URLChangeTracker
-     * @param resource
-     *            to track
+     *
+     * @param resource to track
      * @return last modified time, to nearest second
+     * @see URLChangeTracker
      */
     long trackResource(Resource resource);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTrackerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTrackerImpl.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTrackerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ResourceChangeTrackerImpl.java Tue Oct 11 21:47:22 2011
@@ -30,15 +30,15 @@ public class ResourceChangeTrackerImpl e
     private final URLChangeTracker tracker;
 
     public ResourceChangeTrackerImpl(ClasspathURLConverter classpathURLConverter,
-            @Symbol(SymbolConstants.PRODUCTION_MODE)
-            boolean productionMode)
+                                     @Symbol(SymbolConstants.PRODUCTION_MODE)
+                                     boolean productionMode)
     {
         super(productionMode);
-        
+
         // Use granularity of seconds (not milliseconds) since that works properly
         // with response headers for identifying last modified. Don't track
         // folder changes, just changes to actual files.
-        tracker = new URLChangeTracker(classpathURLConverter, true, false);
+        tracker = productionMode ? null : new URLChangeTracker(classpathURLConverter, true, false);
     }
 
     @PostInjection
@@ -49,9 +49,19 @@ public class ResourceChangeTrackerImpl e
 
     public long trackResource(Resource resource)
     {
+        if (tracker == null)
+        {
+            return 0;
+        }
+
         return tracker.add(resource.toURL());
     }
 
+    public void addDependency(Resource dependency)
+    {
+        trackResource(dependency);
+    }
+
     public void checkForUpdates()
     {
         if (tracker.containsChanges())

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCachingInterceptor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCachingInterceptor.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCachingInterceptor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCachingInterceptor.java Tue Oct 11 21:47:22 2011
@@ -17,6 +17,7 @@ package org.apache.tapestry5.internal.se
 import org.apache.tapestry5.ioc.Resource;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.services.InvalidationListener;
+import org.apache.tapestry5.services.assets.ResourceDependencies;
 import org.apache.tapestry5.services.assets.StreamableResource;
 import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
 import org.apache.tapestry5.services.assets.StreamableResourceSource;
@@ -42,12 +43,12 @@ public class SRSCachingInterceptor imple
         this.delegate = delegate;
     }
 
-    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing)
+    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing, ResourceDependencies dependencies)
             throws IOException
     {
         if (processing == StreamableResourceProcessing.FOR_AGGREGATION)
         {
-            return delegate.getStreamableResource(baseResource, processing);
+            return delegate.getStreamableResource(baseResource, processing, dependencies);
         }
 
         SoftReference<StreamableResource> ref = cache.get(baseResource);
@@ -56,11 +57,11 @@ public class SRSCachingInterceptor imple
 
         if (result == null)
         {
-            result = delegate.getStreamableResource(baseResource, processing);
+            result = delegate.getStreamableResource(baseResource, processing, dependencies);
 
             if (isCacheable(result))
             {
-                tracker.trackResource(baseResource);
+                dependencies.addDependency(baseResource);
 
                 cache.put(baseResource, new SoftReference<StreamableResource>(result));
             }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCompressingInterceptor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCompressingInterceptor.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCompressingInterceptor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSCompressingInterceptor.java Tue Oct 11 21:47:22 2011
@@ -14,17 +14,14 @@
 
 package org.apache.tapestry5.internal.services.assets;
 
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.services.assets.*;
+
 import java.io.BufferedOutputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.zip.GZIPOutputStream;
 
-import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.services.assets.CompressionStatus;
-import org.apache.tapestry5.services.assets.StreamableResource;
-import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
-import org.apache.tapestry5.services.assets.StreamableResourceSource;
-
 public class SRSCompressingInterceptor implements StreamableResourceSource
 {
     private final int compressionCutoff;
@@ -37,20 +34,20 @@ public class SRSCompressingInterceptor i
         this.delegate = delegate;
     }
 
-    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing)
+    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing, ResourceDependencies dependencies)
             throws IOException
     {
-        StreamableResource streamable = delegate.getStreamableResource(baseResource, processing);
-
-        if (processing == StreamableResourceProcessing.COMPRESSION_ENABLED) { return compress(streamable); }
+        StreamableResource streamable = delegate.getStreamableResource(baseResource, processing, dependencies);
 
-        return streamable;
+        return processing == StreamableResourceProcessing.COMPRESSION_ENABLED ? compress(streamable) : streamable;
     }
 
     private StreamableResource compress(StreamableResource uncompressed) throws IOException
     {
         if (uncompressed.getCompression() != CompressionStatus.COMPRESSABLE)
+        {
             return uncompressed;
+        }
 
         int size = uncompressed.getSize();
 
@@ -58,7 +55,9 @@ public class SRSCompressingInterceptor i
         // we don't even try.
 
         if (size < compressionCutoff)
+        {
             return uncompressed;
+        }
 
         ByteArrayOutputStream bos = new ByteArrayOutputStream(size);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSMinimizingInterceptor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSMinimizingInterceptor.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSMinimizingInterceptor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/SRSMinimizingInterceptor.java Tue Oct 11 21:47:22 2011
@@ -14,13 +14,10 @@
 
 package org.apache.tapestry5.internal.services.assets;
 
-import java.io.IOException;
-
 import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.services.assets.ResourceMinimizer;
-import org.apache.tapestry5.services.assets.StreamableResource;
-import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
-import org.apache.tapestry5.services.assets.StreamableResourceSource;
+import org.apache.tapestry5.services.assets.*;
+
+import java.io.IOException;
 
 /**
  * Loops the result through the {@link ResourceMinimizer} service.
@@ -37,13 +34,15 @@ public class SRSMinimizingInterceptor im
         this.minimizer = minimizer;
     }
 
-    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing)
+    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing, ResourceDependencies dependencies)
             throws IOException
     {
-        StreamableResource streamable = delegate.getStreamableResource(baseResource, processing);
+        StreamableResource streamable = delegate.getStreamableResource(baseResource, processing, dependencies);
 
         if (processing != StreamableResourceProcessing.FOR_AGGREGATION)
+        {
             return minimizer.minimize(streamable);
+        }
 
         return streamable;
     }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StackAssetRequestHandler.java Tue Oct 11 21:47:22 2011
@@ -14,18 +14,6 @@
 
 package org.apache.tapestry5.internal.services.assets;
 
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.zip.GZIPOutputStream;
-
 import org.apache.tapestry5.Asset;
 import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.internal.IOOperation;
@@ -37,20 +25,18 @@ import org.apache.tapestry5.ioc.annotati
 import org.apache.tapestry5.ioc.annotations.Symbol;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.json.JSONArray;
-import org.apache.tapestry5.services.InvalidationListener;
-import org.apache.tapestry5.services.LocalizationSetter;
-import org.apache.tapestry5.services.Request;
-import org.apache.tapestry5.services.Response;
-import org.apache.tapestry5.services.ResponseCompressionAnalyzer;
-import org.apache.tapestry5.services.assets.AssetRequestHandler;
-import org.apache.tapestry5.services.assets.CompressionStatus;
-import org.apache.tapestry5.services.assets.ResourceMinimizer;
-import org.apache.tapestry5.services.assets.StreamableResource;
-import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
-import org.apache.tapestry5.services.assets.StreamableResourceSource;
+import org.apache.tapestry5.services.*;
+import org.apache.tapestry5.services.assets.*;
 import org.apache.tapestry5.services.javascript.JavaScriptStack;
 import org.apache.tapestry5.services.javascript.JavaScriptStackSource;
 
+import java.io.*;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.GZIPOutputStream;
+
 public class StackAssetRequestHandler implements AssetRequestHandler, InvalidationListener
 {
     private static final String JAVASCRIPT_CONTENT_TYPE = "text/javascript";
@@ -78,13 +64,15 @@ public class StackAssetRequestHandler im
 
     private final boolean minificationEnabled;
 
+    private final ResourceChangeTracker resourceChangeTracker;
+
     public StackAssetRequestHandler(StreamableResourceSource streamableResourceSource,
-            JavaScriptStackSource javascriptStackSource, LocalizationSetter localizationSetter,
-            ResponseCompressionAnalyzer compressionAnalyzer, ResourceStreamer resourceStreamer,
-            ResourceMinimizer resourceMinimizer, OperationTracker tracker,
+                                    JavaScriptStackSource javascriptStackSource, LocalizationSetter localizationSetter,
+                                    ResponseCompressionAnalyzer compressionAnalyzer, ResourceStreamer resourceStreamer,
+                                    ResourceMinimizer resourceMinimizer, OperationTracker tracker,
 
-            @Symbol(SymbolConstants.MINIFICATION_ENABLED)
-            boolean minificationEnabled)
+                                    @Symbol(SymbolConstants.MINIFICATION_ENABLED)
+                                    boolean minificationEnabled, ResourceChangeTracker resourceChangeTracker)
     {
         this.streamableResourceSource = streamableResourceSource;
         this.javascriptStackSource = javascriptStackSource;
@@ -94,6 +82,7 @@ public class StackAssetRequestHandler im
         this.resourceMinimizer = resourceMinimizer;
         this.tracker = tracker;
         this.minificationEnabled = minificationEnabled;
+        this.resourceChangeTracker = resourceChangeTracker;
     }
 
     @PostInjection
@@ -120,7 +109,9 @@ public class StackAssetRequestHandler im
         return true;
     }
 
-    /** Notified by the {@link ResourceChangeTracker} when (any) resource files change; the internal caches are cleared. */
+    /**
+     * Notified by the {@link ResourceChangeTracker} when (any) resource files change; the internal caches are cleared.
+     */
     public synchronized void objectWasInvalidated()
     {
         uncompressedCache.clear();
@@ -204,7 +195,7 @@ public class StackAssetRequestHandler im
             Resource resource = library.getResource();
 
             StreamableResource streamable = streamableResourceSource.getStreamableResource(resource,
-                    StreamableResourceProcessing.FOR_AGGREGATION);
+                    StreamableResourceProcessing.FOR_AGGREGATION, resourceChangeTracker);
 
             streamable.streamTo(stream);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StreamableResourceSourceImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StreamableResourceSourceImpl.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StreamableResourceSourceImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/StreamableResourceSourceImpl.java Tue Oct 11 21:47:22 2011
@@ -14,23 +14,15 @@
 
 package org.apache.tapestry5.internal.services.assets;
 
-import java.io.BufferedInputStream;
+import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.services.assets.*;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URL;
 import java.util.Map;
 
-import org.apache.tapestry5.internal.TapestryInternalUtils;
-import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.services.assets.CompressionAnalyzer;
-import org.apache.tapestry5.services.assets.CompressionStatus;
-import org.apache.tapestry5.services.assets.ContentTypeAnalyzer;
-import org.apache.tapestry5.services.assets.ResourceTransformer;
-import org.apache.tapestry5.services.assets.StreamableResource;
-import org.apache.tapestry5.services.assets.StreamableResourceProcessing;
-import org.apache.tapestry5.services.assets.StreamableResourceSource;
-
 public class StreamableResourceSourceImpl implements StreamableResourceSource
 {
     private final Map<String, ResourceTransformer> configuration;
@@ -42,8 +34,8 @@ public class StreamableResourceSourceImp
     private final ResourceChangeTracker resourceChangeTracker;
 
     public StreamableResourceSourceImpl(Map<String, ResourceTransformer> configuration,
-            ContentTypeAnalyzer contentTypeAnalyzer, CompressionAnalyzer compressionAnalyzer,
-            ResourceChangeTracker resourceChangeTracker)
+                                        ContentTypeAnalyzer contentTypeAnalyzer, CompressionAnalyzer compressionAnalyzer,
+                                        ResourceChangeTracker resourceChangeTracker)
     {
         this.configuration = configuration;
         this.contentTypeAnalyzer = contentTypeAnalyzer;
@@ -51,15 +43,15 @@ public class StreamableResourceSourceImp
         this.resourceChangeTracker = resourceChangeTracker;
     }
 
-    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing)
+    public StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing, ResourceDependencies dependencies)
             throws IOException
     {
         assert baseResource != null;
 
-        URL url = baseResource.toURL();
-
-        if (url == null)
+        if (!baseResource.exists())
+        {
             throw new IOException(String.format("Resource %s does not exist.", baseResource));
+        }
 
         String fileSuffix = TapestryInternalUtils.toFileSuffix(baseResource.getFile());
 
@@ -68,14 +60,13 @@ public class StreamableResourceSourceImp
         // http://jashkenas.github.com/coffee-script/
         ResourceTransformer rt = configuration.get(fileSuffix);
 
-        InputStream buffered = new BufferedInputStream(url.openStream());
+        InputStream transformed = rt == null ? baseResource.openStream() : rt.transform(baseResource, dependencies);
 
-        InputStream transformed = rt == null ? buffered : rt.transform(buffered);
+        assert transformed != null;
 
         BytestreamCache bytestreamCache = readStream(transformed);
 
         transformed.close();
-        buffered.close();
 
         String contentType = contentTypeAnalyzer.getContentType(baseResource);
 

Copied: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceDependencies.java (from r1182106, tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java)
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceDependencies.java?p2=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceDependencies.java&p1=tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java&r1=1182106&r2=1182107&rev=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceDependencies.java Tue Oct 11 21:47:22 2011
@@ -14,25 +14,22 @@
 
 package org.apache.tapestry5.services.assets;
 
-import java.io.IOException;
-import java.io.InputStream;
+import org.apache.tapestry5.ioc.Resource;
 
 /**
- * A transformer is used to read a resource and pass it through a transformation stage, to get a
- * stream that can be used on the client side. Examples of this are languages that "compile" to
- * JavaScript, or any of a few higher-level versions of CSS that are compiled to standard CSS.
- * 
+ * Used by some {@link ResourceTransformer} implementations to track additional dependencies that can arise
+ * when the underlying resource being transformed can be dependent on other resources (for instance, if it has the
+ * notion of "including" or "importing" content).
+ *
  * @since 5.3
  */
-public interface ResourceTransformer
+public interface ResourceDependencies
 {
     /**
-     * Read the source input stream and provide a new input stream of the transformed content.
-     * 
-     * @param source
-     *            input content
-     * @return stream of output content
-     * @throws IOException
+     * Marks the dependency as an additional resource. A change to the dependency is considered the same as a change to
+     * the resource being transformed.
+     *
+     * @param dependency
      */
-    InputStream transform(InputStream source) throws IOException;
+    void addDependency(Resource dependency);
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/ResourceTransformer.java Tue Oct 11 21:47:22 2011
@@ -14,25 +14,27 @@
 
 package org.apache.tapestry5.services.assets;
 
+import org.apache.tapestry5.ioc.Resource;
+
 import java.io.IOException;
 import java.io.InputStream;
 
 /**
- * A transformer is used to read a resource and pass it through a transformation stage, to get a
+ * A transformer is used to read a {@link Resource} and pass it through a transformation stage, to get a
  * stream that can be used on the client side. Examples of this are languages that "compile" to
  * JavaScript, or any of a few higher-level versions of CSS that are compiled to standard CSS.
- * 
+ *
  * @since 5.3
  */
 public interface ResourceTransformer
 {
     /**
      * Read the source input stream and provide a new input stream of the transformed content.
-     * 
-     * @param source
-     *            input content
+     *
+     * @param source       input content
+     * @param dependencies allows additional dependencies of the source to be tracked
      * @return stream of output content
      * @throws IOException
      */
-    InputStream transform(InputStream source) throws IOException;
+    InputStream transform(Resource source, ResourceDependencies dependencies) throws IOException;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java?rev=1182107&r1=1182106&r2=1182107&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/StreamableResourceSource.java Tue Oct 11 21:47:22 2011
@@ -14,16 +14,16 @@
 
 package org.apache.tapestry5.services.assets;
 
-import java.io.IOException;
-
 import org.apache.tapestry5.ioc.Resource;
 import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
 
+import java.io.IOException;
+
 /**
  * Converts {@link Resource}s into {@link StreamableResource}s, and may be responsible for
  * {@linkplain ResourceTransformer transforming} resources based on file extension. In addition,
  * service decorators added to the service may provide additional processing (compression, minimization, and caching).
- * 
+ *
  * @since 5.3
  */
 @UsesMappedConfiguration(ResourceTransformer.class)
@@ -32,15 +32,13 @@ public interface StreamableResourceSourc
     /**
      * Converts a Resource (which must be non-null and exist) into a streamable resource, along with
      * some additional optional behaviors.
-     * 
-     * @param baseResource
-     *            the resource to convert
-     * @param processing
-     *            defines additional processing after the resource has been read and possibly transformed
+     *
+     * @param baseResource the resource to convert
+     * @param processing   defines additional processing after the resource has been read and possibly transformed
+     * @param dependencies Passed to any {@link ResourceTransformer} to track additional dependencies of the base resource
      * @return the contents of the Resource, possibly transformed, in a streamable format.
-     * @throws IOException
-     *             if the resource does not exist or a URL for the content is not available
+     * @throws IOException if the resource does not exist or a URL for the content is not available
      */
-    StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing)
+    StreamableResource getStreamableResource(Resource baseResource, StreamableResourceProcessing processing, ResourceDependencies dependencies)
             throws IOException;
 }