001: package org.apache.ojb.broker.cache;
002:
003: /* Copyright 2003-2005 The Apache Software Foundation
004: *
005: * Licensed under the Apache License, Version 2.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: import org.apache.commons.lang.builder.ToStringBuilder;
019: import org.apache.commons.lang.builder.ToStringStyle;
020: import org.apache.ojb.broker.Identity;
021: import org.apache.ojb.broker.PersistenceBroker;
022:
023: import java.lang.ref.SoftReference;
024: import java.util.HashMap;
025: import java.util.Map;
026: import java.util.Properties;
027:
028: /**
029: * Simple, flexible local {@link ObjectCache} implementation using a
030: * {@link java.util.HashMap} to cache given objects.
031: * <p>
032: * The cache uses soft-references which allows objects (softly) referenced by
033: * the cache to be reclaimed by the Java Garbage Collector when they are not
034: * longer referenced elsewhere.
035: * </p>
036: * <p>
037: * NOTE: Handle with care! If multiple PB instances are used (OJB standard behavior) you
038: * will run into synchronization problems.
039: * </p>
040: * <p>
041: * Implementation configuration properties:
042: * </p>
043: *
044: * <table cellspacing="2" cellpadding="2" border="3" frame="box">
045: * <tr>
046: * <td><strong>Property Key</strong></td>
047: * <td><strong>Property Values</strong></td>
048: * </tr>
049: * <tr>
050: * <td>timeout</td>
051: * <td>
052: * Lifetime of the cached objects in seconds.
053: * If expired the cached object was not returned
054: * on lookup call (and removed from cache).
055: * </td>
056: * </tr>
057: * </table>
058: *
059: * <br/>
060: *
061: * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
062: * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
063: * @version $Id: ObjectCacheLocalDefaultImpl.java,v 1.5.2.2 2005/12/21 22:24:15 tomdz Exp $
064: */
065: public class ObjectCacheLocalDefaultImpl implements ObjectCache {
066: private static final String TIMEOUT = "timeout";
067:
068: /**
069: * the hashtable holding all cached object
070: */
071: protected Map objectTable = new HashMap();
072:
073: /**
074: * Timeout of the cached objects.
075: */
076: private long timeout = 1000 * 60 * 15;
077:
078: /**
079: *
080: */
081: public ObjectCacheLocalDefaultImpl(PersistenceBroker broker,
082: Properties prop) {
083: timeout = prop == null ? timeout : (Long.parseLong(prop
084: .getProperty(TIMEOUT, "" + timeout))) * 1000;
085: }
086:
087: /**
088: * Clear ObjectCache. I.e. remove all entries for classes and objects.
089: */
090: public void clear() {
091: objectTable.clear();
092: }
093:
094: /**
095: * Makes object persistent to the Objectcache.
096: * I'm using soft-references to allow gc reclaim unused objects
097: * even if they are still cached.
098: */
099: public void cache(Identity oid, Object obj) {
100: if ((obj != null)) {
101: SoftReference ref = new SoftReference(new CacheEntry(obj));
102: objectTable.put(oid, ref);
103: }
104: }
105:
106: public boolean cacheIfNew(Identity oid, Object obj) {
107: if (objectTable.get(oid) == null) {
108: cache(oid, obj);
109: return true;
110: }
111: return false;
112: }
113:
114: /**
115: * Lookup object with Identity oid in objectTable.
116: * Returns null if no matching id is found
117: */
118: public Object lookup(Identity oid) {
119: CacheEntry entry = null;
120: SoftReference ref = (SoftReference) objectTable.get(oid);
121: if (ref != null) {
122: entry = (CacheEntry) ref.get();
123: if (entry == null
124: || entry.lifetime < System.currentTimeMillis()) {
125: objectTable.remove(oid); // Soft-referenced Object reclaimed by GC
126: // timeout, so set null
127: entry = null;
128: }
129: }
130: return entry != null ? entry.object : null;
131: }
132:
133: /**
134: * Removes an Object from the cache.
135: */
136: public void remove(Identity oid) {
137: if (oid != null) {
138: objectTable.remove(oid);
139: }
140: }
141:
142: public String toString() {
143: ToStringBuilder buf = new ToStringBuilder(this ,
144: ToStringStyle.DEFAULT_STYLE);
145: buf.append("Count of cached objects", objectTable.keySet()
146: .size());
147: return buf.toString();
148: }
149:
150: //-----------------------------------------------------------
151: // inner class
152: //-----------------------------------------------------------
153: class CacheEntry {
154: long lifetime;
155: Object object;
156:
157: public CacheEntry(Object object) {
158: this.object = object;
159: lifetime = System.currentTimeMillis() + timeout;
160: }
161: }
162:
163: }
|