001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: /**
066: * OrderedCache.java
067: *
068: * Copyright 2000, 2001 Jcorporate Ltd.
069: */package com.jcorporate.expresso.core.cache;
070:
071: import org.apache.log4j.Logger;
072:
073: import java.util.Enumeration;
074: import java.util.Vector;
075:
076: /**
077: * Insert the type's description here.
078: * Creation date: (9/7/00 11:42:43 AM)
079: *
080: * @author Administrator
081: */
082: public class OrderedCache implements Cache {
083:
084: private Vector cacheContents = new Vector();
085:
086: private String cacheName = null;
087:
088: private long accessCount = 0;
089:
090: private int maxSize = 0;
091:
092: private static final String this Class = OrderedCache.class
093: .getName();
094:
095: private static final Logger log = Logger
096: .getLogger(OrderedCache.class);
097:
098: /**
099: * OrderedCache constructor comment.
100: */
101: public OrderedCache() {
102: super ();
103: } /* OrderedCache() */
104:
105: /**
106: * addItem method comment.
107: *
108: * @param newItem New item to add.
109: */
110: public void addItem(CacheEntry newItem) {
111:
112: /* if we're now over our max size, we must find an item to drop */
113: /* from the cache */
114: if ((maxSize > 0) && (cacheContents.size() >= maxSize)) {
115: long minUsed = java.lang.Long.MAX_VALUE;
116: CacheEntry leastUsedItem = null;
117: CacheEntry oneItem = null;
118:
119: synchronized (cacheContents) {
120: for (Enumeration e = cacheContents.elements(); e
121: .hasMoreElements();) {
122: oneItem = (CacheEntry) e.nextElement();
123:
124: /* if we hit an "expired" item, we remove it & now have */
125: /* room to insert */
126: if (oneItem.isExpired()) {
127: break;
128: }
129: if (oneItem.getUsedCount() < minUsed) {
130: leastUsedItem = oneItem;
131: minUsed = oneItem.getUsedCount();
132: }
133: }
134:
135: removeItem(oneItem.getContents());
136: }
137: }
138:
139: cacheContents.addElement(newItem);
140: newItem.clearUsedCount();
141: } /* addItem(CacheEntry) */
142:
143: /**
144: * clear method comment.
145: */
146: public void clear() {
147: synchronized (cacheContents) {
148: cacheContents = new Vector();
149: }
150: } /* clear() */
151:
152: /**
153: * Retrieve the low-level CacheEntry for the cache. This is particularly
154: * useful for debugging or management.
155: *
156: * @param itemKey the cache key to retrieve
157: * @return the CacheEntry for the cache or null.
158: */
159: public CacheEntry getCacheEntry(String itemKey) {
160: CacheEntry oneItem = null;
161: synchronized (cacheContents) {
162: for (Enumeration allItems = cacheContents.elements(); allItems
163: .hasMoreElements();) {
164: oneItem = (CacheEntry) allItems.nextElement();
165:
166: if (oneItem.getKey().equals(itemKey)) {
167: if (oneItem.isExpired()) {
168: removeItem(oneItem.getContents());
169:
170: return null;
171: }
172: oneItem.incrementUsedCount();
173:
174: return oneItem;
175: }
176: }
177: }
178:
179: return null;
180: }
181:
182: /**
183: * removeItem method comment.
184: *
185: * @param itemKey The item key
186: * @return the Cacheable entry
187: */
188: public Cacheable getItem(String itemKey) {
189: accessCount++;
190:
191: CacheEntry oneItem = this .getCacheEntry(itemKey);
192:
193: if (oneItem == null) {
194: return null;
195: } else {
196: return oneItem.getContents();
197: }
198: } /* getItem(String) */
199:
200: /**
201: * getItemCount method comment.
202: *
203: * @return the item count
204: */
205: public int getItemCount() {
206: return cacheContents.size();
207: } /* getItemCount() */
208:
209: /**
210: * Retrieves all the items in this cache May return an empty Vector
211: * if the cache contents have expired.
212: *
213: * @return the actual items or null if no items exist in the cache.
214: */
215: public Vector getItems() {
216: accessCount++;
217:
218: Vector aClone = null;
219: CacheEntry oneEntry = null;
220:
221: synchronized (cacheContents) {
222: if (cacheContents.size() > 0) {
223: oneEntry = (CacheEntry) cacheContents.get(0);
224: if (oneEntry.isExpired()) {
225: this .clear();
226: return new Vector(1);
227: } else {
228: aClone = (Vector) cacheContents.clone();
229: }
230: } else {
231: return new Vector(1);
232: }
233: }
234:
235: Vector v = new Vector(aClone.size());
236: for (Enumeration e = aClone.elements(); e.hasMoreElements();) {
237: oneEntry = (CacheEntry) e.nextElement();
238: v.addElement(oneEntry.getContents());
239: }
240:
241: return v;
242: } /* getItems() */
243:
244: /**
245: * getName method comment.
246: *
247: * @return the cache name
248: */
249: public String getName() {
250: return cacheName;
251: } /* getName() */
252:
253: /**
254: * getUsedCount method comment.
255: *
256: * @return the useage count
257: */
258: public long getUsedCount() {
259: return accessCount;
260: } /* getUsedCount() */
261:
262: /**
263: * Retrieve whether the cache instance is an ordered cache [list based]
264: * or unordered cache. [map based]
265: *
266: * @return true if the cache is an ordered cache.
267: */
268: public boolean isOrdered() {
269: return true;
270: }
271:
272: /**
273: * removeItem method comment.
274: *
275: * @param oldItem the old item to remove
276: */
277: public void removeItem(Cacheable oldItem) {
278: CacheEntry oneItem = null;
279: for (int i = 0; i < cacheContents.size(); i++) {
280:
281: try {
282: oneItem = (CacheEntry) cacheContents.elementAt(i);
283: if (oneItem != null) {
284: if (oneItem.getKey().equals(oldItem.getKey())) {
285: oneItem.clearUsedCount();
286:
287: synchronized (cacheContents) {
288: cacheContents.removeElement(oneItem);
289: }
290: }
291: }
292: } catch (Exception ex) {
293: //Ignore this one! We stepped out of bounds due to
294: //another thread.
295: if (log.isDebugEnabled()) {
296: log.debug("Ignored Exception", ex);
297: }
298: }
299: }
300:
301: } /* removeItem(Cacheable) */
302:
303: /**
304: * Eventually the new way to set items
305: *
306: * @param newItems the new items to add
307: * @throws CacheException upon error
308: */
309: public void setItems(java.util.List newItems) throws CacheException {
310: if (newItems instanceof java.util.Vector) {
311: setItems((Vector) newItems);
312: } else {
313: accessCount++;
314: clear();
315:
316: Object oneObject = null;
317:
318: for (java.util.Iterator e = newItems.iterator(); e
319: .hasNext();) {
320: oneObject = e.next();
321:
322: if (oneObject instanceof Cacheable) {
323: CacheEntry ce = new CacheEntry(
324: (Cacheable) oneObject, -1);
325: addItem(ce);
326: } else {
327: String myName = (this Class + "setItems(Vector)");
328: throw new CacheException(
329: myName
330: + ":Item in vector is of class "
331: + oneObject.getClass().getName()
332: + ", which is not Cacheable - cannot set items");
333: }
334: }
335: return;
336: }
337: }
338:
339: /**
340: * getItemCount method comment.
341: *
342: * @param newItems the new items to add
343: */
344: public void setItems(Vector newItems) throws CacheException {
345: accessCount++;
346: clear();
347:
348: Object oneObject = null;
349:
350: for (Enumeration e = newItems.elements(); e.hasMoreElements();) {
351: oneObject = e.nextElement();
352:
353: if (oneObject instanceof Cacheable) {
354: CacheEntry ce = new CacheEntry((Cacheable) oneObject,
355: -1);
356: addItem(ce);
357: } else {
358: String myName = (this Class + "setItems(Vector)");
359: throw new CacheException(myName
360: + ":Item in vector is of class "
361: + oneObject.getClass().getName()
362: + ", which is not Cacheable - cannot set items");
363: }
364: }
365: } /* setItems(Vector) */
366:
367: /**
368: * setName method comment.
369: *
370: * @param newMaxSize the new maximum size for the cache
371: */
372: public synchronized void setMaxSize(int newMaxSize) {
373: maxSize = newMaxSize;
374: } /* setMaxSize(int) */
375:
376: /**
377: * setName method comment.
378: *
379: * @param newName The new cache name
380: */
381: public synchronized void setName(String newName) {
382: cacheName = newName;
383: } /* setName(String) */
384:
385: } /* OrderedCache */
|