001    package org.chenillekit.tapestry.core.factories;
002    
003    import java.io.UnsupportedEncodingException;
004    import java.net.URLEncoder;
005    import java.util.Map;
006    
007    import org.apache.tapestry5.Asset;
008    import org.apache.tapestry5.internal.services.ResourceCache;
009    import org.apache.tapestry5.ioc.Resource;
010    import static org.apache.tapestry5.ioc.internal.util.CollectionFactory.newConcurrentMap;
011    import org.apache.tapestry5.services.AssetFactory;
012    
013    import org.chenillekit.core.resources.URIResource;
014    import org.chenillekit.tapestry.core.services.URIAssetAliasManager;
015    
016    /**
017     * @version $Id: URIAssetFactory.java 594 2009-12-05 15:17:26Z mlusetti $
018     */
019    public class URIAssetFactory implements AssetFactory
020    {
021            private final ResourceCache cache;
022    
023            private final URIAssetAliasManager aliasManager;
024    
025            private final Map<Resource, String> resourceToClientURL = newConcurrentMap();
026    
027            public URIAssetFactory(final ResourceCache cache,
028                                                       final URIAssetAliasManager aliasManager)
029            {
030                    this.cache = cache;
031                    this.aliasManager = aliasManager;
032            }
033    
034            /**
035             * Returns the Resource representing the root folder of the domain this factory is responsible for.
036             */
037            public Resource getRootResource()
038            {
039                    return new URIResource("/");
040            }
041    
042            private String clientURL(Resource resource)
043            {
044                    String clientURL = resourceToClientURL.get(resource);
045    
046                    if (clientURL == null)
047                    {
048                            clientURL = buildClientURL(resource);
049                            resourceToClientURL.put(resource, clientURL);
050                    }
051    
052                    // The path generated is partially request-dependent and therefore can't be cached, it will even
053                    // vary from request to the next.
054    
055                    return aliasManager.toClientURL(clientURL);
056            }
057    
058            private String buildClientURL(Resource resource)
059            {
060                    boolean requiresDigest = cache.requiresDigest(resource);
061    
062                    String path = null;
063    
064                    try
065                    {
066                            path = URLEncoder.encode(resource.getPath(), "UTF-8");
067                    }
068                    catch (UnsupportedEncodingException e)
069                    {
070                            throw new RuntimeException(e);
071                    }
072    
073                    if (requiresDigest)
074                    {
075                            // Resources with extensions go from foo/bar/baz.txt --> foo/bar/baz.CHECKSUM.txt
076    
077                            int lastdotx = path.lastIndexOf('.');
078    
079                            path = path.substring(0, lastdotx + 1) + cache.getDigest(resource) + path.substring(lastdotx);
080                    }
081    
082                    return path;
083            }
084    
085            public Asset createAsset(final Resource resource)
086            {
087                    return new Asset()
088                    {
089                            public Resource getResource()
090                            {
091                                    return resource;
092                            }
093    
094                            public String toClientURL()
095                            {
096                                    return clientURL(resource);
097                            }
098    
099                            @Override
100                            public String toString()
101                            {
102                                    return toClientURL();
103                            }
104                    };
105            }
106    }