001: // Copyright 2006, 2007 The Apache Software Foundation
002: //
003: // Licensed under the Apache License, Version 2.0 (the "License");
004: // you may not use this file except in compliance with the License.
005: // You may obtain a copy of the License at
006: //
007: // http://www.apache.org/licenses/LICENSE-2.0
008: //
009: // Unless required by applicable law or agreed to in writing, software
010: // distributed under the License is distributed on an "AS IS" BASIS,
011: // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012: // See the License for the specific language governing permissions and
013: // limitations under the License.
014:
015: package org.apache.tapestry.internal.services;
016:
017: import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newConcurrentMap;
018:
019: import java.util.Map;
020:
021: import org.apache.tapestry.Asset;
022: import org.apache.tapestry.internal.events.InvalidationListener;
023: import org.apache.tapestry.ioc.Resource;
024: import org.apache.tapestry.ioc.internal.util.ClasspathResource;
025: import org.apache.tapestry.services.AssetFactory;
026: import org.apache.tapestry.services.ClasspathAssetAliasManager;
027:
028: /**
029: * Generates Assets for files on the classpath. Caches generated client URLs internally, and clears
030: * that cache when notified to do so by the {@link ResourceCache}.
031: *
032: * @see AssetDispatcher
033: */
034: public class ClasspathAssetFactory implements AssetFactory,
035: InvalidationListener {
036: private final ResourceCache _cache;
037:
038: private final ClasspathAssetAliasManager _aliasManager;
039:
040: private final Map<Resource, String> _resourceToClientURL = newConcurrentMap();
041:
042: public ClasspathAssetFactory(final ResourceCache cache,
043: final ClasspathAssetAliasManager aliasManager) {
044: _cache = cache;
045: _aliasManager = aliasManager;
046: }
047:
048: public void objectWasInvalidated() {
049: _resourceToClientURL.clear();
050: }
051:
052: private String clientURL(Resource resource) {
053: String clientURL = _resourceToClientURL.get(resource);
054:
055: if (clientURL == null) {
056: clientURL = buildClientURL(resource);
057: _resourceToClientURL.put(resource, clientURL);
058: }
059:
060: return clientURL;
061: }
062:
063: private String buildClientURL(Resource resource) {
064: boolean requiresDigest = _cache.requiresDigest(resource);
065:
066: String path = resource.getPath();
067:
068: if (requiresDigest) {
069: // Resources with extensions go from foo/bar/baz.txt --> foo/bar/baz.CHECKSUM.txt
070:
071: int lastdotx = path.lastIndexOf('.');
072:
073: String revisedPath = path.substring(0, lastdotx + 1)
074: + _cache.getDigest(resource)
075: + path.substring(lastdotx);
076:
077: return _aliasManager.toClientURL(revisedPath);
078: }
079:
080: return _aliasManager.toClientURL(path);
081: }
082:
083: public Asset createAsset(final Resource resource) {
084: // TODO: Assets will eventually have a kind of symbolic link used
085: // to shorten the path. Some assets may need to have a checksum embedded
086: // in the path as well.
087:
088: return new Asset() {
089: public Resource getResource() {
090: return resource;
091: }
092:
093: public String toClientURL() {
094: return clientURL(resource);
095: }
096:
097: @Override
098: public String toString() {
099: return toClientURL();
100: }
101: };
102: }
103:
104: public Resource getRootResource() {
105: return new ClasspathResource("");
106: }
107:
108: }
|