001    // Copyright 2005 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.asset;
016    
017    import org.apache.hivemind.Location;
018    import org.apache.hivemind.Resource;
019    import org.apache.hivemind.util.Defense;
020    import org.apache.tapestry.IAsset;
021    import org.apache.tapestry.spec.IComponentSpecification;
022    
023    import java.util.*;
024    
025    /**
026     * Implementation of the {@link org.apache.tapestry.asset.AssetSource} service interface.
027     * 
028     */
029    public class AssetSourceImpl implements AssetSource
030    {
031        private Map _assetFactoryByPrefix = new HashMap();
032    
033        private List _contributions;
034    
035        private AssetFactory _defaultAssetFactory;
036    
037        private AssetFactory _lookupAssetFactory;
038    
039        private AssetFactory _classpathAssetFactory;
040    
041        private AssetFactory _contextAssetFactory;
042    
043        public void initializeService()
044        {
045            Iterator i = _contributions.iterator();
046            while (i.hasNext())
047            {
048                AssetFactoryContribution c = (AssetFactoryContribution) i.next();
049    
050                _assetFactoryByPrefix.put(c.getPrefix(), c.getFactory());
051            }
052        }
053    
054        public IAsset findAsset(Resource base, String path, Locale locale, Location location)
055        {
056            return findAsset(base, null, path, locale, location);
057        }
058    
059        public IAsset findAsset(Resource base, IComponentSpecification spec, String path, Locale locale, Location location)
060        {
061            Defense.notNull(path, "path");
062            Defense.notNull(location, "location");
063    
064            int colonx = path.indexOf(':');
065            
066            String prefix = colonx > -1 ? path.substring(0, colonx) : null;
067            String truePath = colonx > -1 ? path.substring(colonx + 1) : path;
068    
069            AssetFactory factory = null;
070    
071            if (prefix != null) {
072    
073                factory = (AssetFactory) _assetFactoryByPrefix.get(prefix);
074            }
075    
076            // now we have to search
077            
078            if (factory == null && prefix == null) {
079                
080                factory = findAssetFactory(spec, base, truePath, locale);
081            }
082            
083            // Unknown prefix is expected to happen when an external asset (using an established
084            // prefix such as http:) is referenced.
085    
086            if (factory == null)
087            {
088                factory = _defaultAssetFactory;
089    
090                // Path is the full path, including the prefix (which is really the scheme
091                // of the URL).
092    
093                truePath = path;
094            }
095            
096            if (truePath.startsWith("/"))
097                return factory.createAbsoluteAsset(truePath, locale, location);
098    
099            // This can happen when a 3.0 DTD is read in
100    
101            return factory.createAsset(base, spec, truePath, locale, location);
102        }
103    
104        AssetFactory findAssetFactory(IComponentSpecification spec, Resource baseResource, String path, Locale locale)
105        {
106            // need to check these two core factories in order first
107    
108            if (_classpathAssetFactory.assetExists(spec, baseResource, path, locale))
109                return _classpathAssetFactory;
110    
111            if (_contextAssetFactory.assetExists(spec, baseResource, path, locale))
112                return _contextAssetFactory;
113            
114            for (int i=0; i < _contributions.size(); i++) {
115    
116                AssetFactoryContribution c = (AssetFactoryContribution)_contributions.get(i);
117    
118                if (c.getFactory().assetExists(spec, baseResource, path, locale))
119                    return c.getFactory();
120            }
121    
122            return null;
123        }
124    
125        /**
126         * Factory used when the path has no prefix, and the type of asset must be inferred from the
127         * type of resource.
128         */
129    
130        public void setLookupAssetFactory(AssetFactory lookupAssetFactory)
131        {
132            _lookupAssetFactory = lookupAssetFactory;
133        }
134    
135        /**
136         * List of {@link org.apache.tapestry.asset.AssetFactoryContribution}.
137         */
138    
139        public void setContributions(List contributions)
140        {
141            _contributions = contributions;
142        }
143    
144        /**
145         * Factory used when an unrecognized prefix (typically, an arbitrary URL's scheme) is provided.
146         */
147    
148        public void setDefaultAssetFactory(AssetFactory defaultAssetFactory)
149        {
150            _defaultAssetFactory = defaultAssetFactory;
151        }
152    
153        public void setClasspathAssetFactory(AssetFactory classpathAssetFactory)
154        {
155            _classpathAssetFactory = classpathAssetFactory;
156        }
157    
158        public void setContextAssetFactory(AssetFactory contextAssetFactory)
159        {
160            _contextAssetFactory = contextAssetFactory;
161        }
162    }