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: import static org.apache.tapestry.ioc.internal.util.CollectionFactory.newMap;
019: import static org.apache.tapestry.ioc.internal.util.Defense.notBlank;
020:
021: import java.util.Locale;
022: import java.util.Map;
023:
024: import org.apache.tapestry.Asset;
025: import org.apache.tapestry.ioc.Resource;
026: import org.apache.tapestry.ioc.services.ThreadLocale;
027: import org.apache.tapestry.ioc.util.StrategyRegistry;
028: import org.apache.tapestry.services.AssetFactory;
029: import org.apache.tapestry.services.AssetSource;
030:
031: public class AssetSourceImpl implements AssetSource {
032: private static final String CLASSPATH = "classpath";
033:
034: private final StrategyRegistry<AssetFactory> _registry;
035:
036: private final ThreadLocale _threadLocale;
037:
038: private final Map<String, Resource> _prefixToRootResource = newMap();
039:
040: private final Map<Resource, Asset> _cache = newConcurrentMap();
041:
042: public AssetSourceImpl(ThreadLocale threadLocale,
043:
044: Map<String, AssetFactory> configuration) {
045: _threadLocale = threadLocale;
046:
047: Map<Class, AssetFactory> byResourceClass = newMap();
048:
049: for (Map.Entry<String, AssetFactory> e : configuration
050: .entrySet()) {
051: String prefix = e.getKey();
052: AssetFactory factory = e.getValue();
053:
054: Resource rootResource = factory.getRootResource();
055:
056: byResourceClass.put(rootResource.getClass(), factory);
057:
058: _prefixToRootResource.put(prefix, rootResource);
059: }
060:
061: _registry = StrategyRegistry.newInstance(AssetFactory.class,
062: byResourceClass);
063: }
064:
065: public Asset getClasspathAsset(String path) {
066: return getClasspathAsset(path, null);
067: }
068:
069: public Asset getClasspathAsset(String path, Locale locale) {
070: return findAsset(null, path, locale);
071: }
072:
073: public Asset findAsset(Resource baseResource, String path,
074: Locale locale) {
075: notBlank(path, "path");
076:
077: if (baseResource == null)
078: baseResource = _prefixToRootResource.get(CLASSPATH);
079:
080: if (locale == null)
081: locale = _threadLocale.getLocale();
082:
083: int colonx = path.indexOf(':');
084:
085: if (colonx < 0)
086: return findRelativeAsset(baseResource, path, locale);
087:
088: String prefix = path.substring(0, colonx);
089:
090: Resource rootResource = _prefixToRootResource.get(prefix);
091:
092: if (rootResource == null)
093: throw new IllegalArgumentException(ServicesMessages
094: .unknownAssetPrefix(path));
095:
096: return findRelativeAsset(rootResource, path
097: .substring(colonx + 1), locale);
098: }
099:
100: private Asset findRelativeAsset(Resource baseResource, String path,
101: Locale locale) {
102: Resource unlocalized = baseResource.forFile(path);
103: Resource localized = unlocalized.forLocale(locale);
104:
105: if (localized == null)
106: throw new RuntimeException(ServicesMessages
107: .assetDoesNotExist(unlocalized));
108:
109: return getAssetForResource(localized);
110: }
111:
112: private Asset getAssetForResource(Resource resource) {
113: Asset result = _cache.get(resource);
114:
115: if (result == null) {
116: result = createAssetFromResource(resource);
117: _cache.put(resource, result);
118: }
119:
120: return result;
121: }
122:
123: private Asset createAssetFromResource(Resource resource) {
124: // The class of the resource is derived from the class of the base resource.
125: // So we can then use the class of the resource as a key to locate the correct asset
126: // factory.
127:
128: Class resourceClass = resource.getClass();
129:
130: AssetFactory factory = _registry.get(resourceClass);
131:
132: return factory.createAsset(resource);
133: }
134:
135: }
|