You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2010/04/19 15:48:23 UTC

svn commit: r935566 - in /tapestry/tapestry5/trunk/tapestry-core/src: main/java/org/apache/tapestry5/internal/ main/java/org/apache/tapestry5/internal/services/ main/java/org/apache/tapestry5/internal/services/assets/ main/java/org/apache/tapestry5/ser...

Author: hlship
Date: Mon Apr 19 13:48:23 2010
New Revision: 935566

URL: http://svn.apache.org/viewvc?rev=935566&view=rev
Log:
Temporarily cobble back together the virtual assets.

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/AssetConstants.java   (with props)
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/VirtualAssetRequestHandler.java   (with props)
Removed:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/VirtualAssetDispatcher.java
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.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/DocumentLinkerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestConstants.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/VirtualAssetStreamerImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetPathConstructorImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/TapestryModule.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetPathConstructor.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.java

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/AssetConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/AssetConstants.java?rev=935566&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/AssetConstants.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/AssetConstants.java Mon Apr 19 13:48:23 2010
@@ -0,0 +1,29 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal;
+
+/**
+ * Defines constants for the two basic asset prefixes.
+ * 
+ * @since 5.2.0
+ */
+public class AssetConstants
+{
+    /** For assets that are stored in the web application context. */
+    public static final String CONTEXT = "context";
+
+    /** For assets that are stored in the classpath (i.e., inside 3rd party component library JARs). */
+    public static final String CLASSPATH = "classpath";
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/AssetConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocator.java Mon Apr 19 13:48:23 2010
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.internal.services;
 
 import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.services.assets.AssetPathConstructor;
 
 import java.io.IOException;
 
@@ -29,13 +30,25 @@ import java.io.IOException;
 public interface AssetResourceLocator
 {
     /**
-     * Analyzes the path and identifies the underying Asset Resource for that path. Handles context resources and
-     * checking for a digest.
+     * Analyzes the path and identifies the underlying Asset Resource for that path. Handles both context resources and
+     * classpath resources,
+     * as well as checking for a digest (for protected classpath resources).
      * 
      * @param path
-     *            classpath path, possibly including a checksum in the file name
-     * @return resource corresponding to path (may be for a non-existent resource), or null if path is invalid (i.e.,
+     *            path for Asset URL, as per {@link AssetPathConstructor#constructAssetPath(String, String)}
+     * @return
+     *         resource corresponding to path (may be for a non-existent resource), or null if path is invalid (i.e.,
      *         incorrect digest)
      */
-    Resource findResourceForPath(String path) throws IOException;
+    Resource findResourceForAssetPath(String path) throws IOException;
+
+    /**
+     * For a complete classpath path, returns the Resource for the path. This include checking for a
+     * digest for protected files.
+     * 
+     * @return
+     *         resource corresponding to path (may be for a non-existent resource), or null if path is invalid (i.e.,
+     *         incorrect digest)
+     */
+    Resource findClasspathResourceForPath(String path) throws IOException;
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetResourceLocatorImpl.java Mon Apr 19 13:48:23 2010
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2010 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,12 +15,16 @@
 package org.apache.tapestry5.internal.services;
 
 import java.io.IOException;
+import java.util.Map;
 
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.tapestry5.internal.AssetConstants;
 import org.apache.tapestry5.ioc.Resource;
-import org.apache.tapestry5.ioc.internal.util.ClasspathResource;
+import org.apache.tapestry5.services.AssetSource;
+import org.apache.tapestry5.services.ClasspathAssetAliasManager;
 import org.apache.tapestry5.services.Response;
+import org.apache.tapestry5.services.assets.AssetPathConstructor;
 
 public class AssetResourceLocatorImpl implements AssetResourceLocator
 {
@@ -28,21 +32,79 @@ public class AssetResourceLocatorImpl im
 
     private final Response response;
 
+    private final AssetSource assetSource;
+
+    private final String contextAssetPathPrefix;
+
+    private final String assetPathPrefix;
+    
+    private final Map<String, String> classpathMappings;
+
     public AssetResourceLocatorImpl(ResourceCache resourceCache,
 
-    Response response)
+    Response response,
+
+    AssetSource assetSource, ClasspathAssetAliasManager aliasManager,
+
+    AssetPathConstructor assetPathConstructor)
     {
         this.resourceCache = resourceCache;
         this.response = response;
+        this.assetSource = assetSource;
+
+        classpathMappings = aliasManager.getMappings();
+
+        contextAssetPathPrefix = assetPathConstructor.constructAssetPath(RequestConstants.CONTEXT_FOLDER, "");
+        
+        assetPathPrefix = assetPathConstructor.getAssetPathPrefix();
+        
+    }
+
+    public Resource findResourceForAssetPath(String path) throws IOException
+    {
+        if (path.startsWith(contextAssetPathPrefix))
+        {
+            String assetPath = String.format("%s:%s", AssetConstants.CONTEXT, path.substring(contextAssetPathPrefix
+                    .length() + 1));
+
+            return assetSource.resourceForPath(assetPath);
+        }
+
+        // TODO: We need some work in this area to support more than just classpath and context assets
+        // but any asset.
+
+        // The path provided has been mangled into an asset URL for a classpath asset. Let's unmangle it.
+
+        // Strip off the asset path prefix, leaving just the virtual folder and path below it.
+        
+        String virtualPath = path.substring(assetPathPrefix.length());
+        
+        int slashx = virtualPath.indexOf('/');
+        String virtualFolder = virtualPath.substring(0, slashx);
+        String extraPath = virtualPath.substring(slashx + 1);
+
+        String assetPath = classpathMappings.get(virtualFolder) + "/" + extraPath;
+
+        return findClasspathResourceForPath(assetPath);
     }
 
-    public Resource findResourceForPath(String path) throws IOException
+    public Resource findClasspathResourceForPath(String path) throws IOException
     {
-        Resource resource = new ClasspathResource(path);
+
+        Resource resource = assetSource.resourceForPath(path);
 
         if (!resourceCache.requiresDigest(resource))
             return resource;
 
+        return validateChecksumOfClasspathResource(resource);
+    }
+
+    /**
+     * Validates the checksome encoded into the resource, and returns the true resource (with the checksum
+     * portion removed from the file name).
+     */
+    private Resource validateChecksumOfClasspathResource(Resource resource) throws IOException
+    {
         String file = resource.getFile();
 
         // Somehow this code got real ugly, but it's all about preventing NPEs when a resource

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=935566&r1=935565&r2=935566&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 Mon Apr 19 13:48:23 2010
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,6 +15,7 @@
 package org.apache.tapestry5.internal.services;
 
 import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.internal.AssetConstants;
 import org.apache.tapestry5.ioc.Resource;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
 import org.apache.tapestry5.ioc.internal.util.Defense;
@@ -28,10 +29,6 @@ import java.util.Map;
 
 public class AssetSourceImpl implements AssetSource
 {
-    private static final String CLASSPATH = "classpath";
-
-    private static final String CONTEXT = "context";
-
     private final StrategyRegistry<AssetFactory> registry;
 
     private final ThreadLocale threadLocale;
@@ -75,7 +72,7 @@ public class AssetSourceImpl implements 
 
     public Asset getContextAsset(String path, Locale locale)
     {
-        return getAsset(prefixToRootResource.get(CONTEXT), path, locale);
+        return getAsset(prefixToRootResource.get(AssetConstants.CONTEXT), path, locale);
     }
 
     public Asset getAsset(Resource baseResource, String path, Locale locale)
@@ -101,7 +98,7 @@ public class AssetSourceImpl implements 
 
         if (colonx < 0)
         {
-            Resource root = baseResource != null ? baseResource : prefixToRootResource.get(CLASSPATH);
+            Resource root = baseResource != null ? baseResource : prefixToRootResource.get(AssetConstants.CLASSPATH);
 
             return root.forFile(path);
         }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DocumentLinkerImpl.java Mon Apr 19 13:48:23 2010
@@ -1,4 +1,4 @@
-// Copyright 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2007, 2008, 2009, 2010 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@ import org.apache.tapestry5.ioc.internal
 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
 import org.apache.tapestry5.services.ClientDataEncoder;
 import org.apache.tapestry5.services.ClientDataSink;
+import org.apache.tapestry5.services.assets.AssetPathConstructor;
 
 import java.io.IOException;
 import java.io.ObjectOutputStream;
@@ -54,6 +55,8 @@ public class DocumentLinkerImpl implemen
 
     private final int contextPathLength;
 
+    private final AssetPathConstructor assetPathConstructor;
+
     /**
      * @param productionMode
      *            via symbol configuration
@@ -67,12 +70,16 @@ public class DocumentLinkerImpl implemen
      *            {@link org.apache.tapestry5.services.Request#getContextPath()}
      * @param clientDataEncoder
      *            used to encode data for the combined virtual asset
+     * @param assetPathConstructor
+     *            TODO
      */
     public DocumentLinkerImpl(boolean productionMode, boolean omitGeneratorMetaTag, String tapestryVersion,
-            boolean combineScripts, String contextPath, ClientDataEncoder clientDataEncoder)
+            boolean combineScripts, String contextPath, ClientDataEncoder clientDataEncoder,
+            AssetPathConstructor assetPathConstructor)
     {
         this.combineScripts = combineScripts;
         this.clientDataEncoder = clientDataEncoder;
+        this.assetPathConstructor = assetPathConstructor;
 
         developmentMode = !productionMode;
         this.omitGeneratorMetaTag = omitGeneratorMetaTag;
@@ -248,8 +255,9 @@ public class DocumentLinkerImpl implemen
                 stream.writeUTF(scriptURL.substring(contextPathLength));
             }
 
-            String virtualURL = fullAssetPrefix + RequestConstants.VIRTUAL_FOLDER + dataSink.getEncodedClientData()
-                    + ".js";
+            String virtualURL = assetPathConstructor.constructAssetPath(RequestConstants.VIRTUAL_FOLDER, dataSink
+                    .getEncodedClientData()
+                    + ".js");
 
             container.element("script", "type", "text/javascript", "src", virtualURL);
         }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestConstants.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestConstants.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestConstants.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestConstants.java Mon Apr 19 13:48:23 2010
@@ -42,7 +42,7 @@ public final class RequestConstants
      * 
      * @since 5.1.0.2
      */
-    public static final String VIRTUAL_FOLDER = "virtual/";
+    public static final String VIRTUAL_FOLDER = "virtual";
 
     /**
      * Name of parameter, in an Ajax update, that identifies the client-side id of the {@link Form} being extended. Used

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/VirtualAssetStreamerImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/VirtualAssetStreamerImpl.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/VirtualAssetStreamerImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/VirtualAssetStreamerImpl.java Mon Apr 19 13:48:23 2010
@@ -114,8 +114,7 @@ public class VirtualAssetStreamerImpl im
         request.setAttribute(InternalConstants.SUPPRESS_COMPRESSION, true);
 
         // CSS support is problematic, because of relative URLs inside the CSS files. For the
-        // moment, only
-        // JavaScript is supported.
+        // moment, only JavaScript is supported.
 
         OutputStream output = response.getOutputStream("text/javascript");
 
@@ -221,7 +220,7 @@ public class VirtualAssetStreamerImpl im
 
     private void streamPath(String path, ByteArrayOutputStream output) throws IOException
     {
-        Resource resource = resourceLocator.findResourceForPath(path);
+        Resource resource = resourceLocator.findResourceForAssetPath(request.getContextPath() + path);
 
         StreamableResource streamable = resourceCache.getStreamableResource(resource);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetPathConstructorImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetPathConstructorImpl.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetPathConstructorImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetPathConstructorImpl.java Mon Apr 19 13:48:23 2010
@@ -37,6 +37,11 @@ public class AssetPathConstructorImpl im
         this.prefix = RequestConstants.ASSET_PATH_PREFIX + applicationVersion + "/";
     }
 
+    public String getAssetPathPrefix()
+    {
+        return request.getContextPath() + prefix;
+    }
+
     public String constructAssetPath(String virtualFolder, String path)
     {
         StringBuilder builder = new StringBuilder(request.getContextPath());

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/ClasspathAssetRequestHandler.java Mon Apr 19 13:48:23 2010
@@ -48,9 +48,9 @@ public class ClasspathAssetRequestHandle
 
     public boolean handleAssetRequest(Request request, Response response, String extraPath) throws IOException
     {
-        String path = baseFolder + "/" + extraPath;
+        String assetPath = baseFolder + "/" + extraPath;
 
-        Resource resource = assetResourceLocator.findResourceForPath(path);
+        Resource resource = assetResourceLocator.findClasspathResourceForPath(assetPath);
 
         if (resource == null)
             return false;

Added: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/VirtualAssetRequestHandler.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/VirtualAssetRequestHandler.java?rev=935566&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/VirtualAssetRequestHandler.java (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/VirtualAssetRequestHandler.java Mon Apr 19 13:48:23 2010
@@ -0,0 +1,52 @@
+// Copyright 2010 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.internal.services.assets;
+
+import java.io.IOException;
+
+import org.apache.tapestry5.internal.services.VirtualAssetStreamer;
+import org.apache.tapestry5.services.Request;
+import org.apache.tapestry5.services.Response;
+import org.apache.tapestry5.services.assets.AssetRequestHandler;
+
+/**
+ * Processes requests for virtual assets, passing off such requests to the {@link VirtualAssetStreamer} service.
+ * 
+ * @since 5.2.0
+ */
+public class VirtualAssetRequestHandler implements AssetRequestHandler
+{
+    private final VirtualAssetStreamer streamer;
+
+    public VirtualAssetRequestHandler(VirtualAssetStreamer streamer)
+    {
+        this.streamer = streamer;
+    }
+
+    public boolean handleAssetRequest(Request request, Response response, String extraPath) throws IOException
+    {
+        // To make the virtual asset look like an ordinary file, a fake ".js" suffix is added, which is
+        // stripped off here.
+
+        int dotx = extraPath.lastIndexOf('.');
+
+        String clientData = extraPath.substring(0, dotx);
+
+        streamer.streamVirtualAsset(clientData);
+
+        return true;
+    }
+
+}

Propchange: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/VirtualAssetRequestHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=935566&r1=935565&r2=935566&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 Mon Apr 19 13:48:23 2010
@@ -51,6 +51,7 @@ import org.apache.tapestry5.corelib.data
 import org.apache.tapestry5.corelib.data.GridPagerPosition;
 import org.apache.tapestry5.corelib.data.InsertPosition;
 import org.apache.tapestry5.grid.GridDataSource;
+import org.apache.tapestry5.internal.AssetConstants;
 import org.apache.tapestry5.internal.DefaultNullFieldStrategy;
 import org.apache.tapestry5.internal.DefaultValidationDecorator;
 import org.apache.tapestry5.internal.InternalConstants;
@@ -79,6 +80,7 @@ import org.apache.tapestry5.internal.ser
 import org.apache.tapestry5.internal.services.assets.AssetPathConstructorImpl;
 import org.apache.tapestry5.internal.services.assets.ClasspathAssetRequestHandler;
 import org.apache.tapestry5.internal.services.assets.ContextAssetRequestHandler;
+import org.apache.tapestry5.internal.services.assets.VirtualAssetRequestHandler;
 import org.apache.tapestry5.internal.services.messages.PropertiesFileParserImpl;
 import org.apache.tapestry5.internal.transform.*;
 import org.apache.tapestry5.internal.translator.NumericTranslator;
@@ -116,6 +118,7 @@ import org.apache.tapestry5.validator.Mi
 import org.apache.tapestry5.validator.Regexp;
 import org.apache.tapestry5.validator.Required;
 import org.apache.tapestry5.validator.ValidatorMacro;
+import org.apache.tools.ant.taskdefs.condition.ResourceContains;
 import org.slf4j.Logger;
 
 /**
@@ -461,7 +464,8 @@ public final class TapestryModule
     }
 
     /**
-     * Contributes an handler for each mapped classpath alias, as well as one for context assets.
+     * Contributes an handler for each mapped classpath alias, as well handlers for context assets
+     * and virtual assets (combined Javascript files).
      */
     public static void contributeAssetDispatcher(MappedConfiguration<String, AssetRequestHandler> configuration,
 
@@ -482,6 +486,8 @@ public final class TapestryModule
 
         configuration.add(RequestConstants.CONTEXT_FOLDER, new ContextAssetRequestHandler(streamer, contextAssetFactory
                 .getRootResource()));
+
+        configuration.addInstance(RequestConstants.VIRTUAL_FOLDER, VirtualAssetRequestHandler.class);
     }
 
     private static String toPackagePath(String packageName)
@@ -1688,8 +1694,8 @@ public final class TapestryModule
     @ClasspathProvider
     AssetFactory classpathAssetFactory)
     {
-        configuration.add("context", contextAssetFactory);
-        configuration.add("classpath", classpathAssetFactory);
+        configuration.add(AssetConstants.CONTEXT, contextAssetFactory);
+        configuration.add(AssetConstants.CLASSPATH, classpathAssetFactory);
     }
 
     /**
@@ -1789,9 +1795,7 @@ public final class TapestryModule
      * <dt>RootPath</dt>
      * <dd>Renders the start page for the "/" request (outdated)</dd>
      * <dt>Asset</dt>
-     * <dd>Provides access to assets</dd>
-     * <dt>VirtualAsset</dt>
-     * <dd>Provides access to combined scripts</dd>
+     * <dd>Provides access to assets (context, classpath and virtual) via {@link AssetDispatcher}</dd>
      * <dt>PageRender</dt>
      * <dd>Identifies the {@link org.apache.tapestry5.services.PageRenderRequestParameters} and forwards onto
      * {@link PageRenderRequestHandler}</dd>
@@ -1818,8 +1822,6 @@ public final class TapestryModule
 
         configuration.add("Asset", assetDispatcher, "before:ComponentEvent");
 
-        configuration.addInstance("VirtualAsset", VirtualAssetDispatcher.class, "before:Asset");
-
         configuration.addInstance("ComponentEvent", ComponentEventDispatcher.class, "before:PageRender");
 
         configuration.addInstance("PageRender", PageRenderDispatcher.class);
@@ -1912,14 +1914,16 @@ public final class TapestryModule
 
     final ClientDataEncoder clientDataEncoder,
 
-    final ClientInfrastructure clientInfrastructure)
+    final ClientInfrastructure clientInfrastructure,
+
+    final AssetPathConstructor assetPathConstructor)
     {
         MarkupRendererFilter documentLinker = new MarkupRendererFilter()
         {
             public void renderMarkup(MarkupWriter writer, MarkupRenderer renderer)
             {
                 DocumentLinkerImpl linker = new DocumentLinkerImpl(productionMode, omitGeneratorMeta, tapestryVersion,
-                        combineScripts, request.getContextPath(), clientDataEncoder);
+                        combineScripts, request.getContextPath(), clientDataEncoder, assetPathConstructor);
 
                 environment.push(DocumentLinker.class, linker);
 

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetPathConstructor.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetPathConstructor.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetPathConstructor.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/assets/AssetPathConstructor.java Mon Apr 19 13:48:23 2010
@@ -29,7 +29,15 @@ public interface AssetPathConstructor
      *            corresponds to a {@link AssetRequestHandler} contributed to the AssetDispatcher service
      * @param path
      *            within the virtual folder (should <em>not</em> start with a slash)
-     * @return path portion of asset URL
+     * @return path portion of asset URL, including the context path, the /assets/ virtual folder, the application
+     *         version number,
+     *         the virtual folder, and the path extension
      */
     String constructAssetPath(String virtualFolder, String path);
+
+    /**
+     * Returns the prefix portion of the asset URL, the portion including the context path, the /assets/ virtual folder,
+     * and the version number, and the trailing slash.
+     */
+    String getAssetPathPrefix();
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.java?rev=935566&r1=935565&r2=935566&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/DocumentLinkerImplTest.java Mon Apr 19 13:48:23 2010
@@ -1,10 +1,10 @@
-// Copyright 2007, 2008, 2009 The Apache Software Foundation
+// Copyright 2007, 2008, 2009, 2010 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
 // You may obtain a copy of the License at
 //
-//     http://www.apache.org/licenses/LICENSE-2.0
+// http://www.apache.org/licenses/LICENSE-2.0
 //
 // Unless required by applicable law or agreed to in writing, software
 // distributed under the License is distributed on an "AS IS" BASIS,
@@ -19,6 +19,9 @@ import org.apache.tapestry5.dom.Element;
 import org.apache.tapestry5.dom.XMLMarkupModel;
 import org.apache.tapestry5.internal.test.InternalBaseTestCase;
 import org.apache.tapestry5.services.URLEncoder;
+import org.apache.tapestry5.services.assets.AssetPathConstructor;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
@@ -47,7 +50,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("not-html").text("not an HTML document");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         // Only checked if there's something to link.
 
@@ -61,8 +64,9 @@ public class DocumentLinkerImplTest exte
         }
         catch (RuntimeException ex)
         {
-            assertEquals(ex.getMessage(),
-                         "The root element of the rendered document was <not-html>, not <html>. A root element of <html> is needed when linking JavaScript and stylesheet resources.");
+            assertEquals(
+                    ex.getMessage(),
+                    "The root element of the rendered document was <not-html>, not <html>. A root element of <html> is needed when linking JavaScript and stylesheet resources.");
         }
     }
 
@@ -73,7 +77,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("not-html").text("not an HTML document");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         // Only checked if there's something to link.
 
@@ -95,7 +99,7 @@ public class DocumentLinkerImplTest exte
     {
         Document document = new Document();
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addScript("foo.js");
         linker.addScript("doSomething();");
@@ -112,7 +116,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addScriptLink("foo.js");
         linker.addScriptLink("bar/baz.js");
@@ -133,11 +137,10 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be marked with generator meta.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, false, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, false, "1.2.3", false, "", null, null);
 
         linker.updateDocument(document);
 
-
         check(document, "include_generator_meta.txt");
     }
 
@@ -151,11 +154,10 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("no_html").text("Generator meta only added if root is html tag.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, false, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, false, "1.2.3", false, "", null, null);
 
         linker.updateDocument(document);
 
-
         check(document, "omit_generator_meta_on_no_html_root.txt");
     }
 
@@ -166,7 +168,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addStylesheetLink("style.css", "print");
         linker.addScriptLink("foo.js");
@@ -185,7 +187,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts at top.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addScriptLink("foo.js");
         linker.addScriptLink("bar/baz.js");
@@ -203,7 +205,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with styles.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addStylesheetLink("foo.css", null);
         linker.addStylesheetLink("bar/baz.css", "print");
@@ -220,7 +222,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with styles.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addStylesheetLink("foo.css", null);
         linker.addStylesheetLink("bar/baz.css", "print");
@@ -238,10 +240,10 @@ public class DocumentLinkerImplTest exte
     {
         Document document = new Document(new XMLMarkupModel());
 
-        document.newRootElement("html").element("head").comment("existing head").getParent()
-                .element("body").text("body content");
+        document.newRootElement("html").element("head").comment("existing head").getParent().element("body").text(
+                "body content");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addStylesheetLink("foo.css", null);
 
@@ -257,7 +259,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         for (int i = 0; i < 3; i++)
         {
@@ -278,7 +280,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addScript("doSomething();");
         linker.addScript("doSomethingElse();");
@@ -295,7 +297,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(false, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(false, true, "1.2.3", false, "", null, null);
 
         linker.addScriptLink("foo.js");
 
@@ -314,7 +316,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("notbody").element("p").text("Ready to be updated with scripts.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addScriptLink("foo.js");
 
@@ -323,7 +325,6 @@ public class DocumentLinkerImplTest exte
         check(document, "no_body_element.txt");
     }
 
-
     @Test
     public void script_written_raw() throws Exception
     {
@@ -331,7 +332,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", false, "", null, null);
 
         linker.addScript("for (var i = 0; i < 5; i++)  { doIt(i); }");
 
@@ -343,13 +344,37 @@ public class DocumentLinkerImplTest exte
     @Test
     public void aggregated_script_link() throws Exception
     {
+        final ClientDataEncoderImpl encoder = new ClientDataEncoderImpl(urlEncoder);
+
+        AssetPathConstructor apc = newMock(AssetPathConstructor.class);
+
+        expect(apc.constructAssetPath(EasyMock.eq(RequestConstants.VIRTUAL_FOLDER), EasyMock.isA(String.class)))
+                .andAnswer(new IAnswer<String>()
+                {
+                    public String answer() throws Throwable
+                    {
+                        String path = (String) EasyMock.getCurrentArguments()[1];
+
+                        String clientData = path.substring(0, path.length() - 3);
+
+                        ObjectInputStream stream = encoder.decodeEncodedClientData(clientData);
+
+                        assertEquals(stream.readInt(), 2);
+                        assertEquals(stream.readUTF(), "/assets/foo.js");
+                        assertEquals(stream.readUTF(), "/assets/xyz/bar.js");
+
+                        return "{virtual}";
+                    }
+
+                });
+
+        replay();
+
         Document document = new Document();
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.");
 
-        ClientDataEncoderImpl encoder = new ClientDataEncoderImpl(urlEncoder);
-
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", true, "/context", encoder);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", true, "/context", encoder, apc);
 
         linker.addScriptLink("/context/assets/foo.js");
         linker.addScriptLink("/context/assets/xyz/bar.js");
@@ -358,17 +383,9 @@ public class DocumentLinkerImplTest exte
 
         Element script = document.getRootElement().find("head/script");
 
-        String assetURL = script.getAttribute("src");
-
-        String fileName = assetURL.substring("/context/assets/virtual/".length());
-
-        String clientData = fileName.substring(0, fileName.length() - 3);
-
-        ObjectInputStream stream = encoder.decodeEncodedClientData(clientData);
+        assertEquals(script.getAttribute("src"), "{virtual}");
 
-        assertEquals(stream.readInt(), 2);
-        assertEquals(stream.readUTF(), "/assets/foo.js");
-        assertEquals(stream.readUTF(), "/assets/xyz/bar.js");
+        verify();
     }
 
     @Test
@@ -378,7 +395,7 @@ public class DocumentLinkerImplTest exte
 
         document.newRootElement("html").element("body").element("p").text("Ready to be updated with scripts.");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", true, "/context", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", true, "/context", null, null);
 
         linker.addScriptLink("/context/foo.js");
 
@@ -401,7 +418,7 @@ public class DocumentLinkerImplTest exte
         head.element("meta");
         head.element("script");
 
-        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", true, "/context", null);
+        DocumentLinkerImpl linker = new DocumentLinkerImpl(true, true, "1.2.3", true, "/context", null, null);
 
         linker.addScriptLink("/foo.js");
 
@@ -409,6 +426,5 @@ public class DocumentLinkerImplTest exte
 
         assertEquals(document.toString(), readFile("added_scripts_go_before_existing_script.txt"));
 
-
     }
 }