KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opencms > flex > CmsFlexCache


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src/org/opencms/flex/CmsFlexCache.java,v $
3  * Date : $Date: 2006/03/27 14:52:35 $
4  * Version: $Revision: 1.52 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (c) 2005 Alkacon Software GmbH (http://www.alkacon.com)
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about Alkacon Software GmbH, please see the
22  * company website: http://www.alkacon.com
23  *
24  * For further information about OpenCms, please see the
25  * project website: http://www.opencms.org
26  *
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30  */

31
32 package org.opencms.flex;
33
34 import org.opencms.cache.CmsLruCache;
35 import org.opencms.cache.I_CmsLruCacheObject;
36 import org.opencms.file.CmsObject;
37 import org.opencms.main.CmsLog;
38 import org.opencms.main.I_CmsEventListener;
39 import org.opencms.main.OpenCms;
40 import org.opencms.security.CmsRole;
41 import org.opencms.util.CmsFileUtil;
42 import org.opencms.util.CmsStringUtil;
43
44 import java.io.File JavaDoc;
45 import java.util.Collections JavaDoc;
46 import java.util.HashMap JavaDoc;
47 import java.util.HashSet JavaDoc;
48 import java.util.Hashtable JavaDoc;
49 import java.util.Iterator JavaDoc;
50 import java.util.Map JavaDoc;
51 import java.util.Set JavaDoc;
52
53 import org.apache.commons.collections.map.LRUMap;
54 import org.apache.commons.logging.Log;
55
56 /**
57  * This class implements the FlexCache.<p>
58  *
59  * The data structure used is a two-level hashtable.
60  * This is optimized for the structure of the keys that are used to describe the
61  * caching behaviour of the entries.
62  * The first hash-level is calculated from the resource name, i.e. the
63  * name of the resource as it is referred to in the VFS of OpenCms.
64  * The second hash-level is calculated from the cache-key of the resource,
65  * which also is a String representing the specifc variation of the cached entry.<p>
66  *
67  * A suffix [online] or [offline] is appended to te resource name
68  * to distinguish between the online and offline projects of OpenCms.
69  * Also, for support of JSP based workplace pages, a suffix [workplace]
70  * is appended. The same cached workplace pages are used both in the online and
71  * all offline projects.<p>
72  *
73  * Entries in the first level of the cache are of type CmsFlexCacheVariation,
74  * which is a sub-class of CmsFlexCache.
75  * This class is a simple data type that contains of a Map of CmsFlexCacheEntries,
76  * with variations - Strings as keys.<p>
77  *
78  * Here's a short summary of used terms:
79  * <ul>
80  * <li><b>key:</b>
81  * A combination of a resource name and a variation.
82  * The data structure used is CmsFlexCacheKey.
83  * <li><b>resource:</b>
84  * A String with the resource name and an appended [online] of [offline] suffix.
85  * <li><b>variation:</b>
86  * A String describing a variation of a cached entry in the CmsFlexCache language.
87  * <li><b>entry:</b>
88  * A CmsFlexCacheEntry data structure which is describes a cached OpenCms resource.
89  * For every entry a key is saved which contains the resource name and the variation.
90  * </ul>
91  *
92  * Cache clearing is handled using events.
93  * The cache is fully flushed if an event {@link I_CmsEventListener#EVENT_PUBLISH_PROJECT}
94  * or {@link I_CmsEventListener#EVENT_CLEAR_CACHES} is caught.<p>
95  *
96  * @author Alexander Kandzior
97  * @author Thomas Weckert
98  *
99  * @version $Revision: 1.52 $
100  *
101  * @since 6.0.0
102  *
103  * @see org.opencms.flex.CmsFlexCacheKey
104  * @see org.opencms.flex.CmsFlexCacheEntry
105  * @see org.opencms.cache.CmsLruCache
106  * @see org.opencms.cache.I_CmsLruCacheObject
107  */

108 public class CmsFlexCache extends Object JavaDoc implements I_CmsEventListener {
109
110     /**
111      * A simple data container class for the FlexCache variations.<p>
112      *
113      * @author Alexander Kandzior
114      */

115     public class CmsFlexCacheVariation extends Object JavaDoc {
116
117         /** The key belonging to the resource. */
118         public CmsFlexCacheKey m_key;
119
120         /** Maps variations to CmsFlexCacheEntries. */
121         public Map JavaDoc m_map;
122
123         /**
124          * Generates a new instance of CmsFlexCacheVariation.<p>
125          *
126          * @param theKey The (resource) key to contruct this variation list for
127          */

128         public CmsFlexCacheVariation(CmsFlexCacheKey theKey) {
129
130             m_key = theKey;
131             m_map = new Hashtable JavaDoc(INITIAL_CAPACITY_VARIATIONS);
132         }
133     }
134
135     /**
136      * Extended LRUMap that handles the variations in case a key is removed.<p>
137      *
138      * @author Alexander Kandzior
139      */

140     class CmsFlexKeyMap extends LRUMap {
141
142         /** Serial version UID required for safe serialization. */
143         private static final long serialVersionUID = 6931995916013396902L;
144
145         /**
146          * Initialize the map with the given size.<p>
147          *
148          * @param maxSize the maximum number of key to cache
149          */

150         public CmsFlexKeyMap(int maxSize) {
151
152             super(maxSize);
153         }
154
155         /**
156          * Ensures that all variations that referenced by this key are released
157          * if the key is released.<p>
158          */

159         protected boolean removeLRU(LinkEntry entry) {
160
161             CmsFlexCacheVariation v = (CmsFlexCacheVariation)entry.getValue();
162             if (v == null) {
163                 return true;
164             }
165             Map JavaDoc m = v.m_map;
166             if ((m == null) || (m.size() == 0)) {
167                 return true;
168             }
169             Object JavaDoc[] entries = m.values().toArray();
170             synchronized (m_variationCache) {
171                 for (int i = 0, s = entries.length; i < s; i++) {
172                     CmsFlexCacheEntry e = (CmsFlexCacheEntry)entries[i];
173                     m_variationCache.remove(e);
174                 }
175                 v.m_map.clear();
176                 v.m_map = null;
177                 v.m_key = null;
178             }
179             return true;
180         }
181     }
182
183     /** Suffix to append to online cache entries. */
184     public static final String JavaDoc CACHE_OFFLINESUFFIX = " [offline]";
185
186     /** Suffix to append to online cache entries. */
187     public static final String JavaDoc CACHE_ONLINESUFFIX = " [online]";
188
189     /** Trigger for clearcache event: Clear complete cache. */
190     public static final int CLEAR_ALL = 0;
191
192     /** Trigger for clearcache event: Clear only entries. */
193     public static final int CLEAR_ENTRIES = 1;
194
195     /** Trigger for clearcache event: Clear complete offine cache. */
196     public static final int CLEAR_OFFLINE_ALL = 4;
197
198     /** Trigger for clearcache event: Clear only offline entries. */
199     public static final int CLEAR_OFFLINE_ENTRIES = 5;
200
201     /** Trigger for clearcache event: Clear complete online cache. */
202     public static final int CLEAR_ONLINE_ALL = 2;
203
204     /** Trigger for clearcache event: Clear only online entries. */
205     public static final int CLEAR_ONLINE_ENTRIES = 3;
206
207     /** Initial cache size, this should be a power of 2 because of the Java collections implementation. */
208     public static final int INITIAL_CAPACITY_CACHE = 512;
209
210     /** Initial size for variation lists, should be a power of 2. */
211     public static final int INITIAL_CAPACITY_VARIATIONS = 8;
212
213     /** Offline repository constant. */
214     public static final String JavaDoc REPOSITORY_OFFLINE = "offline";
215
216     /** Online repository constant. */
217     public static final String JavaDoc REPOSITORY_ONLINE = "online";
218
219     /** The log object for this class. */
220     private static final Log LOG = CmsLog.getLog(CmsFlexCache.class);
221
222     /** The LRU cache to organize the cached entries. */
223     protected CmsLruCache m_variationCache;
224
225     /** Indicates if offline resources should be cached or not. */
226     private boolean m_cacheOffline;
227
228     /** Indicates if the cache is enabled or not. */
229     private boolean m_enabled;
230
231     /** Hashmap to store the entries for fast lookup. */
232     private Map JavaDoc m_keyCache;
233
234     /** Counter for the size. */
235     private int m_size;
236
237     /**
238      * Constructor for class CmsFlexCache.<p>
239      *
240      * The parameter "enabled" is used to control if the cache is
241      * actually on or off. Even if you don't need the cache, you still
242      * have to create an instance of it with enabled=false.
243      * This is because you need some of the FlexCache data structures
244      * for JSP inclusion buffering.<p>
245      *
246      * @param configuration the flex cache configuration
247      */

248     public CmsFlexCache(CmsFlexCacheConfiguration configuration) {
249
250         m_enabled = configuration.isCacheEnabled();
251         m_cacheOffline = configuration.isCacheOffline();
252
253         int maxCacheBytes = configuration.getMaxCacheBytes();
254         int avgCacheBytes = configuration.getAvgCacheBytes();
255         int maxEntryBytes = configuration.getMaxEntryBytes();
256         int maxKeys = configuration.getMaxKeys();
257
258         m_variationCache = new CmsLruCache(maxCacheBytes, avgCacheBytes, maxEntryBytes);
259
260         if (OpenCms.getMemoryMonitor().enabled()) {
261             OpenCms.getMemoryMonitor().register(getClass().getName() + ".m_entryLruCache", m_variationCache);
262         }
263
264         if (m_enabled) {
265             CmsFlexKeyMap flexKeyMap = new CmsFlexKeyMap(maxKeys);
266             m_keyCache = Collections.synchronizedMap(flexKeyMap);
267
268             if (OpenCms.getMemoryMonitor().enabled()) {
269                 OpenCms.getMemoryMonitor().register(getClass().getName() + ".m_resourceMap", flexKeyMap);
270             }
271
272             OpenCms.addCmsEventListener(this, new int[] {
273                 I_CmsEventListener.EVENT_PUBLISH_PROJECT,
274                 I_CmsEventListener.EVENT_CLEAR_CACHES,
275                 I_CmsEventListener.EVENT_FLEX_PURGE_JSP_REPOSITORY,
276                 I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR});
277         }
278
279         if (LOG.isInfoEnabled()) {
280             LOG.info(Messages.get().getBundle().key(
281                 Messages.INIT_FLEXCACHE_CREATED_2,
282                 new Boolean JavaDoc(m_enabled),
283                 new Boolean JavaDoc(m_cacheOffline)));
284         }
285     }
286
287     /**
288      * Indicates if offline project resources are cached.<p>
289      *
290      * @return true if offline projects are cached, false if not
291      */

292     public boolean cacheOffline() {
293
294         return m_cacheOffline;
295     }
296
297     /**
298      * Implements the CmsEvent interface,
299      * the FlexCache uses the events to clear itself in case a project is published.<p>
300      *
301      * @param event CmsEvent that has occurred
302      */

303     public void cmsEvent(org.opencms.main.CmsEvent event) {
304
305         if (!isEnabled()) {
306             return;
307         }
308
309         switch (event.getType()) {
310             case I_CmsEventListener.EVENT_PUBLISH_PROJECT:
311             case I_CmsEventListener.EVENT_CLEAR_CACHES:
312                 if (LOG.isDebugEnabled()) {
313                     LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_RECEIVED_EVENT_CLEAR_CACHE_0));
314                 }
315                 clear();
316                 break;
317             case I_CmsEventListener.EVENT_FLEX_PURGE_JSP_REPOSITORY:
318                 if (LOG.isDebugEnabled()) {
319                     LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_RECEIVED_EVENT_PURGE_REPOSITORY_0));
320                 }
321                 purgeJspRepository();
322                 break;
323             case I_CmsEventListener.EVENT_FLEX_CACHE_CLEAR:
324                 if (LOG.isDebugEnabled()) {
325                     LOG.debug(Messages.get().getBundle().key(
326                         Messages.LOG_FLEXCACHE_RECEIVED_EVENT_CLEAR_CACHE_PARTIALLY_0));
327                 }
328                 Map JavaDoc m = event.getData();
329                 if (m == null) {
330                     break;
331                 }
332                 Integer JavaDoc it = null;
333                 try {
334                     it = (Integer JavaDoc)m.get("action");
335                 } catch (Exception JavaDoc e) {
336                     // it will be null
337
}
338                 if (it == null) {
339                     break;
340                 }
341                 int i = it.intValue();
342                 switch (i) {
343                     case CLEAR_ALL:
344                         clear();
345                         break;
346                     case CLEAR_ENTRIES:
347                         clearEntries();
348                         break;
349                     case CLEAR_ONLINE_ALL:
350                         clearOnline();
351                         break;
352                     case CLEAR_ONLINE_ENTRIES:
353                         clearOnlineEntries();
354                         break;
355                     case CLEAR_OFFLINE_ALL:
356                         clearOffline();
357                         break;
358                     case CLEAR_OFFLINE_ENTRIES:
359                         clearOfflineEntries();
360                         break;
361                     default:
362                 // no operation
363
}
364             default:
365         // no operation
366
}
367     }
368
369     /**
370      * Returns the CmsFlexCacheKey data structure for a given
371      * key (i.e. resource name).<p>
372      *
373      * Usefull if you want to show the cache key for a resources,
374      * like on the FlexCache administration page.<p>
375      *
376      * Only users with administrator permissions are allowed
377      * to perform this operation.<p>
378      *
379      * @param key the resource name for which to look up the variation for
380      * @param cms the CmsObject used for user authorization
381      * @return the CmsFlexCacheKey data structure found for the resource
382      */

383     public CmsFlexCacheKey getCachedKey(String JavaDoc key, CmsObject cms) {
384
385         if (!isEnabled() || !cms.hasRole(CmsRole.WORKPLACE_MANAGER)) {
386             return null;
387         }
388         Object JavaDoc o = m_keyCache.get(key);
389         if (o != null) {
390             return ((CmsFlexCacheVariation)o).m_key;
391         }
392         return null;
393     }
394
395     /**
396      * Returns a set of all cached resource names.
397      * Usefull if you want to show a list of all cached resources,
398      * like on the FlexCache administration page.<p>
399      *
400      * Only users with administrator permissions are allowed
401      * to perform this operation.<p>
402      *
403      * @param cms the CmsObject used for user authorization
404      * @return a Set of cached resource names (which are of type String)
405      */

406     public Set JavaDoc getCachedResources(CmsObject cms) {
407
408         if (!isEnabled() || !cms.hasRole(CmsRole.WORKPLACE_MANAGER)) {
409             return null;
410         }
411         return m_keyCache.keySet();
412     }
413
414     /**
415      * Returns all variations in the cache for a given resource name.
416      * The variations are of type String.<p>
417      *
418      * Usefull if you want to show a list of all cached entry - variations,
419      * like on the FlexCache administration page.<p>
420      *
421      * Only users with administrator permissions are allowed
422      * to perform this operation.<p>
423      *
424      * @param key the resource name for which to look up the variations for
425      * @param cms the CmsObject used for user authorization
426      * @return a Set of cached variations (which are of type String)
427      */

428     public Set JavaDoc getCachedVariations(String JavaDoc key, CmsObject cms) {
429
430         if (!isEnabled() || !cms.hasRole(CmsRole.WORKPLACE_MANAGER)) {
431             return null;
432         }
433         Object JavaDoc o = m_keyCache.get(key);
434         if (o != null) {
435             return ((CmsFlexCacheVariation)o).m_map.keySet();
436         }
437         return null;
438     }
439
440     /**
441      * Returns the LRU cache where the CacheEntries are cached.<p>
442      *
443      * @return the LRU cache where the CacheEntries are cached
444      */

445     public CmsLruCache getEntryLruCache() {
446
447         return m_variationCache;
448     }
449
450     /**
451      * Indicates if the cache is enabled (i.e. actually
452      * caching entries) or not.<p>
453      *
454      * @return true if the cache is enabled, false if not
455      */

456     public boolean isEnabled() {
457
458         return m_enabled;
459     }
460
461     /**
462      * Returns the total number of cached resource keys.
463      *
464      * @return the number of resource keys in the cache
465      */

466     public int keySize() {
467
468         if (!isEnabled()) {
469             return 0;
470         }
471         return m_keyCache.size();
472     }
473
474     /**
475      * Returns the total number of entries in the cache.<p>
476      *
477      * @return the number of entries in the cache
478      */

479     public int size() {
480
481         return m_variationCache.size();
482     }
483
484     /**
485      * Clears the cache for finalization.<p>
486      * @throws Throwable if something goes wrong
487      */

488     protected void finalize() throws Throwable JavaDoc {
489
490         try {
491             clear();
492             m_variationCache = null;
493             m_keyCache = null;
494         } catch (Throwable JavaDoc t) {
495             // ignore
496
}
497         super.finalize();
498     }
499
500     /**
501      * Looks up a specific entry in the cache.<p>
502      *
503      * In case a found entry has a timeout set, it will be checked upon lookup.
504      * In case the timeout of the entry has been reached, it will be removed from
505      * the cache (and null will be returned in this case).<p>
506      *
507      * @param key The key to look for in the cache
508      * @return the entry found for the key, or null if key is not in the cache
509      */

510     CmsFlexCacheEntry get(CmsFlexRequestKey key) {
511
512         if (!isEnabled()) {
513             // cache is disabled
514
return null;
515         }
516         Object JavaDoc o = m_keyCache.get(key.getResource());
517         if (o != null) {
518             // found a matching key in the cache
519
CmsFlexCacheVariation v = (CmsFlexCacheVariation)o;
520             String JavaDoc variation = v.m_key.matchRequestKey(key);
521
522             if (CmsStringUtil.isEmpty(variation)) {
523                 // requested resource is not cacheable
524
return null;
525             }
526             CmsFlexCacheEntry entry = (CmsFlexCacheEntry)v.m_map.get(variation);
527             if (entry == null) {
528                 // no cache entry available for variation
529
return null;
530             }
531             if (entry.getDateExpires() < System.currentTimeMillis()) {
532                 // cache entry avaiable but expired, remove entry
533
m_variationCache.remove(entry);
534                 return null;
535             }
536             // return the found cache entry
537
return entry;
538         } else {
539             return null;
540         }
541     }
542
543     /**
544      * Returns the CmsFlexCacheKey data structure for a given resource name.<p>
545      *
546      * @param resource the resource name for which to look up the key for
547      * @return the CmsFlexCacheKey data structure found for the resource
548      */

549     CmsFlexCacheKey getKey(String JavaDoc resource) {
550
551         if (!isEnabled()) {
552             return null;
553         }
554         Object JavaDoc o = m_keyCache.get(resource);
555         if (o != null) {
556             if (LOG.isDebugEnabled()) {
557                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHEKEY_FOUND_1, resource));
558             }
559             return ((CmsFlexCacheVariation)o).m_key;
560         } else {
561             if (LOG.isDebugEnabled()) {
562                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHEKEY_NOT_FOUND_1, resource));
563             }
564             return null;
565         }
566     }
567
568     /**
569      * Checks if the cache is empty or if at last one element is contained.<p>
570      *
571      * @return true if the cache is empty, false otherwise
572      */

573     boolean isEmpty() {
574
575         if (!isEnabled()) {
576             return true;
577         }
578         return m_keyCache.isEmpty();
579     }
580
581     /**
582      * This method adds new entries to the cache.<p>
583      *
584      * The key describes the conditions under which the value can be cached.
585      * Usually the key belongs to the response.
586      * The variation describes the conditions under which the
587      * entry was created. This is usually calculated from the request.
588      * If the variation is != null, the entry is cachable.<p>
589      *
590      * @param key the key for the new value entry
591      * @param entry the CmsFlexCacheEntry to store in the cache
592      * @param variation the pre-calculated variation for the entry
593      * @return true if the value was added to the cache, false otherwise
594      */

595     boolean put(CmsFlexCacheKey key, CmsFlexCacheEntry entry, String JavaDoc variation) {
596
597         if (!isEnabled()) {
598             return false;
599         }
600         if (LOG.isDebugEnabled()) {
601             LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_ADD_ENTRY_1, key.getResource()));
602         }
603         if (variation != null) {
604             // This is a cachable result
605
key.setVariation(variation);
606             if (LOG.isDebugEnabled()) {
607                 LOG.debug(Messages.get().getBundle().key(
608                     Messages.LOG_FLEXCACHE_ADD_ENTRY_WITH_VARIATION_2,
609                     key.getResource(),
610                     key.getVariation()));
611             }
612             put(key, entry);
613             // Note that duplicates are NOT checked, it it assumed that this is done beforehand,
614
// while checking if the entry is already in the cache or not.
615
return true;
616         } else {
617             // Result is not cachable
618
if (LOG.isDebugEnabled()) {
619                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_RESOURCE_NOT_CACHEABLE_0));
620             }
621             return false;
622         }
623     }
624
625     /**
626      * Adds a key with a new, empty variation map to the cache.<p>
627      *
628      * @param key the key to add to the cache.
629      */

630     void putKey(CmsFlexCacheKey key) {
631
632         if (!isEnabled()) {
633             return;
634         }
635         Object JavaDoc o = m_keyCache.get(key.getResource());
636         if (o == null) {
637             // No variation map for this resource yet, so create one
638
CmsFlexCacheVariation variationMap = new CmsFlexCacheVariation(key);
639             m_keyCache.put(key.getResource(), variationMap);
640             if (LOG.isDebugEnabled()) {
641                 LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_ADD_KEY_1, key.getResource()));
642             }
643         }
644         // If != null the key is already in the cache, so we just do nothing
645
}
646
647     /**
648      * Removes an entry from the cache.<p>
649      *
650      * @param key the key which describes the entry to remove from the cache
651      */

652     void remove(CmsFlexCacheKey key) {
653
654         if (!isEnabled()) {
655             return;
656         }
657         Object JavaDoc o = m_keyCache.get(key.getResource());
658         if (o != null) {
659             //Object old = ((HashMap)o).remove(key.Variation);
660
Object JavaDoc old = ((HashMap JavaDoc)o).get(key.getVariation());
661             if (old != null) {
662                 getEntryLruCache().remove((I_CmsLruCacheObject)old);
663             }
664         }
665     }
666
667     /**
668      * Emptys the cache completely.<p>
669      */

670     private synchronized void clear() {
671
672         if (!isEnabled()) {
673             return;
674         }
675         m_keyCache.clear();
676         m_size = 0;
677
678         m_variationCache.clear();
679
680         if (LOG.isInfoEnabled()) {
681             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_CLEAR_0));
682         }
683     }
684
685     /**
686      * Internal method to perform cache clearance.<p>
687      *
688      * It clears "one half" of the cache, i.e. either
689      * the online or the offline parts.
690      * A parameter is used to indicate if only
691      * the entries or keys and entries are to be cleared.<p>
692      *
693      * @param suffix used to distinguish between "[Online]" and "[Offline]" entries
694      * @param entriesOnly if <code>true</code>, only entries will be cleared, otherwise
695      * the entries and the keys will be cleared
696      */

697     private synchronized void clearAccordingToSuffix(String JavaDoc suffix, boolean entriesOnly) {
698
699         Set JavaDoc keys = new HashSet JavaDoc(m_keyCache.keySet());
700         Iterator JavaDoc i = keys.iterator();
701         while (i.hasNext()) {
702             String JavaDoc s = (String JavaDoc)i.next();
703             if (s.endsWith(suffix)) {
704                 CmsFlexCacheVariation v = (CmsFlexCacheVariation)m_keyCache.get(s);
705                 if (entriesOnly) {
706                     // Clear only entry
707
m_size -= v.m_map.size();
708                     Iterator JavaDoc allEntries = v.m_map.values().iterator();
709                     while (allEntries.hasNext()) {
710                         I_CmsLruCacheObject nextObject = (I_CmsLruCacheObject)allEntries.next();
711                         allEntries.remove();
712                         m_variationCache.remove(nextObject);
713                     }
714                     v.m_map = new Hashtable JavaDoc(INITIAL_CAPACITY_VARIATIONS);
715                 } else {
716                     // Clear key and entry
717
m_size -= v.m_map.size();
718                     Iterator JavaDoc allEntries = v.m_map.values().iterator();
719                     while (allEntries.hasNext()) {
720                         I_CmsLruCacheObject nextObject = (I_CmsLruCacheObject)allEntries.next();
721                         allEntries.remove();
722                         m_variationCache.remove(nextObject);
723                     }
724
725                     v.m_map = null;
726                     v.m_key = null;
727                     m_keyCache.remove(s);
728                 }
729             }
730         }
731         if (LOG.isInfoEnabled()) {
732             LOG.info(Messages.get().getBundle().key(
733                 Messages.LOG_FLEXCACHE_CLEAR_HALF_2,
734                 suffix,
735                 new Boolean JavaDoc(entriesOnly)));
736         }
737     }
738
739     /**
740      * Clears all entries in the cache, online or offline.<p>
741      *
742      * The keys are not cleared.<p>
743      *
744      * Only users with administrator permissions are allowed
745      * to perform this operation.<p>
746      */

747     private synchronized void clearEntries() {
748
749         if (!isEnabled()) {
750             return;
751         }
752         if (LOG.isInfoEnabled()) {
753             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_CLEAR_ALL_0));
754         }
755         // create new set to avoid ConcurrentModificationExceptions
756
Set JavaDoc cacheKeys = new HashSet JavaDoc(m_keyCache.keySet());
757         Iterator JavaDoc i = cacheKeys.iterator();
758         while (i.hasNext()) {
759             CmsFlexCacheVariation v = (CmsFlexCacheVariation)m_keyCache.get(i.next());
760             Iterator JavaDoc allEntries = v.m_map.values().iterator();
761             while (allEntries.hasNext()) {
762                 I_CmsLruCacheObject nextObject = (I_CmsLruCacheObject)allEntries.next();
763                 allEntries.remove();
764                 m_variationCache.remove(nextObject);
765             }
766             v.m_map = new Hashtable JavaDoc(INITIAL_CAPACITY_VARIATIONS);
767         }
768         m_size = 0;
769     }
770
771     /**
772      * Clears all entries and all keys from offline projects in the cache.<p>
773      *
774      * Cached resources from the online project are not touched.<p>
775      *
776      * Only users with administrator permissions are allowed
777      * to perform this operation.<p>
778      */

779     private void clearOffline() {
780
781         if (!isEnabled()) {
782             return;
783         }
784         if (LOG.isInfoEnabled()) {
785             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_CLEAR_KEYS_AND_ENTRIES_0));
786         }
787         clearAccordingToSuffix(CACHE_OFFLINESUFFIX, false);
788     }
789
790     /**
791      * Clears all entries from offline projects in the cache.<p>
792      *
793      * The keys from the offline projects are not cleared.
794      * Cached resources from the online project are not touched.<p>
795      *
796      * Only users with administrator permissions are allowed
797      * to perform this operation.<p>
798      */

799     private void clearOfflineEntries() {
800
801         if (!isEnabled()) {
802             return;
803         }
804         if (LOG.isInfoEnabled()) {
805             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_CLEAR_OFFLINE_ENTRIES_0));
806         }
807         clearAccordingToSuffix(CACHE_OFFLINESUFFIX, true);
808     }
809
810     /**
811      * Clears all entries and all keys from the online project in the cache.<p>
812      *
813      * Cached resources from the offline projects are not touched.<p>
814      *
815      * Only users with administrator permissions are allowed
816      * to perform this operation.<p>
817      */

818     private void clearOnline() {
819
820         if (!isEnabled()) {
821             return;
822         }
823         if (LOG.isInfoEnabled()) {
824             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_CLEAR_ONLINE_KEYS_AND_ENTRIES_0));
825         }
826         clearAccordingToSuffix(CACHE_ONLINESUFFIX, false);
827     }
828
829     /**
830      * Clears all entries from the online project in the cache.<p>
831      *
832      * The keys from the online project are not cleared.
833      * Cached resources from the offline projects are not touched.<p>
834      *
835      * Only users with administrator permissions are allowed
836      * to perform this operation.<p>
837      */

838     private void clearOnlineEntries() {
839
840         if (!isEnabled()) {
841             return;
842         }
843         if (LOG.isInfoEnabled()) {
844             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_CLEAR_ONLINE_ENTRIES_0));
845         }
846         clearAccordingToSuffix(CACHE_ONLINESUFFIX, true);
847     }
848
849     /**
850      * This method purges the JSP repository dirs,
851      * i.e. it deletes all JSP files that OpenCms has written to the
852      * real FS.<p>
853      *
854      * Obviously this method must be used with caution.
855      * Purpose of this method is to allow
856      * a complete purge of all JSP pages on a machine after
857      * a major update of JSP templates was made.<p>
858      */

859     private synchronized void purgeJspRepository() {
860
861         if (LOG.isInfoEnabled()) {
862             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_WILL_PURGE_JSP_REPOSITORY_0));
863         }
864
865         File JavaDoc d;
866         d = new File JavaDoc(org.opencms.loader.CmsJspLoader.getJspRepository() + REPOSITORY_ONLINE + File.separator);
867         CmsFileUtil.purgeDirectory(d);
868
869         d = new File JavaDoc(org.opencms.loader.CmsJspLoader.getJspRepository() + REPOSITORY_OFFLINE + File.separator);
870         CmsFileUtil.purgeDirectory(d);
871
872         clear();
873         if (LOG.isInfoEnabled()) {
874             LOG.info(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_PURGED_JSP_REPOSITORY_0));
875         }
876     }
877
878     /**
879      * Save a value to the cache.<p>
880      *
881      * @param key the key under shich the value is saved
882      * @param theCacheEntry the entry to cache
883      */

884     private void put(CmsFlexCacheKey key, CmsFlexCacheEntry theCacheEntry) {
885
886         Object JavaDoc o = m_keyCache.get(key.getResource());
887         if (key.getTimeout() > 0) {
888             theCacheEntry.setDateExpiresToNextTimeout(key.getTimeout());
889         }
890         if (o != null) {
891             // We already have a variation map for this resource
892
Map JavaDoc m = ((CmsFlexCacheVariation)o).m_map;
893             boolean wasAdded = true;
894             if (!m.containsKey(key.getVariation())) {
895                 wasAdded = m_variationCache.add(theCacheEntry);
896             } else {
897                 wasAdded = m_variationCache.touch(theCacheEntry);
898             }
899
900             if (wasAdded) {
901                 theCacheEntry.setVariationData(key.getVariation(), m);
902                 m.put(key.getVariation(), theCacheEntry);
903             }
904         } else {
905             // No variation map for this resource yet, so create one
906
CmsFlexCacheVariation list = new CmsFlexCacheVariation(key);
907
908             boolean wasAdded = m_variationCache.add(theCacheEntry);
909
910             if (wasAdded) {
911                 theCacheEntry.setVariationData(key.getVariation(), list.m_map);
912                 list.m_map.put(key.getVariation(), theCacheEntry);
913                 m_keyCache.put(key.getResource(), list);
914             }
915         }
916
917         if (LOG.isDebugEnabled()) {
918             LOG.debug(Messages.get().getBundle().key(
919                 Messages.LOG_FLEXCACHE_ADDED_ENTRY_FOR_RESOURCE_WITH_VARIATION_3,
920                 new Integer JavaDoc(m_size),
921                 key.getResource(),
922                 key.getVariation()));
923             LOG.debug(Messages.get().getBundle().key(Messages.LOG_FLEXCACHE_ADDED_ENTRY_1, theCacheEntry.toString()));
924         }
925     }
926 }
Popular Tags