KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > team > internal > core > ResourceVariantCache


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.team.internal.core;
12
13 import java.io.File JavaDoc;
14 import java.util.*;
15
16 import org.eclipse.core.runtime.IPath;
17 import org.eclipse.core.runtime.jobs.ILock;
18 import org.eclipse.core.runtime.jobs.Job;
19 import org.eclipse.osgi.util.NLS;
20 import org.eclipse.team.core.TeamException;
21 import org.eclipse.team.core.variants.CachedResourceVariant;
22
23 /**
24  * This class implements a caching facility that can be used by TeamProviders to cache contents
25  */

26 public class ResourceVariantCache {
27     
28     // Directory to cache file contents
29
private static final String JavaDoc CACHE_DIRECTORY = ".cache"; //$NON-NLS-1$
30
// Maximum lifespan of local cache file, in milliseconds
31
private static final long CACHE_FILE_LIFESPAN = 60*60*1000; // 1hr
32

33     // Map of registered caches indexed by local name of a QualifiedName
34
private static Map caches = new HashMap(); // String (local name) > RemoteContentsCache
35

36     private String JavaDoc name;
37     private Map cacheEntries;
38     private long lastCacheCleanup;
39     private int cacheDirSize;
40
41     // Lock used to serialize the writing of cache contents
42
private ILock lock = Job.getJobManager().newLock();
43     
44     /**
45      * Enables the use of remote contents caching for the given cacheId. The cache ID must be unique.
46      * A good candidate for this ID is the plugin ID of the plugin performing the caching.
47      *
48      * @param cacheId the unique Id of the cache being enabled
49      */

50     public static synchronized void enableCaching(String JavaDoc cacheId) {
51         if (isCachingEnabled(cacheId)) return;
52         ResourceVariantCache cache = new ResourceVariantCache(cacheId);
53         cache.createCacheDirectory();
54         caches.put(cacheId, cache);
55     }
56     
57     /**
58      * Returns whether caching has been enabled for the given Id. A cache should only be enabled once.
59      * It is conceivable that a cache be persisted over workbench invocations thus leading to a cache that
60      * is enabled on startup without intervention by the owning plugin.
61      *
62      * @param cacheId the unique Id of the cache
63      * @return true if caching for the given Id is enabled
64      */

65     public static boolean isCachingEnabled(String JavaDoc cacheId) {
66         return getCache(cacheId) != null;
67     }
68     
69     /**
70      * Disable the cache, disposing of any file contents in the cache.
71      *
72      * @param cacheId the unique Id of the cache
73      */

74     public static void disableCache(String JavaDoc cacheId) {
75         ResourceVariantCache cache = getCache(cacheId);
76         if (cache == null) {
77             // There is no cache to dispose of
78
return;
79         }
80         caches.remove(cacheId);
81         cache.deleteCacheDirectory();
82     }
83     
84     /**
85      * Return the cache for the given id or null if caching is not enabled for the given id.
86      * @param cacheId
87      * @return the cache
88      */

89     public static synchronized ResourceVariantCache getCache(String JavaDoc cacheId) {
90         return (ResourceVariantCache)caches.get(cacheId);
91     }
92     
93     public static synchronized void shutdown() {
94         String JavaDoc[] keys = (String JavaDoc[])caches.keySet().toArray(new String JavaDoc[caches.size()]);
95         for (int i = 0; i < keys.length; i++) {
96             String JavaDoc id = keys[i];
97             disableCache(id);
98         }
99     }
100     
101     private ResourceVariantCache(String JavaDoc name) {
102         this.name = name;
103     }
104     
105     /**
106      * Return whether the cache contains an entry for the given id. Register a hit if it does.
107      * @param id the id of the cache entry
108      * @return true if there are contents cached for the id
109      */

110     public boolean hasEntry(String JavaDoc id) {
111         return internalGetCacheEntry(id) != null;
112     }
113
114     protected IPath getCachePath() {
115         return getStateLocation().append(CACHE_DIRECTORY).append(name);
116     }
117
118     private IPath getStateLocation() {
119         return TeamPlugin.getPlugin().getStateLocation();
120     }
121     
122     private synchronized void clearOldCacheEntries() {
123         long current = new Date().getTime();
124         if ((lastCacheCleanup!=-1) && (current - lastCacheCleanup < CACHE_FILE_LIFESPAN)) return;
125         List stale = new ArrayList();
126         for (Iterator iter = cacheEntries.values().iterator(); iter.hasNext();) {
127             ResourceVariantCacheEntry entry = (ResourceVariantCacheEntry) iter.next();
128             long lastHit = entry.getLastAccessTimeStamp();
129             if ((current - lastHit) > CACHE_FILE_LIFESPAN){
130                 stale.add(entry);
131             }
132         }
133         for (Iterator iter = stale.iterator(); iter.hasNext();) {
134             ResourceVariantCacheEntry entry = (ResourceVariantCacheEntry) iter.next();
135             entry.dispose();
136         }
137     }
138     
139     private synchronized void purgeFromCache(String JavaDoc id) {
140         ResourceVariantCacheEntry entry = (ResourceVariantCacheEntry)cacheEntries.get(id);
141         File JavaDoc f = entry.getFile();
142         try {
143             deleteFile(f);
144         } catch (TeamException e) {
145             // Ignore the deletion failure.
146
// A failure only really matters when purging the directory on startup
147
}
148         cacheEntries.remove(id);
149     }
150     
151     private synchronized void createCacheDirectory() {
152         IPath cacheLocation = getCachePath();
153         File JavaDoc file = cacheLocation.toFile();
154         if (file.exists()) {
155             try {
156                 deleteFile(file);
157             } catch (TeamException e) {
158                 // Check to see if were in an acceptable state
159
if (file.exists() && (!file.isDirectory() || file.listFiles().length != 0)) {
160                     TeamPlugin.log(e);
161                 }
162             }
163         }
164         if (! file.exists() && ! file.mkdirs()) {
165             TeamPlugin.log(new TeamException(NLS.bind(Messages.RemoteContentsCache_fileError, new String JavaDoc[] { file.getAbsolutePath() })));
166         }
167         cacheEntries = new HashMap();
168         lastCacheCleanup = -1;
169         cacheDirSize = 0;
170     }
171             
172     private synchronized void deleteCacheDirectory() {
173         cacheEntries = null;
174         lastCacheCleanup = -1;
175         cacheDirSize = 0;
176         IPath cacheLocation = getCachePath();
177         File JavaDoc file = cacheLocation.toFile();
178         if (file.exists()) {
179             try {
180                 deleteFile(file);
181             } catch (TeamException e) {
182                 // Don't worry about problems deleting.
183
// The only case that matters is when the cache directory is created
184
}
185         }
186     }
187     
188     private void deleteFile(File JavaDoc file) throws TeamException {
189         if (file.isDirectory()) {
190             File JavaDoc[] children = file.listFiles();
191             for (int i = 0; i < children.length; i++) {
192                 deleteFile(children[i]);
193             }
194         }
195         if (! file.delete()) {
196             throw new TeamException(NLS.bind(Messages.RemoteContentsCache_fileError, new String JavaDoc[] { file.getAbsolutePath() }));
197         }
198     }
199
200     /**
201      * Purge the given cache entry from the cache. This method should only be invoked from
202      * an instance of ResourceVariantCacheEntry after it has set it's state to DISPOSED.
203      * @param entry
204      */

205     protected void purgeFromCache(ResourceVariantCacheEntry entry) {
206         purgeFromCache(entry.getId());
207     }
208
209     private synchronized ResourceVariantCacheEntry internalGetCacheEntry(String JavaDoc id) {
210         if (cacheEntries == null) {
211             // This probably means that the cache has been disposed
212
throw new IllegalStateException JavaDoc(NLS.bind(Messages.RemoteContentsCache_cacheDisposed, new String JavaDoc[] { name }));
213         }
214         ResourceVariantCacheEntry entry = (ResourceVariantCacheEntry)cacheEntries.get(id);
215         if (entry != null) {
216             entry.registerHit();
217         }
218         return entry;
219     }
220     
221     /**
222      * @param id the id that uniquely identifies the remote resource that is cached.
223      * @return the cache entry
224      */

225     public ResourceVariantCacheEntry getCacheEntry(String JavaDoc id) {
226         return internalGetCacheEntry(id);
227     }
228     
229     public synchronized ResourceVariantCacheEntry add(String JavaDoc id, CachedResourceVariant resource) {
230         clearOldCacheEntries();
231         String JavaDoc filePath = String.valueOf(cacheDirSize++);
232         ResourceVariantCacheEntry entry = new ResourceVariantCacheEntry(this, lock, id, filePath);
233         entry.setResourceVariant(resource);
234         cacheEntries.put(id, entry);
235         return entry;
236     }
237
238     public String JavaDoc getName() {
239         return name;
240     }
241     
242     /*
243      * Method used for testing only
244      */

245     public ResourceVariantCacheEntry[] getEntries() {
246         return (ResourceVariantCacheEntry[]) cacheEntries.values().toArray(new ResourceVariantCacheEntry[cacheEntries.size()]);
247     }
248
249 }
250
Popular Tags