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 2005/09/23 02:38:08 UTC

svn commit: r291051 - in /jakarta/tapestry/trunk: ./ examples/Workbench/src/context/WEB-INF/ framework/src/descriptor/META-INF/ framework/src/java/org/apache/tapestry/asset/ framework/src/java/org/apache/tapestry/pageload/ framework/src/test/org/apache...

Author: hlship
Date: Thu Sep 22 17:37:56 2005
New Revision: 291051

URL: http://svn.apache.org/viewcvs?rev=291051&view=rev
Log:
TAPESTRY-655: In some circumstances, using the classpath: or context: prefixes on paths fails to work

Added:
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ContextAssetFactoryTest.java
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/base-resource.txt
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/base-resource_fr.txt
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/relative-resource.txt
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/relative-resource_fr.txt
Modified:
    jakarta/tapestry/trunk/examples/Workbench/src/context/WEB-INF/workbench.application
    jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetFactory.java
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetMessages.java
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetSourceImpl.java
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetStrings.properties
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ClasspathAssetFactory.java
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ContextAssetFactory.java
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/DefaultAssetFactory.java
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/PrivateAsset.java
    jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/pageload/PageLoader.java
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestAssetSource.java
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/app/RelativeAssets.page
    jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/wml/Home.page
    jakarta/tapestry/trunk/status.xml

Modified: jakarta/tapestry/trunk/examples/Workbench/src/context/WEB-INF/workbench.application
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/examples/Workbench/src/context/WEB-INF/workbench.application?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/examples/Workbench/src/context/WEB-INF/workbench.application (original)
+++ jakarta/tapestry/trunk/examples/Workbench/src/context/WEB-INF/workbench.application Thu Sep 22 17:37:56 2005
@@ -27,6 +27,6 @@
   
   <extension name="org.apache.tapestry.request-decoder" class="org.apache.tapestry.workbench.RequestDecoder"/>
          
-  <library id="contrib" specification-path="/org/apache/tapestry/contrib/Contrib.library"/>
+  <library id="contrib" specification-path="classpath:/org/apache/tapestry/contrib/Contrib.library"/>
   
 </application>

Modified: jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml (original)
+++ jakarta/tapestry/trunk/framework/src/descriptor/META-INF/tapestry.asset.xml Thu Sep 22 17:37:56 2005
@@ -61,9 +61,9 @@
     
     <invoke-factory>
       <construct class="ContextAssetFactory">
-        <set-service property="context" service-id="tapestry.globals.WebContext"/>
+        <set-service property="classpathAssetFactory" service-id="ClasspathAssetFactory"/>
         <set-object property="contextPath" value="infrastructure:contextPath"/>
-        <set-object property="assetService" value="engine-service:asset"/>
+        <set-service property="webContext" service-id="tapestry.globals.WebContext"/>
       </construct>
     </invoke-factory>
     

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetFactory.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetFactory.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetFactory.java Thu Sep 22 17:37:56 2005
@@ -30,7 +30,7 @@
 public interface AssetFactory
 {
     /**
-     * Creates a new asset.
+     * Creates a new asset relative to an existing asset.
      * 
      * @param baseResource
      *            the base resource from which an asset path may be calculated. Each type of asset
@@ -49,6 +49,19 @@
      *             if no matching asset may be found.
      */
     public IAsset createAsset(Resource baseResource, String path, Locale locale, Location location);
+
+    /**
+     * Creates a new asset relative to the root of the domain defined by the type of asset.
+     * 
+     * @param path
+     *            the absolute path for the resource
+     * @param locale
+     *            the locale to localize the asset to, or null for no localization
+     * @param location
+     *            the location used to report any errors
+     * @return an {@link IAsset}
+     */
+    public IAsset createAbsoluteAsset(String path, Locale locale, Location location);
 
     /**
      * Creates a new asset based on a known resource.

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetMessages.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetMessages.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetMessages.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetMessages.java Thu Sep 22 17:37:56 2005
@@ -51,4 +51,14 @@
     {
         return _formatter.format("exception-report-title", path);
     }
+
+    static String missingClasspathResource(String path)
+    {
+        return _formatter.format("missing-classpath-resource", path);
+    }
+
+    static String missingContextResource(String path)
+    {
+        return _formatter.format("missing-context-resource", path);
+    }
 }

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetSourceImpl.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetSourceImpl.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetSourceImpl.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetSourceImpl.java Thu Sep 22 17:37:56 2005
@@ -20,6 +20,7 @@
 import java.util.Locale;
 import java.util.Map;
 
+import org.apache.hivemind.ApplicationRuntimeException;
 import org.apache.hivemind.Location;
 import org.apache.hivemind.Resource;
 import org.apache.hivemind.util.Defense;
@@ -80,6 +81,11 @@
 
             truePath = path;
         }
+
+        if (truePath.startsWith("/"))
+            return factory.createAbsoluteAsset(truePath, locale, location);
+
+        // This can happen when a 3.0 DTD is read in
 
         return factory.createAsset(base, truePath, locale, location);
     }

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetStrings.properties
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetStrings.properties?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetStrings.properties (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/AssetStrings.properties Thu Sep 22 17:37:56 2005
@@ -12,8 +12,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-missing-asset=Unable to locate asset ''{0}'' relative to {1}.
+missing-classpath-resource=Missing classpath resource ''{0}''.
+missing-context-resource=Missing context resource ''{0}''.
+missing-asset=Unable to locate resource ''{0}'' relative to {1}.
 no-such-resource=Classpath resource ''{0}'' does not exist.
 unable-to-read-resource=Unable to read classpath resource ''{0}'': {1}
 exception-report-title=Failure to export classpath resource {0}.
-md5-mismatch=The MD5 digest provided in the request does not match the actual value for classpath resource ''{0}''.
\ No newline at end of file
+md5-mismatch=The MD5 digest provided in the request does not match the actual value for classpath resource ''{0}''.

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ClasspathAssetFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ClasspathAssetFactory.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ClasspathAssetFactory.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ClasspathAssetFactory.java Thu Sep 22 17:37:56 2005
@@ -17,6 +17,7 @@
 import java.util.Locale;
 
 import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.ClassResolver;
 import org.apache.hivemind.Location;
 import org.apache.hivemind.Resource;
 import org.apache.hivemind.util.ClasspathResource;
@@ -32,6 +33,8 @@
  */
 public class ClasspathAssetFactory implements AssetFactory
 {
+    private ClassResolver _classResolver;
+
     private IEngineService _assetService;
 
     public IAsset createAsset(Resource baseResource, String path, Locale locale, Location location)
@@ -43,7 +46,19 @@
             throw new ApplicationRuntimeException(AssetMessages.missingAsset(path, baseResource),
                     location, null);
 
-        return new PrivateAsset((ClasspathResource) localized, _assetService, location);
+        return createAsset(localized, location);
+    }
+
+    public IAsset createAbsoluteAsset(String path, Locale locale, Location location)
+    {
+        Resource base = new ClasspathResource(_classResolver, path);
+        Resource localized = base.getLocalization(locale);
+
+        if (localized == null)
+            throw new ApplicationRuntimeException(AssetMessages.missingClasspathResource(path),
+                    location, null);
+
+        return createAsset(localized, location);
     }
 
     public IAsset createAsset(Resource resource, Location location)
@@ -56,5 +71,10 @@
     public void setAssetService(IEngineService assetService)
     {
         _assetService = assetService;
+    }
+
+    public void setClassResolver(ClassResolver classResolver)
+    {
+        _classResolver = classResolver;
     }
 }

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ContextAssetFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ContextAssetFactory.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ContextAssetFactory.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/ContextAssetFactory.java Thu Sep 22 17:37:56 2005
@@ -17,42 +17,39 @@
 import java.util.Locale;
 
 import org.apache.hivemind.ApplicationRuntimeException;
-import org.apache.hivemind.ClassResolver;
 import org.apache.hivemind.Location;
 import org.apache.hivemind.Resource;
-import org.apache.hivemind.util.ClasspathResource;
 import org.apache.tapestry.IAsset;
-import org.apache.tapestry.engine.IEngineService;
 import org.apache.tapestry.web.WebContext;
 import org.apache.tapestry.web.WebContextResource;
 
 /**
- * For the moment, all "context:" prefixed asset paths are interpreted relative to the web context
- * (the web application's root folder).
+ * All "context:" prefixed asset paths are interpreted relative to the web context (the web
+ * application's root folder).
  * 
  * @author Howard M. Lewis Ship
  * @since 4.0
  */
 public class ContextAssetFactory implements AssetFactory
 {
-    private WebContext _context;
-
     private String _contextPath;
 
-    private Resource _servletRoot;
-
-    private ClassResolver _classResolver;
+    private AssetFactory _classpathAssetFactory;
 
-    private IEngineService _assetService;
+    private WebContext _webContext;
 
-    public void initializeService()
+    public void setWebContext(WebContext webContext)
     {
-        _servletRoot = new WebContextResource(_context, "/");
+        _webContext = webContext;
     }
 
     public IAsset createAsset(Resource baseResource, String path, Locale locale, Location location)
     {
-        Resource assetResource = _servletRoot.getRelativeResource(path);
+        // We always create a new asset relative to an existing resource; the type of resource
+        // will jive with the type of asset returned. Path may start with a leading slash, which
+        // yields an absolute, not relative, path to the resource.
+
+        Resource assetResource = baseResource.getRelativeResource(path);
 
         // Here's the thing; In Tapestry 3.0 and earlier, you could specify
         // library path like /org/apache/tapestry/contrib/Contrib.library. In the new scheme
@@ -60,28 +57,32 @@
         // But to keep a lot of things from breaking, we'll kludgely allow that here.
 
         if (assetResource.getResourceURL() == null && path.startsWith("/"))
-        {
-            ClasspathResource resource = new ClasspathResource(_classResolver, path);
-            return new PrivateAsset(resource, _assetService, location);
-        }
+            return _classpathAssetFactory.createAbsoluteAsset(path, locale, location);
 
         Resource localized = assetResource.getLocalization(locale);
 
         if (localized == null)
-            throw new ApplicationRuntimeException(AssetMessages.missingAsset(path, _servletRoot),
+            throw new ApplicationRuntimeException(AssetMessages.missingAsset(path, baseResource),
                     location, null);
 
-        return new ContextAsset(_contextPath, localized, location);
+        return createAsset(localized, location);
     }
 
-    public IAsset createAsset(Resource resource, Location location)
+    public IAsset createAbsoluteAsset(String path, Locale locale, Location location)
     {
-        return new ContextAsset(_contextPath, resource, location);
+        Resource base = new WebContextResource(_webContext, path);
+        Resource localized = base.getLocalization(locale);
+
+        if (localized == null)
+            throw new ApplicationRuntimeException(AssetMessages.missingContextResource(path),
+                    location, null);
+
+        return createAsset(localized, location);
     }
 
-    public void setContext(WebContext context)
+    public IAsset createAsset(Resource resource, Location location)
     {
-        _context = context;
+        return new ContextAsset(_contextPath, resource, location);
     }
 
     public void setContextPath(String contextPath)
@@ -89,13 +90,8 @@
         _contextPath = contextPath;
     }
 
-    public void setAssetService(IEngineService assetService)
-    {
-        _assetService = assetService;
-    }
-
-    public void setClassResolver(ClassResolver classResolver)
+    public void setClasspathAssetFactory(AssetFactory classpathAssetFactory)
     {
-        _classResolver = classResolver;
+        _classpathAssetFactory = classpathAssetFactory;
     }
 }

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/DefaultAssetFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/DefaultAssetFactory.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/DefaultAssetFactory.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/DefaultAssetFactory.java Thu Sep 22 17:37:56 2005
@@ -40,4 +40,9 @@
         return new ExternalAsset(resource.getPath(), location);
     }
 
+    public IAsset createAbsoluteAsset(String path, Locale locale, Location location)
+    {
+        return new ExternalAsset(path, location);
+    }
+
 }

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/PrivateAsset.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/PrivateAsset.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/PrivateAsset.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/asset/PrivateAsset.java Thu Sep 22 17:37:56 2005
@@ -90,9 +90,7 @@
         }
         catch (Exception ex)
         {
-            throw new ApplicationRuntimeException(Tapestry.format(
-                    "PrivateAsset.resource-missing",
-                    location), ex);
+            throw new ApplicationRuntimeException(AssetMessages.noSuchResource(location.getPath()));
         }
     }
 

Modified: jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/pageload/PageLoader.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/pageload/PageLoader.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/pageload/PageLoader.java (original)
+++ jakarta/tapestry/trunk/framework/src/java/org/apache/tapestry/pageload/PageLoader.java Thu Sep 22 17:37:56 2005
@@ -24,7 +24,9 @@
 import org.apache.hivemind.ClassResolver;
 import org.apache.hivemind.HiveMind;
 import org.apache.hivemind.Location;
+import org.apache.hivemind.Resource;
 import org.apache.hivemind.service.ThreadLocale;
+import org.apache.hivemind.util.ContextResource;
 import org.apache.tapestry.AbstractComponent;
 import org.apache.tapestry.BaseComponent;
 import org.apache.tapestry.IAsset;
@@ -56,6 +58,7 @@
 import org.apache.tapestry.spec.IContainedComponent;
 import org.apache.tapestry.spec.IListenerBindingSpecification;
 import org.apache.tapestry.spec.IParameterSpecification;
+import org.apache.tapestry.web.WebContextResource;
 
 /**
  * Runs the process of building the component hierarchy for an entire page.
@@ -705,7 +708,7 @@
     }
 
     /**
-     * Builds an instance of {@link IAsset}from the specification.
+     * Builds an instance of {@link IAsset} from the specification.
      */
 
     private IAsset convertAsset(IAssetSpecification spec)
@@ -714,7 +717,21 @@
         String path = spec.getPath();
         Location location = spec.getLocation();
 
-        return _assetSource.findAsset(location.getResource(), path, _locale, location);
+        Resource specResource = location.getResource();
+
+        // And ugly, ugly kludge. For page and component specifications in the
+        // context (typically, somewhere under WEB-INF), we evaluate them
+        // relative the web application root.
+
+        if (isContextResource(specResource))
+            specResource = specResource.getRelativeResource("/");
+
+        return _assetSource.findAsset(specResource, path, _locale, location);
+    }
+
+    private boolean isContextResource(Resource resource)
+    {
+        return (resource instanceof WebContextResource) || (resource instanceof ContextResource);
     }
 
     /** @since 4.0 */

Added: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java?rev=291051&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java (added)
+++ jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ClasspathAssetFactoryTest.java Thu Sep 22 17:37:56 2005
@@ -0,0 +1,150 @@
+// Copyright 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.asset;
+
+import java.util.Locale;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.Location;
+import org.apache.hivemind.Resource;
+import org.apache.hivemind.test.HiveMindTestCase;
+import org.apache.hivemind.util.ClasspathResource;
+import org.apache.tapestry.IAsset;
+import org.apache.tapestry.engine.IEngineService;
+
+/**
+ * Tests for {@link org.apache.tapestry.asset.ClasspathAssetFactory}.
+ * 
+ * @author Howard M. Lewis Ship
+ */
+public class ClasspathAssetFactoryTest extends HiveMindTestCase
+{
+    public void testCreateAsset()
+    {
+        IEngineService assetService = newService();
+        Location l = newLocation();
+
+        replayControls();
+
+        ClasspathAssetFactory factory = new ClasspathAssetFactory();
+        factory.setClassResolver(getClassResolver());
+        factory.setAssetService(assetService);
+
+        Resource base = newBaseResource();
+
+        IAsset asset = factory.createAsset(base, "relative-resource.txt", Locale.FRENCH, l);
+
+        assertTrue(asset instanceof PrivateAsset);
+        assertEquals("/org/apache/tapestry/asset/relative-resource_fr.txt", asset
+                .getResourceLocation().getPath());
+        assertSame(l, asset.getLocation());
+
+        verifyControls();
+    }
+
+    public void testCreateAssetMissing()
+    {
+        IEngineService assetService = newService();
+        Location l = newLocation();
+
+        replayControls();
+
+        ClasspathAssetFactory factory = new ClasspathAssetFactory();
+        factory.setClassResolver(getClassResolver());
+        factory.setAssetService(assetService);
+
+        Resource base = newBaseResource();
+
+        try
+        {
+            factory.createAsset(base, "does-not-exist.txt", Locale.ENGLISH, l);
+            unreachable();
+        }
+        catch (ApplicationRuntimeException ex)
+        {
+            assertEquals(
+                    "Unable to locate resource 'does-not-exist.txt' relative to classpath:/org/apache/tapestry/asset/base-resource.txt.",
+                    ex.getMessage());
+            assertSame(l, ex.getLocation());
+        }
+
+        verifyControls();
+    }
+
+    public void testCreateAbsoluteAsset()
+    {
+        IEngineService assetService = newService();
+        Location l = newLocation();
+
+        replayControls();
+
+        ClasspathAssetFactory factory = new ClasspathAssetFactory();
+        factory.setClassResolver(getClassResolver());
+        factory.setAssetService(assetService);
+
+        IAsset asset = factory.createAbsoluteAsset(
+                "/org/apache/tapestry/asset/relative-resource.txt",
+                Locale.FRENCH,
+                l);
+
+        assertTrue(asset instanceof PrivateAsset);
+        assertEquals("/org/apache/tapestry/asset/relative-resource_fr.txt", asset
+                .getResourceLocation().getPath());
+        assertSame(l, asset.getLocation());
+
+        verifyControls();
+    }
+
+    public void testCreateAbsoluteAssetMissing()
+    {
+        IEngineService assetService = newService();
+        Location l = newLocation();
+
+        replayControls();
+
+        ClasspathAssetFactory factory = new ClasspathAssetFactory();
+        factory.setClassResolver(getClassResolver());
+        factory.setAssetService(assetService);
+
+        try
+        {
+            factory.createAbsoluteAsset(
+                    "/org/apache/tapestry/asset/does-not-exist.txt",
+                    Locale.ENGLISH,
+                    l);
+            unreachable();
+        }
+        catch (ApplicationRuntimeException ex)
+        {
+            assertEquals(
+                    "Missing classpath resource '/org/apache/tapestry/asset/does-not-exist.txt'.",
+                    ex.getMessage());
+            assertSame(l, ex.getLocation());
+        }
+
+        verifyControls();
+    }
+
+    private ClasspathResource newBaseResource()
+    {
+        return new ClasspathResource(getClassResolver(),
+                "/org/apache/tapestry/asset/base-resource.txt");
+    }
+
+    private IEngineService newService()
+    {
+        return (IEngineService) newMock(IEngineService.class);
+    }
+}

Added: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ContextAssetFactoryTest.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ContextAssetFactoryTest.java?rev=291051&view=auto
==============================================================================
--- jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ContextAssetFactoryTest.java (added)
+++ jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/ContextAssetFactoryTest.java Thu Sep 22 17:37:56 2005
@@ -0,0 +1,198 @@
+// Copyright 2005 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry.asset;
+
+import java.net.URL;
+import java.util.Locale;
+
+import org.apache.hivemind.ApplicationRuntimeException;
+import org.apache.hivemind.Location;
+import org.apache.hivemind.Resource;
+import org.apache.hivemind.test.HiveMindTestCase;
+import org.apache.tapestry.IAsset;
+import org.apache.tapestry.web.WebContext;
+
+public class ContextAssetFactoryTest extends HiveMindTestCase
+{
+    protected Resource newResource()
+    {
+        return (Resource) newMock(Resource.class);
+    }
+
+    protected URL newURL()
+    {
+        return getClass().getResource("base-resource.txt");
+    }
+
+    public void testCreateAsset()
+    {
+        Resource base = newResource();
+        Resource relative = newResource();
+        Resource localized = newResource();
+        Location l = newLocation();
+        URL url = newURL();
+
+        trainGetRelativeResource(base, "asset.png", relative);
+        trainGetResourceURL(relative, url);
+        trainGetLocalization(relative, Locale.FRENCH, localized);
+
+        replayControls();
+
+        ContextAssetFactory factory = new ContextAssetFactory();
+
+        factory.setContextPath("/context");
+
+        IAsset asset = factory.createAsset(base, "asset.png", Locale.FRENCH, l);
+
+        assertTrue(asset instanceof ContextAsset);
+        assertSame(localized, asset.getResourceLocation());
+        assertSame(l, asset.getLocation());
+
+        verifyControls();
+    }
+
+    public void testCreateAssetMissing()
+    {
+        Resource base = newResource();
+        Resource relative = newResource();
+        Location l = newLocation();
+        trainGetRelativeResource(base, "asset.png", relative);
+        trainGetResourceURL(relative, null);
+        trainGetLocalization(relative, Locale.FRENCH, null);
+
+        replayControls();
+
+        ContextAssetFactory factory = new ContextAssetFactory();
+
+        factory.setContextPath("/context");
+
+        try
+        {
+            factory.createAsset(base, "asset.png", Locale.FRENCH, l);
+            unreachable();
+        }
+        catch (ApplicationRuntimeException ex)
+        {
+            assertEquals(
+                    "Unable to locate resource 'asset.png' relative to EasyMock for interface org.apache.hivemind.Resource.",
+                    ex.getMessage());
+            assertSame(l, ex.getLocation());
+        }
+
+        verifyControls();
+    }
+
+    public void testCreateAssetForClasspath()
+    {
+        Resource base = newResource();
+        Resource relative = newResource();
+        Location l = newLocation();
+        AssetFactory classpathFactory = (AssetFactory) newMock(AssetFactory.class);
+        IAsset asset = (IAsset) newMock(IAsset.class);
+
+        trainGetRelativeResource(base, "/asset.png", relative);
+        trainGetResourceURL(relative, null);
+
+        classpathFactory.createAbsoluteAsset("/asset.png", Locale.FRENCH, l);
+        getControl(classpathFactory).setReturnValue(asset);
+
+        replayControls();
+
+        ContextAssetFactory factory = new ContextAssetFactory();
+
+        factory.setContextPath("/context");
+        factory.setClasspathAssetFactory(classpathFactory);
+
+        assertSame(asset, factory.createAsset(base, "/asset.png", Locale.FRENCH, l));
+
+        verifyControls();
+    }
+
+    public void testCreateAbsoluteAsset()
+    {
+        Location l = newLocation();
+        URL url = newURL();
+        WebContext context = (WebContext) newMock(WebContext.class);
+
+        trainGetResource(context, "/asset_fr.png", url);
+
+        replayControls();
+
+        ContextAssetFactory factory = new ContextAssetFactory();
+
+        factory.setContextPath("/context");
+        factory.setWebContext(context);
+
+        IAsset asset = factory.createAbsoluteAsset("/asset.png", Locale.FRENCH, l);
+
+        assertTrue(asset instanceof ContextAsset);
+        assertEquals("/asset_fr.png", asset.getResourceLocation().getPath());
+        assertSame(l, asset.getLocation());
+
+        verifyControls();
+    }
+
+    public void testCreateAbsoluteAssetMissing()
+    {
+        Location l = newLocation();
+        WebContext context = (WebContext) newMock(WebContext.class);
+
+        trainGetResource(context, "/asset_fr.png", null);
+        trainGetResource(context, "/asset.png", null);
+
+        replayControls();
+
+        ContextAssetFactory factory = new ContextAssetFactory();
+
+        factory.setContextPath("/context");
+        factory.setWebContext(context);
+
+        try
+        {
+            factory.createAbsoluteAsset("/asset.png", Locale.FRENCH, l);
+            unreachable();
+        }
+        catch (ApplicationRuntimeException ex)
+        {
+            assertEquals("Missing context resource '/asset.png'.", ex.getMessage());
+            assertSame(l, ex.getLocation());
+        }
+        verifyControls();
+    }
+
+    private void trainGetLocalization(Resource resource, Locale locale, Resource localized)
+    {
+        resource.getLocalization(locale);
+        getControl(resource).setReturnValue(localized);
+    }
+
+    protected void trainGetResourceURL(Resource resource, URL url)
+    {
+        resource.getResourceURL();
+        getControl(resource).setReturnValue(url);
+    }
+
+    protected void trainGetResource(WebContext context, String path, URL url)
+    {
+        context.getResource(path);
+        getControl(context).setReturnValue(url);
+    }
+
+    protected void trainGetRelativeResource(Resource base, String path, Resource relative)
+    {
+        base.getRelativeResource(path);
+        getControl(base).setReturnValue(relative);
+    }
+}

Modified: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestAssetSource.java
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestAssetSource.java?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestAssetSource.java (original)
+++ jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/TestAssetSource.java Thu Sep 22 17:37:56 2005
@@ -70,7 +70,7 @@
 
     public void testKnownPrefix()
     {
-        Location l = fabricateLocation(17);
+        Location l = newLocation();
 
         Resource r = newResource();
         IAsset asset = newAsset();

Added: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/base-resource.txt
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/base-resource.txt?rev=291051&view=auto
==============================================================================
    (empty)

Added: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/base-resource_fr.txt
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/base-resource_fr.txt?rev=291051&view=auto
==============================================================================
    (empty)

Added: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/relative-resource.txt
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/relative-resource.txt?rev=291051&view=auto
==============================================================================
    (empty)

Added: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/relative-resource_fr.txt
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/asset/relative-resource_fr.txt?rev=291051&view=auto
==============================================================================
    (empty)

Modified: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/app/RelativeAssets.page
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/app/RelativeAssets.page?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/app/RelativeAssets.page (original)
+++ jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/app/RelativeAssets.page Thu Sep 22 17:37:56 2005
@@ -22,6 +22,6 @@
 <page-specification class="org.apache.tapestry.html.BasePage">
 
   <private-asset name="private" resource-path="images/PrivateAsset.gif"/>
-  <context-asset name="context" path="images/ContextAsset.gif"/>
+  <context-asset name="context" path="/images/ContextAsset.gif"/>
     
 </page-specification>

Modified: jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/wml/Home.page
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/wml/Home.page?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/wml/Home.page (original)
+++ jakarta/tapestry/trunk/framework/src/test/org/apache/tapestry/junit/mock/wml/Home.page Thu Sep 22 17:37:56 2005
@@ -21,7 +21,7 @@
 
 <page-specification class="org.apache.tapestry.junit.mock.wml.Home">
 
-    <context-asset name="image" path="images/image.wbmp"/>
+    <context-asset name="image" path="/images/image.wbmp"/>
 
     <property-specification name="u" type="java.lang.String" persistent="yes" initial-value='"newbie"'/>
     <property-specification name="l" type="java.lang.String" persistent="yes" initial-value='"option_one"'/>

Modified: jakarta/tapestry/trunk/status.xml
URL: http://svn.apache.org/viewcvs/jakarta/tapestry/trunk/status.xml?rev=291051&r1=291050&r2=291051&view=diff
==============================================================================
--- jakarta/tapestry/trunk/status.xml (original)
+++ jakarta/tapestry/trunk/status.xml Thu Sep 22 17:37:56 2005
@@ -65,7 +65,8 @@
       <action type="fix" dev="DS" fixes-bug="TAPESTRY-485" due-to="Pierre-Yves Nicolas">Document Upload component</action>
       <action type="fix" dev="HLS" fixes-bug="TAPESTRY-660">Injecting meta data generates incorrect code for boolean properties</action>
       <action type="update" dev="HLS">Improve exception reporting of certain objects, including object arrays</action>
-      <action type="update" dev="HLS" fixes-bug="TAPESTRY-639">Expose the ServletContext as service tapestry.globals.ServletContext</action>
+      <action type="fix" dev="HLS" fixes-bug="TAPESTRY-639">Expose the ServletContext as service tapestry.globals.ServletContext</action>
+      <action type="fix" dev="HLS" fixes-bug="TAPESTRY-655">In some circumstances, using the classpath: or context: prefixes on paths fails to work</action>
     </release>
     <release version="4.0-beta-7" date="Sep 17 2005">
       <action type="fix" dev="HLS" fixes-bug="TAPESTRY-341">Need better line-precise reporting for listener method</action>



---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org