001: /* Copyright 2002 The JA-SIG Collaborative. All rights reserved.
002: * See license distributed with this file and
003: * available online at http://www.uportal.org/license.html
004: */
005:
006: package org.jasig.portal.concurrency.caching;
007:
008: import java.util.HashMap;
009: import java.util.Iterator;
010: import java.util.Map;
011:
012: import org.jasig.portal.EntityIdentifier;
013: import org.jasig.portal.EntityTypes;
014: import org.jasig.portal.IBasicEntity;
015: import org.jasig.portal.concurrency.CachingException;
016: import org.jasig.portal.concurrency.IEntityCache;
017: import org.jasig.portal.concurrency.IEntityCachingService;
018: import org.jasig.portal.properties.PropertiesManager;
019:
020: /**
021: * Caching service reference implementation.
022: * @author Dan Ellentuck
023: * @version $Revision: 36565 $
024: */
025: public class ReferenceEntityCachingService implements
026: IEntityCachingService {
027: // Singleton instance:
028: private static IEntityCachingService singleton;
029:
030: // Our cache of caches:
031: private Map caches = new HashMap(10);
032:
033: // The following properties can be overridden via settings in portal.properties.
034: // Here they are initialized to their defaults.
035:
036: // Will there be peer caches on other servers?
037: boolean multiServer = false;
038:
039: // Default maximum cache size.
040: int defaultMaxCacheSize = 1000;
041:
042: // The interval between cache updates; defaults to 60 seconds.
043: int defaultSweepIntervalMillis = 60 * 1000;
044:
045: // The interval after which a cache entry may be purged if it has not
046: // been touched. Defaults to 30 minutes.
047: int defaultMaxIdleTimeMillis = 30 * 60 * 1000;
048:
049: /* Fudge factor in milliseconds, for reconciling system clocks on
050: * different hosts. We retrieve invalidations between now and
051: * the time of our last retrieval -- plus the fudge factor.
052: * Only used when inMemory == false. Defaults to 5000.
053: */
054: int clockToleranceMillis = 5000;
055:
056: /**
057: * ReferenceEntityCachingService constructor comment.
058: */
059: public ReferenceEntityCachingService() throws CachingException {
060: super ();
061: initialize();
062: }
063:
064: /**
065: * Adds the entity to the cache.
066: * @param ent org.jasig.portal.IBasicEntity
067: * @exception org.jasig.portal.concurrency.CachingException
068: */
069: public void add(IBasicEntity ent) throws CachingException {
070: EntityIdentifier ei = ent.getEntityIdentifier();
071: Class classRef = ei.getType();
072: IEntityCache entCache = getCache(classRef);
073: entCache.add(ent);
074: }
075:
076: /**
077: * Create a cache for a specific entity type.
078: */
079: IEntityCache createCache(Class type) throws CachingException {
080: int max = 0, idle = 0, interval = 0;
081: String service = "org.jasig.portal.concurrency.IEntityCachingService";
082: String sep = ".";
083:
084: try {
085: max = PropertiesManager.getPropertyAsInt(service + sep
086: + type.getName() + sep + "maxCacheSize");
087: } catch (Exception e) {
088: max = defaultMaxCacheSize;
089: }
090:
091: try {
092: idle = PropertiesManager.getPropertyAsInt(service + sep
093: + type.getName() + sep + "MaxIdleTime");
094: idle *= 1000;
095: } catch (Exception e) {
096: idle = defaultMaxIdleTimeMillis;
097: }
098:
099: try {
100: interval = PropertiesManager.getPropertyAsInt(service + sep
101: + type.getName() + sep + "sweepInterval");
102: interval *= 1000;
103: } catch (Exception e) {
104: interval = defaultSweepIntervalMillis;
105: }
106:
107: return newCache(type, max, idle, interval);
108: }
109:
110: /**
111: * Create a cache for each known entity type.
112: */
113: private void createCaches() throws CachingException {
114: for (Iterator types = EntityTypes.singleton()
115: .getAllEntityTypes(); types.hasNext();) {
116: Class type = (Class) types.next();
117: IEntityCache cache = createCache(type);
118: getCaches().put(type, cache);
119: }
120: }
121:
122: /**
123: * Returns the cached entity identified by type and key.
124: * @param type Class
125: * @param key String
126: * @return IBasicEntity entity
127: * @exception org.jasig.portal.concurrency.CachingException
128: */
129: public IBasicEntity get(Class type, String key)
130: throws CachingException {
131: return getCache(type).get(key);
132: }
133:
134: /**
135: * Returns the <code>IEntityCache</code> for <code>type</code>.
136: * @param type Class
137: * @return IEntityCache
138: * @exception org.jasig.portal.concurrency.CachingException
139: */
140: public IEntityCache getCache(Class type) throws CachingException {
141: IEntityCache c = (IEntityCache) getCaches().get(type);
142: if (c == null) {
143: c = createCache(type);
144: getCaches().put(type, c);
145: }
146: return c;
147: }
148:
149: /**
150: * @return java.util.Map
151: */
152: protected java.util.Map getCaches() {
153: return caches;
154: }
155:
156: /**
157: */
158: private void initialize() throws CachingException {
159: loadDefaultProperties();
160: // createCaches();
161: }
162:
163: /**
164: * Loads default properties applied to caches if not specifically
165: * overridden.
166: */
167: private void loadDefaultProperties() {
168: try {
169: multiServer = PropertiesManager
170: .getPropertyAsBoolean("org.jasig.portal.concurrency.multiServer");
171: } catch (Exception e) { /* defaults to false */
172: }
173:
174: try {
175: int defaultSweepIntervalSecs = PropertiesManager
176: .getPropertyAsInt("org.jasig.portal.concurrency.IEntityCachingService.defaultSweepInterval");
177: defaultSweepIntervalMillis = defaultSweepIntervalSecs * 1000;
178: } catch (Exception ex) { /* defaults to 60 seconds */
179: }
180:
181: try {
182: defaultMaxCacheSize = PropertiesManager
183: .getPropertyAsInt("org.jasig.portal.concurrency.IEntityCachingService.defaultMaxCacheSize");
184: } catch (Exception ex) { /* defaults to 1000 */
185: }
186:
187: try {
188: int defaultMaxIdleTimeSecs = PropertiesManager
189: .getPropertyAsInt("org.jasig.portal.concurrency.IEntityCachingService.defaultMaxIdleTime");
190: defaultMaxIdleTimeMillis = defaultMaxIdleTimeSecs * 1000;
191: } catch (Exception ex) { /* defaults to 30 minutes */
192: }
193:
194: if (multiServer) {
195: try {
196: int clockTolerance = PropertiesManager
197: .getPropertyAsInt("org.jasig.portal.concurrency.clockTolerance");
198: clockToleranceMillis = clockTolerance;
199: } catch (Exception ex) { /* defaults to 5000. */
200: }
201: }
202:
203: }
204:
205: /**
206: * Factory method returns a new instance of <code>IEntityCache</code>
207: * for <code>type</code>.
208: * @param type Class
209: * @param maxSize int - the maximum size of the cache.
210: * @param maxIdleTime int - the idle time in milliseconds after which a cache entry may be purged.
211: * @param sweepInterval int - the period of time in milliseconds between cache sweeps.
212: * @return IEntityCache
213: * @exception org.jasig.portal.concurrency.CachingException
214: */
215: public IEntityCache newCache(Class type, int maxSize,
216: int maxIdleTime, int sweepInterval) throws CachingException {
217: return (multiServer) ? new ReferenceInvalidatingEntityCache(
218: type, maxSize, maxIdleTime, sweepInterval,
219: clockToleranceMillis) : new ReferenceEntityCache(type,
220: maxSize, maxIdleTime, sweepInterval);
221: }
222:
223: /**
224: * Removes the cached entity identified by type and key from the cache
225: * and notifies peer caches.
226: * @param type Class
227: * @param key String
228: * @exception org.jasig.portal.concurrency.CachingException
229: */
230: public void remove(Class type, String key) throws CachingException {
231: getCache(type).remove(key);
232: }
233:
234: /**
235: * @param newCaches java.util.Map
236: */
237: protected void setCaches(java.util.Map newCaches) {
238: caches = newCaches;
239: }
240:
241: /**
242: * @return org.jasig.portal.concurrency.IEntityCachingService
243: */
244: public static synchronized IEntityCachingService singleton()
245: throws CachingException {
246: if (singleton == null) {
247: singleton = new ReferenceEntityCachingService();
248: }
249: return singleton;
250: }
251:
252: /**
253: * Updates the entity in the cache and notifies peer caches.
254: * @param ent org.jasig.portal.IBasicEntity
255: * @exception org.jasig.portal.concurrency.CachingException
256: */
257: public void update(IBasicEntity ent) throws CachingException {
258: getCache(ent.getEntityIdentifier().getType()).update(ent);
259: }
260: }
|