    001    // Copyright 2011, 2012 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.assets;
    016
    017    import org.apache.tapestry5.SymbolConstants;
    018    import org.apache.tapestry5.internal.event.InvalidationEventHubImpl;
    019    import org.apache.tapestry5.ioc.Resource;
    020    import org.apache.tapestry5.ioc.annotations.PostInjection;
    021    import org.apache.tapestry5.ioc.annotations.Symbol;
    022    import org.apache.tapestry5.ioc.internal.util.URLChangeTracker;
    023    import org.apache.tapestry5.ioc.services.ClasspathURLConverter;
    024    import org.apache.tapestry5.services.UpdateListener;
    025    import org.apache.tapestry5.services.UpdateListenerHub;
    026
    027    public class ResourceChangeTrackerImpl extends InvalidationEventHubImpl implements ResourceChangeTracker,
    028            UpdateListener
    029    {
    030        private final URLChangeTracker tracker;
    031
    032        /**
    033         * Used in production mode as the last modified time of any resource exposed to the client. Remember that
    034         * all exposed assets include a URL with a version number, and each new deployment of the application should change
    035         * that version number.
    036         */
    037        private final long fixedLastModifiedTime = Math.round(System.currentTimeMillis() / 1000d) * 1000L;
    038
    039        public ResourceChangeTrackerImpl(ClasspathURLConverter classpathURLConverter,
    040                                         @Symbol(SymbolConstants.PRODUCTION_MODE)
    041                                         boolean productionMode)
    042        {
    043            super(productionMode);
    044
    045            // Use granularity of seconds (not milliseconds) since that works properly
    046            // with response headers for identifying last modified. Don't track
    047            // folder changes, just changes to actual files.
    048            tracker = productionMode ? null : new URLChangeTracker(classpathURLConverter, true, false);
    049        }
    050
    051        @PostInjection
    052        public void registerWithUpdateListenerHub(UpdateListenerHub hub)
    053        {
    054            hub.addUpdateListener(this);
    055        }
    056
    057        public long trackResource(Resource resource)
    058        {
    059            if (tracker == null)
    060            {
    061                return fixedLastModifiedTime;
    062            }
    063
    064            return tracker.add(resource.toURL());
    065        }
    066
    067        public void addDependency(Resource dependency)
    068        {
    069            trackResource(dependency);
    070        }
    071
    072        public void checkForUpdates()
    073        {
    074            if (tracker.containsChanges())
    075            {
    076                fireInvalidationEvent();
    077                tracker.clear();
    078            }
    079        }
    080
    081    }