001    package org.apache.fulcrum.cache;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    /**
023     * The idea of the RefreshableCachedObject is that, rather than removing items
024     * from the cache when they become stale, we'll tell them to refresh themselves
025     * instead. That way they'll always be in the cache, and the code to refresh
026     * them will be run by the background thread rather than by a user request
027     * thread. You can also set a TTL (Time To Live) for the object. This way, if
028     * the object hasn't been touched for the TTL period, then it will be removed
029     * from the cache.
030     * 
031     * This extends CachedObject and provides a method for refreshing the cached
032     * object, and resetting its expire time.
033     * 
034     * @author <a href="mailto:nissim@nksystems.com">Nissim Karpenstein</a>
035     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
036     * @version $Id: RefreshableCachedObject.java 670326 2008-06-22 09:31:47Z tv $
037     */
038    public class RefreshableCachedObject extends CachedObject
039    {
040    
041        /**
042         * Serialization key
043         */
044        private static final long serialVersionUID = 4072572956381768087L;
045    
046        /**
047         * How long to wait before removing an untouched object from the cache.
048         * Negative numbers mean never remove (the default).
049         */
050        private long timeToLive = -1;
051    
052        /**
053         * The last time the Object was accessed from the cache.
054         */
055        private long lastAccess;
056    
057        /**
058         * Constructor; sets the object to expire in the default time (30 minutes).
059         * 
060         * @param o
061         *            The object you want to cache.
062         */
063        public RefreshableCachedObject(Refreshable o)
064        {
065            super(o);
066            this.lastAccess = System.currentTimeMillis();
067        }
068    
069        /**
070         * Constructor.
071         * 
072         * @param o
073         *            The object to cache.
074         * @param expires
075         *            How long before the object expires, in ms, e.g. 1000 = 1
076         *            second.
077         */
078        public RefreshableCachedObject(Refreshable o, long expires)
079        {
080            super(o, expires);
081            this.lastAccess = System.currentTimeMillis();
082        }
083    
084        /**
085         * Sets the timeToLive value
086         * 
087         * @param timeToLive
088         *            the new Value in milliseconds
089         */
090        public synchronized void setTTL(long timeToLive)
091        {
092            this.timeToLive = timeToLive;
093        }
094    
095        /**
096         * Gets the timeToLive value.
097         * 
098         * @return The current timeToLive value (in milliseconds)
099         */
100        public synchronized long getTTL()
101        {
102            return this.timeToLive;
103        }
104    
105        /**
106         * Sets the last access time to the current time.
107         */
108        public synchronized void touch()
109        {
110            this.lastAccess = System.currentTimeMillis();
111        }
112    
113        /**
114         * Returns true if the object hasn't been touched in the previous TTL
115         * period.
116         */
117        public synchronized boolean isUntouched()
118        {
119            if (this.timeToLive < 0)
120            {
121                return false;
122            }
123    
124            if (this.lastAccess + this.timeToLive < System.currentTimeMillis())
125            {
126                return true;
127            }
128            else
129            {
130                return false;
131            }
132        }
133    
134        /**
135         * Refresh the object and the created time.
136         */
137        public void refresh()
138        {
139            Refreshable r = (Refreshable) getContents();
140            synchronized (this)
141            {
142                this.created = System.currentTimeMillis();
143                r.refresh();
144            }
145        }
146    }