Author: hlship
Date: Mon Apr 19 13:24:32 2010
New Revision: 935556
URL: http://svn.apache.org/viewvc?rev=935556&view=rev
Log:
Rework ClasspathAssetAliasManager to always require a mapping to an aliased
package folder
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImpl.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImplTest.java
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImpl.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImpl.java?rev=935556&r1=935555&r2=935556&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImpl.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImpl.java
Mon Apr 19 13:24:32 2010
@@ -4,7 +4,7 @@
// 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,
@@ -14,7 +14,12 @@
package org.apache.tapestry5.internal.services;
+import org.apache.tapestry5.SymbolConstants;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.ioc.annotations.Symbol;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.ioc.util.AvailableValues;
+import org.apache.tapestry5.ioc.util.UnknownValueException;
import org.apache.tapestry5.services.ClasspathAssetAliasManager;
import org.apache.tapestry5.services.Request;
@@ -27,6 +32,8 @@ public class ClasspathAssetAliasManagerI
{
private final Request request;
+ private final String assetPathPrefix;
+
/**
* Map from alias to path.
*/
@@ -44,17 +51,26 @@ public class ClasspathAssetAliasManagerI
/**
* Configuration is a map of aliases (short names) to complete names. Keys
and values should end with a slash, but
* one will be provided as necessary, so don't both.
+ *
+ * @param applicationVersion
+ * TODO
*/
public ClasspathAssetAliasManagerImpl(Request request,
- Map<String, String> configuration)
+ @Inject
+ @Symbol(SymbolConstants.APPLICATION_VERSION)
+ String applicationVersion,
+
+ Map<String, String> configuration)
{
this.request = request;
+ this.assetPathPrefix = RequestConstants.ASSET_PATH_PREFIX +
applicationVersion + "/";
+
for (Map.Entry<String, String> e : configuration.entrySet())
{
- String alias = withSlash(e.getKey());
- String path = withSlash(e.getValue());
+ String alias = withOutSlash(e.getKey());
+ String path = withOutSlash(e.getValue());
aliasToPathPrefix.put(alias, path);
pathPrefixToAlias.put(path, alias);
@@ -76,19 +92,18 @@ public class ClasspathAssetAliasManagerI
Collections.sort(sortedPathPrefixes, sortDescendingByLength);
}
- private String withSlash(String input)
+ private String withOutSlash(String input)
{
- if (input.equals("")) return input;
-
- if (input.endsWith("/")) return input;
+ if (input.endsWith("/"))
+ return input.substring(0, input.length() - 1);
- return input + "/";
+ return input;
}
public String toClientURL(String resourcePath)
{
StringBuilder builder = new StringBuilder(request.getContextPath());
- builder.append(RequestConstants.ASSET_PATH_PREFIX);
+ builder.append(assetPathPrefix);
for (String pathPrefix : sortedPathPrefixes)
{
@@ -96,29 +111,32 @@ public class ClasspathAssetAliasManagerI
{
String alias = pathPrefixToAlias.get(pathPrefix);
builder.append(alias);
- builder.append(resourcePath.substring(pathPrefix.length()));
+ builder.append("/");
+ builder.append(resourcePath.substring(pathPrefix.length() +
1));
return builder.toString();
}
}
- // No alias available as a prefix (kind of unlikely, but whatever).
+ // This is a minor misuse of the UnknownValueException but the
exception reporting
+ // is too useful to pass up.
- builder.append(resourcePath);
-
- return builder.toString();
+ throw new UnknownValueException(
+ String
+ .format(
+ "Unable to create a client URL for classpath
resource %s: The resource path was not within an aliased path.",
+ resourcePath), new AvailableValues("aliased
paths", aliasToPathPrefix.values()));
}
public String toResourcePath(String clientURL)
{
+ // Include the slash in the base path
+
String basePath =
clientURL.substring(RequestConstants.ASSET_PATH_PREFIX.length());
for (String alias : sortedAliases)
{
- if (basePath.startsWith(alias))
- {
- return aliasToPathPrefix.get(alias) +
basePath.substring(alias.length());
- }
+ if (basePath.startsWith(alias)) { return
aliasToPathPrefix.get(alias) + "/" + basePath.substring(alias.length() + 1); }
}
return basePath;
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java?rev=935556&r1=935555&r2=935556&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ClasspathAssetAliasManager.java
Mon Apr 19 13:24:32 2010
@@ -1,10 +1,10 @@
-// Copyright 2006, 2008 The Apache Software Foundation
+// Copyright 2006, 2008, 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,
@@ -17,12 +17,23 @@ package org.apache.tapestry5.services;
import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
/**
- * Used as part of the support for classpath {...@link
org.apache.tapestry5.Asset}s, to convert the Asset's {...@link
- * org.apache.tapestry5.ioc.Resource} to a URL that can be accessed by the
client. The asset path, within the
+ * Used as part of the support for classpath {...@link
org.apache.tapestry5.Asset}s, to convert the Asset's
+ * {...@link org.apache.tapestry5.ioc.Resource} to a URL that can be accessed
by the client. The asset path, within the
* classpath, is converted into a shorter virtual path (one that, typically,
includes some kind of version number).
* <p/>
* Service configuration is a map from aliases (short names) to complete
names. Names should not start or end end with a
- * slash.
+ * slash. Generally, an alias should be a single name (not contain a slash).
Paths should also not start or end with a
+ * slash. An example mapping would be <code>mylib</code> to
<code>com/example/mylib</code>.
+ * <p>
+ * As originally envisioned, this service would simply <em>optimize</em>
classpath assets, allowing the URL path for
+ * such assets to be shortened (and have a version number added, important for
caching); thus the word "alias" makes
+ * sense ... it was responsible for creating an "alias" URL shorter than the
default "classpath" URL.
+ * <p>
+ * Starting in Tapestry 5.2, this changed; all classpath assets
<strong>must</strong> be "aliased" to a shorter URL
+ * path. Any URL that can not be shortened is now rejected.
+ * <p>
+ * Tapestry automatically contributes a number of mappings: for the
application itself (as alias "app") and for each
+ * library (via {...@link ComponentClassResolver#getFolderToPackageMapping()});
*/
@UsesMappedConfiguration(String.class)
public interface ClasspathAssetAliasManager
@@ -30,8 +41,9 @@ public interface ClasspathAssetAliasMana
/**
* Takes a resource path to a classpath resource and adds the asset path
prefix to the path. May also convert part
* of the path to an alias (based on the manager's configuration).
- *
- * @param resourcePath resource path on the classpath (with no leading
slash)
+ *
+ * @param resourcePath
+ * resource path on the classpath (with no leading slash)
* @return URL ready to send to the client
*/
String toClientURL(String resourcePath);
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java?rev=935556&r1=935555&r2=935556&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/services/ComponentClassResolver.java
Mon Apr 19 13:24:32 2010
@@ -119,6 +119,7 @@ public interface ComponentClassResolver
* folder "example", then the package mapping for "example" will be
<code>com.example</code>.
*
* @since 5.2.0
+ * @see ClasspathAssetAliasManager
*/
Map<String, String> getFolderToPackageMapping();
}
Modified:
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImplTest.java
URL:
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImplTest.java?rev=935556&r1=935555&r2=935556&view=diff
==============================================================================
---
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImplTest.java
(original)
+++
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/ClasspathAssetAliasManagerImplTest.java
Mon Apr 19 13:24:32 2010
@@ -4,7 +4,7 @@
// 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,
@@ -15,6 +15,8 @@
package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.internal.test.InternalBaseTestCase;
+import org.apache.tapestry5.ioc.util.UnknownValueException;
+
import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newMap;
import org.apache.tapestry5.services.ClasspathAssetAliasManager;
import org.apache.tapestry5.services.Request;
@@ -25,6 +27,7 @@ import java.util.Map;
public class ClasspathAssetAliasManagerImplTest extends InternalBaseTestCase
{
+ private static final String APP_VERSION = "1.2.3";
public Map<String, String> configuration()
{
@@ -33,7 +36,6 @@ public class ClasspathAssetAliasManagerI
configuration.put("tapestry/4.0", "org/apache/tapestry5/");
configuration.put("tapestry-internal/3.0",
"org/apache/tapestry5/internal/");
configuration.put("mylib/2.0/", "com/example/mylib/");
- configuration.put("classpath/1.0", "");
return configuration;
}
@@ -47,10 +49,38 @@ public class ClasspathAssetAliasManagerI
replay();
- ClasspathAssetAliasManager manager = new
ClasspathAssetAliasManagerImpl(request, configuration());
+ ClasspathAssetAliasManager manager = new
ClasspathAssetAliasManagerImpl(request, APP_VERSION, configuration());
+
+ String expectedPath = "/ctx" + RequestConstants.ASSET_PATH_PREFIX +
APP_VERSION + "/" + expectedClientURL;
- assertEquals(manager.toClientURL(resourcePath),
- "/ctx" + RequestConstants.ASSET_PATH_PREFIX +
expectedClientURL);
+ assertEquals(manager.toClientURL(resourcePath), expectedPath);
+
+ verify();
+ }
+
+ @Test
+ public void failure_if_path_not_in_mapped_alias_folder()
+ {
+ Request request = mockRequest();
+
+ train_getContextPath(request, "");
+
+ replay();
+
+ ClasspathAssetAliasManager manager = new
ClasspathAssetAliasManagerImpl(request, APP_VERSION, configuration());
+
+ try
+ {
+ manager.toClientURL("org/example/icons/flag.gif");
+ unreachable();
+ }
+ catch (UnknownValueException ex)
+ {
+ assertMessageContains(ex, "Unable to create a client URL for
classpath resource org/example/icons/flag.gif");
+
+ assertListsEquals(ex.getAvailableValues().getValues(),
"com/example/mylib", "org/apache/tapestry5",
+ "org/apache/tapestry5/internal");
+ }
verify();
}
@@ -58,17 +88,18 @@ public class ClasspathAssetAliasManagerI
@DataProvider
public Object[][] to_client_url_data()
{
- return new Object[][] { { "foo/bar/Baz.txt",
"classpath/1.0/foo/bar/Baz.txt" },
- { "com/example/mylib/Foo.bar", "mylib/2.0/Foo.bar" },
- { "com/example/mylib/nested/Foo.bar",
"mylib/2.0/nested/Foo.bar" },
- { "org/apache/tapestry5/internal/Foo.bar",
"tapestry-internal/3.0/Foo.bar" },
- { "org/apache/tapestry5/Foo.bar", "tapestry/4.0/Foo.bar" }, };
+ return new Object[][]
+ {
+ { "com/example/mylib/Foo.bar", "mylib/2.0/Foo.bar" },
+ { "com/example/mylib/nested/Foo.bar", "mylib/2.0/nested/Foo.bar" },
+ { "org/apache/tapestry5/internal/Foo.bar",
"tapestry-internal/3.0/Foo.bar" },
+ { "org/apache/tapestry5/Foo.bar", "tapestry/4.0/Foo.bar" }, };
}
@Test(dataProvider = "to_resource_path_data")
public void to_resource_path(String clientURL, String expectedResourcePath)
{
- ClasspathAssetAliasManager manager = new
ClasspathAssetAliasManagerImpl(null, configuration());
+ ClasspathAssetAliasManager manager = new
ClasspathAssetAliasManagerImpl(null, APP_VERSION, configuration());
assertEquals(manager.toResourcePath(clientURL), expectedResourcePath);
}