001 // Copyright 2006, 2007, 2008, 2009, 2011 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.tapestry5.internal.services;
016
017 import java.net.URL;
018 import java.util.Map;
019
020 import org.apache.tapestry5.internal.services.assets.ResourceChangeTracker;
021 import org.apache.tapestry5.ioc.Resource;
022 import org.apache.tapestry5.ioc.annotations.PostInjection;
023 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
024 import org.apache.tapestry5.services.InvalidationListener;
025 import org.apache.tapestry5.services.ResourceDigestGenerator;
026
027 public class ResourceDigestManagerImpl implements ResourceDigestManager, InvalidationListener
028 {
029 private final ResourceDigestGenerator digestGenerator;
030
031 private final ResourceChangeTracker resourceChangeTracker;
032
033 private final Map<Resource, Cached> cache = CollectionFactory.newConcurrentMap();
034
035 final static long MISSING_RESOURCE_TIME_MODIFIED = -1L;
036
037 private class Cached
038 {
039 final boolean requiresDigest;
040
041 final String digest;
042
043 final long timeModified;
044
045 Cached(Resource resource)
046 {
047 requiresDigest = digestGenerator.requiresDigest(resource.getPath());
048
049 URL url = resource.toURL();
050
051 digest = (requiresDigest && url != null) ? digestGenerator.generateDigest(url) : null;
052
053 timeModified = url != null ? resourceChangeTracker.trackResource(resource) : MISSING_RESOURCE_TIME_MODIFIED;
054 }
055 }
056
057 public ResourceDigestManagerImpl(ResourceDigestGenerator digestGenerator,
058 ResourceChangeTracker resourceChangeTracker)
059 {
060 this.digestGenerator = digestGenerator;
061 this.resourceChangeTracker = resourceChangeTracker;
062 }
063
064 @PostInjection
065 public void listenForInvalidations()
066 {
067 resourceChangeTracker.addInvalidationListener(this);
068 }
069
070 private Cached get(Resource resource)
071 {
072 Cached result = cache.get(resource);
073
074 if (result == null)
075 {
076 result = new Cached(resource);
077 cache.put(resource, result);
078 }
079
080 return result;
081 }
082
083 public String getDigest(Resource resource)
084 {
085 return get(resource).digest;
086 }
087
088 public long getTimeModified(Resource resource)
089 {
090 return get(resource).timeModified;
091 }
092
093 public boolean requiresDigest(Resource resource)
094 {
095 return get(resource).requiresDigest;
096 }
097
098 public void addInvalidationListener(InvalidationListener listener)
099 {
100 resourceChangeTracker.addInvalidationListener(listener);
101 }
102
103 public void objectWasInvalidated()
104 {
105 cache.clear();
106 }
107
108 }