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 2013/03/15 00:09:18 UTC
[12/14] git commit: Properly handle resource changes - Invalidate
more caches - Recompute clientURL of Assets that are not discarded
Properly handle resource changes
- Invalidate more caches
- Recompute clientURL of Assets that are not discarded
Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/58ad2241
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/58ad2241
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/58ad2241
Branch: refs/heads/master
Commit: 58ad22413e7a7cacc94dd2a608bad7398010691b
Parents: 6709278
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Thu Mar 14 16:01:53 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Thu Mar 14 16:01:53 2013 -0700
----------------------------------------------------------------------
.../src/main/java/org/apache/tapestry5/Asset.java | 10 ++-
.../internal/services/AbstractAssetFactory.java | 31 +++++++++
.../internal/services/AssetSourceImpl.java | 9 ++-
.../internal/services/ClasspathAssetFactory.java | 25 ++++---
.../internal/services/ContextAssetFactory.java | 51 +++++++++-----
.../internal/services/PageSourceImpl.java | 10 +++-
.../internal/services/RequestPageCacheImpl.java | 6 +-
.../assets/AssetChecksumGeneratorImpl.java | 19 +++++-
.../apache/tapestry5/services/AssetFactory.java | 17 ++++-
.../services/javascript/StylesheetLink.java | 33 +++++++--
10 files changed, 160 insertions(+), 51 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java b/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
index 5ba36fe..b2c76ac 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/Asset.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2008, 2009 The Apache Software Foundation
+// Copyright 2006, 2008, 2009, 2013 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.
@@ -34,10 +34,14 @@ public interface Asset
* Returns a URL that can be passed, unchanged, to the client in order for it to access the resource. The same value
* is returned from <code>toString()</code>.
* <p/>
- * Tapestry's built-in asset types (context and classpath) always incorporate a version number as part of the path,
+ * Tapestry's built-in asset types (context and classpath) always incorporate a checksum as part of the path,
* and alternate implementations are encouraged to do so as well. In addition, Tapestry ensures that context and
* classpath assets have a far-future expires header (to ensure aggressive caching by the client).
- * <p/>
+ * <p/>Note that starting in Tapestry 5.4, it is expected that Asset instances recognize
+ * when the underlying Resource's content has changed, and update the clientURL to reflect the new content's
+ * checksum. This wasn't an issue in earlier releases where the clientURL incorporated a version number.
+ *
+ * @see org.apache.tapestry5.services.AssetSource
*/
String toClientURL();
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAssetFactory.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAssetFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAssetFactory.java
new file mode 100644
index 0000000..7caff2c
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AbstractAssetFactory.java
@@ -0,0 +1,31 @@
+// Copyright 2013 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;
+
+import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
+import org.apache.tapestry5.internal.util.RecomputableSupport;
+import org.apache.tapestry5.ioc.annotations.PostInjection;
+import org.apache.tapestry5.services.AssetFactory;
+
+public abstract class AbstractAssetFactory implements AssetFactory
+{
+ protected final RecomputableSupport recomputable = new RecomputableSupport();
+
+ @PostInjection
+ public void updateVersionNumberOnResourceChange(ResourceChangeTracker tracker)
+ {
+ recomputable.initialize(tracker);
+ }
+}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
index b22cbbf..0994ff5 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/AssetSourceImpl.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 The Apache Software Foundation
+// Copyright 2006-2013 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.
@@ -18,7 +18,9 @@ import org.apache.tapestry5.Asset;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.internal.AssetConstants;
import org.apache.tapestry5.internal.TapestryInternalUtils;
+import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.annotations.PostInjection;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.internal.util.LockSupport;
@@ -77,6 +79,11 @@ public class AssetSourceImpl extends LockSupport implements AssetSource
registry = StrategyRegistry.newInstance(AssetFactory.class, byResourceClass);
}
+ @PostInjection
+ public void clearCacheWhenResourcesChange(ResourceChangeTracker tracker) {
+ tracker.clearOnInvalidation(cache);
+ }
+
public Asset getClasspathAsset(String path)
{
return getClasspathAsset(path, null);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
index 46c02fc..0173058 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ClasspathAssetFactory.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2011, 2013 The Apache Software Foundation
+// Copyright 2006-2013 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,10 +15,10 @@
package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.ioc.Invokable;
import org.apache.tapestry5.ioc.Resource;
import org.apache.tapestry5.ioc.annotations.Marker;
import org.apache.tapestry5.ioc.internal.util.ClasspathResource;
-import org.apache.tapestry5.services.AssetFactory;
import org.apache.tapestry5.services.AssetPathConverter;
import org.apache.tapestry5.services.ClasspathAssetAliasManager;
import org.apache.tapestry5.services.ClasspathProvider;
@@ -29,7 +29,7 @@ import org.apache.tapestry5.services.ClasspathProvider;
* @see AssetDispatcher
*/
@Marker(ClasspathProvider.class)
-public class ClasspathAssetFactory implements AssetFactory
+public class ClasspathAssetFactory extends AbstractAssetFactory
{
private final ClasspathAssetAliasManager aliasManager;
@@ -86,13 +86,21 @@ public class ClasspathAssetFactory implements AssetFactory
}
/**
- * An invariant asset is normal, and only needs to compute the clientURL for the resource once.
+ * An invariant asset is normal, and only needs to compute the clientURL for the resource once (
+ * or when the underlying Resource's content has changed).
*/
private Asset createInvariantAsset(final Resource resource)
{
return new AbstractAsset(true)
{
- private String clientURL;
+ private final Invokable<String> clientURL = recomputable.create(new Invokable<String>()
+ {
+ @Override
+ public String invoke()
+ {
+ return clientURL(resource);
+ }
+ });
public Resource getResource()
{
@@ -101,12 +109,7 @@ public class ClasspathAssetFactory implements AssetFactory
public String toClientURL()
{
- if (clientURL == null)
- {
- clientURL = clientURL(resource);
- }
-
- return clientURL;
+ return clientURL.invoke();
}
};
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
index bd6c6b3..32d63f7 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/ContextAssetFactory.java
@@ -15,6 +15,7 @@
package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.Asset;
+import org.apache.tapestry5.ioc.Invokable;
import org.apache.tapestry5.ioc.Resource;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.services.AssetFactory;
@@ -29,7 +30,7 @@ import java.io.IOException;
*
* @see org.apache.tapestry5.internal.services.ContextResource
*/
-public class ContextAssetFactory implements AssetFactory
+public class ContextAssetFactory extends AbstractAssetFactory
{
private final AssetPathConstructor assetPathConstructor;
@@ -52,16 +53,19 @@ public class ContextAssetFactory implements AssetFactory
public Asset createAsset(Resource resource)
{
- try
+ if (invariant)
{
- String defaultPath = assetPathConstructor.constructAssetPath(RequestConstants.CONTEXT_FOLDER, resource.getPath(), resource);
+ return createInvariantAsset(resource);
+ }
- if (invariant)
- {
- return createInvariantAsset(resource, defaultPath);
- }
+ return createVariantAsset(resource);
+ }
- return createVariantAsset(resource, defaultPath);
+ private String defaultPath(Resource resource)
+ {
+ try
+ {
+ return assetPathConstructor.constructAssetPath(RequestConstants.CONTEXT_FOLDER, resource.getPath(), resource);
} catch (IOException ex)
{
throw new RuntimeException(String.format("Unable to construct asset path for %s: %s",
@@ -69,11 +73,18 @@ public class ContextAssetFactory implements AssetFactory
}
}
- private Asset createInvariantAsset(final Resource resource, final String defaultPath)
+ private Asset createInvariantAsset(final Resource resource)
{
return new AbstractAsset(true)
{
- private String clientURL;
+ private final Invokable<String> clientURL = recomputable.create(new Invokable<String>()
+ {
+ @Override
+ public String invoke()
+ {
+ return converter.convertAssetPath(defaultPath(resource));
+ }
+ });
public Resource getResource()
{
@@ -82,20 +93,24 @@ public class ContextAssetFactory implements AssetFactory
public String toClientURL()
{
- if (clientURL == null)
- {
- clientURL = converter.convertAssetPath(defaultPath);
- }
-
- return clientURL;
+ return clientURL.invoke();
}
};
}
- private Asset createVariantAsset(final Resource resource, final String defaultPath)
+ private Asset createVariantAsset(final Resource resource)
{
return new AbstractAsset(false)
{
+ private final Invokable<String> defaultPath = recomputable.create(new Invokable<String>()
+ {
+ @Override
+ public String invoke()
+ {
+ return defaultPath(resource);
+ }
+ });
+
public Resource getResource()
{
return resource;
@@ -103,7 +118,7 @@ public class ContextAssetFactory implements AssetFactory
public String toClientURL()
{
- return converter.convertAssetPath(defaultPath);
+ return converter.convertAssetPath(defaultPath.invoke());
}
};
}
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
index 066e154..09afc4f 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PageSourceImpl.java
@@ -16,6 +16,7 @@ package org.apache.tapestry5.internal.services;
import org.apache.tapestry5.func.F;
import org.apache.tapestry5.func.Mapper;
+import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
import org.apache.tapestry5.internal.structure.Page;
import org.apache.tapestry5.ioc.annotations.PostInjection;
import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
@@ -111,11 +112,18 @@ public class PageSourceImpl implements PageSource
@PostInjection
public void setupInvalidation(@ComponentClasses InvalidationEventHub classesHub,
@ComponentTemplates InvalidationEventHub templatesHub,
- @ComponentMessages InvalidationEventHub messagesHub)
+ @ComponentMessages InvalidationEventHub messagesHub,
+ ResourceChangeTracker resourceChangeTracker)
{
classesHub.clearOnInvalidation(pageCache);
templatesHub.clearOnInvalidation(pageCache);
messagesHub.clearOnInvalidation(pageCache);
+
+ // Because Assets can be injected into pages, and Assets are invalidated when
+ // an Asset's value is changed (partly due to the change, in 5.4, to include the asset's
+ // checksum as part of the asset URL), then when we notice a change to
+ // any Resource, it is necessary to discard all page instances.
+ resourceChangeTracker.clearOnInvalidation(pageCache);
}
public void clearCache()
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java
index aa663da..5fb378c 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/RequestPageCacheImpl.java
@@ -34,7 +34,7 @@ import java.util.Map;
* @since 5.2
*/
@Scope(ScopeConstants.PERTHREAD)
-public class RequestPageCacheImpl implements RequestPageCache, ThreadCleanupListener
+public class RequestPageCacheImpl implements RequestPageCache, Runnable
{
private final Logger logger;
@@ -54,10 +54,10 @@ public class RequestPageCacheImpl implements RequestPageCache, ThreadCleanupList
@PostInjection
public void listenForThreadCleanup(PerthreadManager perthreadManager)
{
- perthreadManager.addThreadCleanupListener(this);
+ perthreadManager.addThreadCleanupCallback(this);
}
- public void threadDidCleanup()
+ public void run()
{
for (Page page : cache.values())
{
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetChecksumGeneratorImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetChecksumGeneratorImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetChecksumGeneratorImpl.java
index eaf7464..5fcbaf0 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetChecksumGeneratorImpl.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/assets/AssetChecksumGeneratorImpl.java
@@ -16,6 +16,7 @@ package org.apache.tapestry5.internal.services.assets;
import org.apache.commons.codec.binary.Hex;
import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.services.assets.AssetChecksumGenerator;
import org.apache.tapestry5.services.assets.StreamableResource;
@@ -25,6 +26,7 @@ import org.apache.tapestry5.services.assets.StreamableResourceSource;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
+import java.util.Map;
public class AssetChecksumGeneratorImpl implements AssetChecksumGenerator
{
@@ -34,16 +36,18 @@ public class AssetChecksumGeneratorImpl implements AssetChecksumGenerator
private final ResourceChangeTracker tracker;
+ private final Map<StreamableResource, String> cache = CollectionFactory.newConcurrentMap();
+
public AssetChecksumGeneratorImpl(StreamableResourceSource streamableResourceSource, ResourceChangeTracker tracker)
{
this.streamableResourceSource = streamableResourceSource;
this.tracker = tracker;
+
+ tracker.clearOnInvalidation(cache);
}
public String generateChecksum(Resource resource) throws IOException
{
- // TODO: Caching, and cache invalidation.
-
StreamableResource streamable = streamableResourceSource.getStreamableResource(resource, StreamableResourceProcessing.COMPRESSION_DISABLED,
tracker);
@@ -53,7 +57,16 @@ public class AssetChecksumGeneratorImpl implements AssetChecksumGenerator
@Override
public String generateChecksum(StreamableResource resource) throws IOException
{
- return toChecksum(resource.openStream());
+ String result = cache.get(resource);
+
+ if (result == null)
+ {
+ result = toChecksum(resource.openStream());
+
+ cache.put(resource, result);
+ }
+
+ return result;
}
private String toChecksum(InputStream is) throws IOException
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetFactory.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetFactory.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetFactory.java
index 66fd272..a06dc5a 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetFactory.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/AssetFactory.java
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2013 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.
@@ -19,6 +19,16 @@ import org.apache.tapestry5.ioc.Resource;
/**
* Used by {@link AssetSource} to create new {@link Asset}s as needed.
+ * <p/>
+ * Starting in Tapestry 5.4, the built-in implementations of this interface (for context assets, and for classpath assets)
+ * were changed so that when underlying resources changed, the client URLs for Assets are discarded; this is necessitated by two factors:
+ * <p/>1) the {@linkplain org.apache.tapestry5.Asset#toClientURL() client URL}
+ * for an Asset now includes a checksum based on the content of the underlying resource, so a change to resource content
+ * (during development) results in a change to the URL.
+ * <p/>2) {@link org.apache.tapestry5.services.javascript.JavaScriptStack} (especially the {@link org.apache.tapestry5.services.javascript.ExtensibleJavaScriptStack} implementation)
+ * made no provision for rebuilding the Assets post-construction, and there is no backwards compatible way to
+ * introduce this concept (and JavaScriptStacks are something many applications and third-party libraries make use of).
+ * <p/>So, starting in Tapestry 5.4, the implementations of {@link Asset} should be
*
* @see org.apache.tapestry5.services.AssetSource
*/
@@ -33,8 +43,9 @@ public interface AssetFactory
* Creates an instance of an asset. Starting with 5.1.0.0, it is preferred (but not required) that the factory
* return an instance of {@link org.apache.tapestry5.Asset2}.
*
- * @param resource a resource within this factories domain (derived from the {@linkplain #getRootResource() root
- * resource})
+ * @param resource
+ * a resource within this factories domain (derived from the {@linkplain #getRootResource() root
+ * resource})
* @return an Asset for the resource
*/
Asset createAsset(Resource resource);
http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/58ad2241/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StylesheetLink.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StylesheetLink.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StylesheetLink.java
index 0884e8d..2f6d66a 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StylesheetLink.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/javascript/StylesheetLink.java
@@ -31,6 +31,8 @@ import org.apache.tapestry5.ioc.internal.util.InternalUtils;
*/
public final class StylesheetLink
{
+ private final Asset asset;
+
private final String url;
private final StylesheetOptions options;
@@ -39,29 +41,39 @@ public final class StylesheetLink
public StylesheetLink(Asset asset)
{
- this(asset, null);
+ this(asset, null, null);
}
public StylesheetLink(Asset asset, StylesheetOptions options)
{
- this(asset.toClientURL(), options);
+ this(asset, null, options);
}
public StylesheetLink(String url)
{
- this(url, null);
+ this(null, url, null);
}
public StylesheetLink(String url, StylesheetOptions options)
{
- assert InternalUtils.isNonBlank(url);
+ this(null, url, options);
+ }
+
+ private StylesheetLink(Asset asset, String url, StylesheetOptions options)
+ {
+ assert asset != null || InternalUtils.isNonBlank(url);
+
+ this.asset = asset;
this.url = url;
this.options = options != null ? options : BLANK_OPTIONS;
}
public String getURL()
{
- return url;
+ // Only one of asset or url will be non-null.
+ // Starting in 5.4, we keep the asset around and ask it for its clientURL; this is because
+ // clientURLs can change if the content of the underlying Resource changes.
+ return asset != null ? asset.toClientURL() : url;
}
/**
@@ -76,7 +88,8 @@ public final class StylesheetLink
/**
* Invoked to add the stylesheet link to a container element.
*
- * @param container to add the new element to
+ * @param container
+ * to add the new element to
*/
public void add(Element container)
{
@@ -90,7 +103,11 @@ public final class StylesheetLink
String rel = options.ajaxInsertionPoint ? "stylesheet t-ajax-insertion-point" : "stylesheet";
- container.element("link", "href", url, "rel", rel, "type", "text/css", "media", options.media);
+ container.element("link",
+ "href", getURL(),
+ "rel", rel,
+ "type", "text/css",
+ "media", options.media);
if (hasCondition)
{
@@ -115,7 +132,7 @@ public final class StylesheetLink
StylesheetLink ssl = (StylesheetLink) obj;
- return TapestryInternalUtils.isEqual(url, ssl.url) && TapestryInternalUtils.isEqual(options, ssl.options);
+ return TapestryInternalUtils.isEqual(getURL(), ssl.getURL()) && TapestryInternalUtils.isEqual(options, ssl.options);
}
}