001: /*
002: * CoadunationLib: The coaduntion implementation library.
003: * Copyright (C) 2006 Rift IT Contracting
004: *
005: * This library is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU Lesser General Public
007: * License as published by the Free Software Foundation; either
008: * version 2.1 of the License, or (at your option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
013: * Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public
016: * License along with this library; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
018: *
019: * ProxyCache.java
020: *
021: * This object is responsible for caching the proxy entries. They will be
022: * released after x number milli seconds of in activity. Forcing a reconnect
023: * and the release of a resource.
024: */
025:
026: // the package path
027: package com.rift.coad.lib.bean;
028:
029: // java imports
030: import java.util.Date;
031: import java.util.HashMap;
032: import java.util.Iterator;
033: import java.util.Map;
034: import java.util.Vector;
035:
036: // logging import
037: import org.apache.log4j.Logger;
038:
039: // coadunation imports
040: import com.rift.coad.lib.cache.Cache;
041: import com.rift.coad.lib.cache.CacheEntry;
042: import com.rift.coad.lib.common.RandomGuid;
043: import com.rift.coad.lib.configuration.ConfigurationFactory;
044: import com.rift.coad.lib.configuration.Configuration;
045: import com.rift.coad.lib.thread.ThreadStateMonitor;
046:
047: /**
048: * This object is responsible for caching the proxy entries. They will be
049: * released after x number milli seconds of in activity. Forcing a reconnect
050: * and the release of a resource.
051: *
052: * @author Brett Chaldecott
053: */
054: public class ProxyCache implements Cache {
055:
056: // class constants
057: private final static String CACHE_EXPIRY_TIME = "proxy_cache_expiry";
058: private final static long CACHE_EXPIRY_TIME_DEFAULT = 60 * 1000;
059:
060: // private member variables
061: protected static Logger log = Logger.getLogger(ProxyCache.class
062: .getName());
063:
064: // private member variables
065: private Map cacheEntries = new HashMap();
066: private long defaultCacheExpiryTime = 0;
067: private ThreadStateMonitor status = new ThreadStateMonitor();
068:
069: /**
070: * Creates a new instance of ProxyCache
071: *
072: * @exception BeanException
073: */
074: public ProxyCache() throws BeanException {
075: try {
076: Configuration config = ConfigurationFactory.getInstance()
077: .getConfig(ProxyCache.class);
078: defaultCacheExpiryTime = config.getLong(CACHE_EXPIRY_TIME,
079: CACHE_EXPIRY_TIME_DEFAULT);
080: } catch (Exception ex) {
081: log.error(
082: "Failed to start the ProxyCache object because : "
083: + ex.getMessage(), ex);
084: throw new BeanException(
085: "Failed to start the ProxyCache object because : "
086: + ex.getMessage(), ex);
087: }
088: }
089:
090: /**
091: * This method is called to perform garbage collection on the cache entries.
092: */
093: public void garbageCollect() {
094: Map cacheEntries = new HashMap();
095: synchronized (this .cacheEntries) {
096: cacheEntries.putAll(this .cacheEntries);
097: }
098:
099: // the start time
100: Date currentTime = new Date();
101: for (Iterator iter = cacheEntries.keySet().iterator(); iter
102: .hasNext();) {
103: Object key = iter.next();
104: ProxyCacheEntry cacheEntry = (ProxyCacheEntry) cacheEntries
105: .get(key);
106: if (cacheEntry.isExpired(currentTime)) {
107: synchronized (this .cacheEntries) {
108: this .cacheEntries.remove(key);
109: }
110: cacheEntry.cacheRelease();
111: }
112: }
113: }
114:
115: /**
116: * This method is called to forcibly remove everything from the cache.
117: */
118: public void clear() {
119: Map cacheEntries = new HashMap();
120: synchronized (this .cacheEntries) {
121: status.terminate(false);
122: cacheEntries.putAll(this .cacheEntries);
123: this .cacheEntries.clear();
124: }
125:
126: for (Iterator iter = cacheEntries.keySet().iterator(); iter
127: .hasNext();) {
128: ProxyCacheEntry cacheEntry = (ProxyCacheEntry) cacheEntries
129: .get(iter.next());
130: cacheEntry.cacheRelease();
131: }
132: }
133:
134: /**
135: * This mehtod returns true if the cache contains the checked entry.
136: *
137: * @return TRUE if the cache contains the checked entry.
138: * @param cacheEntry The entry to perform the check for.
139: */
140: public boolean contains(Object cacheEntry) {
141: // this method assumes the cache entry is the handler
142: synchronized (cacheEntries) {
143: return cacheEntries.containsKey(cacheEntry);
144: }
145: }
146:
147: /**
148: * This method adds a new entry to the proxy cache.
149: *
150: * @param timeout The timeout for this object.
151: * @param proxy The proxy to add to the cache.
152: * @param handler The handler to perform the check for.
153: */
154: public void addCacheEntry(long timeout, Object proxy,
155: CacheEntry handler) throws BeanException {
156: synchronized (cacheEntries) {
157: checkStatus();
158: long cacheTimeout = timeout;
159: if (timeout == -1) {
160: cacheTimeout = defaultCacheExpiryTime;
161: }
162: cacheEntries.put(handler, new ProxyCacheEntry(cacheTimeout,
163: proxy, handler));
164: }
165: }
166:
167: /**
168: * This method will check to see if the cache has been terminated or not.
169: *
170: * @exception BeanException
171: */
172: private void checkStatus() throws BeanException {
173: if (status.isTerminated()) {
174: throw new BeanException(
175: "The proxy cache has been shut down.");
176: }
177: }
178: }
|