001: /*
002: * The contents of this file are subject to the
003: * Mozilla Public License Version 1.1 (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 http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.
009: * See the License for the specific language governing rights and
010: * limitations under the License.
011: *
012: * The Initial Developer of the Original Code is Simulacra Media Ltd.
013: * Portions created by Simulacra Media Ltd are Copyright (C) Simulacra Media Ltd, 2004.
014: *
015: * All Rights Reserved.
016: *
017: * Contributor(s):
018: */
019: package org.openharmonise.vfs;
020:
021: import java.util.ArrayList;
022: import java.util.Date;
023: import java.util.HashMap;
024: import java.util.List;
025:
026: /**
027: * Generic cache for VirtualFileObjects. The default timeout for these objects
028: * is 5 minutes, this can be overridden.
029: *
030: * @author Matthew Large
031: * @version $Revision: 1.1 $
032: *
033: */
034: public class VirtualFileCache {
035:
036: /**
037: * Map of path to {@link TimestampedObject} objects.
038: */
039: private HashMap m_files = new HashMap(71);
040:
041: /**
042: * Timeout value for virtual files in the cache in milliseconds.
043: */
044: private int m_nTimeout = 60000 /*1 minute in milliseconds*/* 20 /*minutes*/;
045:
046: /**
047: * Constructs a VirtualFileCache with a specific timeout, overriding the default
048: * 5 minute timeout.
049: *
050: * @param nTimeout Sets the cache's timeout value in milliseconds. (60000=1 minute)
051: */
052: public VirtualFileCache(int nTimeout) {
053: super ();
054: this .m_nTimeout = nTimeout;
055: }
056:
057: public VirtualFileCache() {
058: super ();
059: }
060:
061: /**
062: * Checks if the cache contains a specific VirtualFile as indexed by path.
063: *
064: * @param sFullpath The full path of the VirtualFile to be checked
065: * @return true if the cache contains the VirtualFile. If the VirtualFile has timed out it will be removed from the cache and False will be returned
066: */
067: public synchronized boolean hasFile(String sFullpath) {
068: boolean bRetn = false;
069: if (sFullpath != null && sFullpath.endsWith("/")) {
070: sFullpath = sFullpath.substring(0, sFullpath.length() - 1);
071: }
072:
073: if (sFullpath != null && m_files.containsKey(sFullpath.trim())
074: && m_files.get(sFullpath.trim()) != null) {
075: if (!((TimestampedObject) m_files.get(sFullpath.trim()))
076: .isTimedOut(this .m_nTimeout)) {
077: bRetn = true;
078: } else {
079: this .removeFile(sFullpath.trim());
080: }
081: }
082: if (!bRetn) {
083:
084: }
085:
086: return bRetn;
087: }
088:
089: /**
090: * Gets a List object containing all the path Strings in the cache.
091: *
092: * @return List of path Strings
093: */
094: public List getPaths() {
095: List vPaths = new ArrayList(this .m_files.keySet());
096:
097: return vPaths;
098: }
099:
100: /**
101: * Adds a VirtualFile to the cache, if a VirtualFile with the path is already in the cache it will be overwritten with this one.
102: *
103: * @param vfFile VirtualFile to be added
104: */
105: public synchronized void addFile(VirtualFile vfFile) {
106: TimestampedObject tsObj = new TimestampedObject(vfFile);
107: if (m_files.keySet().contains(vfFile.getFullPath().trim())) {
108: if (!((VirtualFile) ((TimestampedObject) m_files.get(vfFile
109: .getFullPath().trim())).getObject()).isChanged()) {
110: m_files.put(vfFile.getFullPath().trim(), tsObj);
111: }
112: } else {
113: m_files.put(vfFile.getFullPath().trim(), tsObj);
114: }
115: }
116:
117: /**
118: * Gets a VirtualFile from the cache as specified by the path.
119: *
120: * @param sFullpath Path of the VirtualFile to be returned
121: * @return Requested VirtualFile or null if path is not found in cache
122: */
123: public VirtualFile getFile(String sFullpath) {
124: VirtualFile vfRetn = null;
125: if (sFullpath.endsWith("/")) {
126: sFullpath = sFullpath.substring(0, sFullpath.length() - 1);
127: }
128:
129: TimestampedObject tsObj = (TimestampedObject) m_files
130: .get(sFullpath.trim());
131: if (tsObj != null) {
132:
133: if (!((VirtualFile) tsObj.getObject()).getFullPath()
134: .equalsIgnoreCase(sFullpath)) {
135: }
136:
137: long currTime = new Date().getTime();
138: if (!tsObj.isTimedOut(this .m_nTimeout)) {
139: vfRetn = (VirtualFile) tsObj.getObject();
140: tsObj.resetTimestamp();
141: } else {
142: this .removeFile(sFullpath);
143: }
144: }
145:
146: return vfRetn;
147: }
148:
149: /**
150: * Removes a specific VirtualFile from the cache.
151: *
152: * @param sFullpath Path of VirtualFile to be removed
153: * @return previous value associated with specified key, or null if there was no mapping for key
154: */
155: public VirtualFile removeFile(String sFullpath) {
156: return (VirtualFile) ((TimestampedObject) m_files
157: .remove(sFullpath)).getObject();
158: }
159:
160: /**
161: * Wraps an object with a timestamp
162: *
163: * @author Matthew Large
164: */
165: private class TimestampedObject {
166: private Object m_object;
167: private Long m_timestamp;
168:
169: /**
170: * Wraps the supplied object and gives it a timestamp of the current system time.
171: *
172: * @param obj Object to be timestamped
173: */
174: public TimestampedObject(Object obj) {
175: this (obj, new Long(new Date().getTime()));
176: }
177:
178: /**
179: * Wraps the supplied object and gives it the specified timestamp.
180: *
181: * @param obj Object to be timestamped
182: * @param timestamp Timestamp to give to the object
183: */
184: public TimestampedObject(Object obj, Long timestamp) {
185: m_timestamp = timestamp;
186: m_object = obj;
187: }
188:
189: /**
190: * Checks a timeout value
191: *
192: * @param nTimeout
193: * @return True if the object is timed out
194: */
195: private boolean isTimedOut(int nTimeout) {
196: long currTime = new Date().getTime();
197: return (!((VirtualFile) this .getObject())
198: .hasVirtualFileListeners()
199: && !((VirtualFile) this .getObject()).isChanged() && (currTime - getTimestamp()
200: .longValue()) > nTimeout);
201: }
202:
203: /**
204: * Gets the object
205: *
206: * @return Object that is wrapped by this Timestampedobject
207: */
208: public Object getObject() {
209: return m_object;
210: }
211:
212: /**
213: * Gets the current timestamp value
214: *
215: * @return Timestamp in milliseconds
216: */
217: public Long getTimestamp() {
218: return m_timestamp;
219: }
220:
221: /**
222: * Resets the timestamp value to the current system time
223: */
224: public void resetTimestamp() {
225: m_timestamp = new Long(new Date().getTime());
226: }
227:
228: /* (non-Javadoc)
229: * @see java.lang.Object#equals(java.lang.Object)
230: */
231: public boolean equals(Object obj) {
232: TimestampedObject to = (TimestampedObject) obj;
233:
234: boolean bReturn = m_object.equals(to.getObject());
235:
236: return bReturn;
237: }
238:
239: /* (non-Javadoc)
240: * @see java.lang.Object#toString()
241: */
242: public String toString() {
243: return "(" + m_object.hashCode() + "," + m_timestamp + ")";
244: }
245: }
246:
247: }
|