001: package org.tigris.scarab.services.cache;
002:
003: /* ================================================================
004: * Copyright (c) 2001 Collab.Net. 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 are
008: * 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 the
015: * documentation and/or other materials provided with the distribution.
016: *
017: * 3. The end-user documentation included with the redistribution, if
018: * any, must include the following acknowlegement: "This product includes
019: * software developed by Collab.Net <http://www.Collab.Net/>."
020: * Alternately, this acknowlegement may appear in the software itself, if
021: * and wherever such third-party acknowlegements normally appear.
022: *
023: * 4. The hosted project names must not be used to endorse or promote
024: * products derived from this software without prior written
025: * permission. For written permission, please contact info@collab.net.
026: *
027: * 5. Products derived from this software may not use the "Tigris" or
028: * "Scarab" names nor may "Tigris" or "Scarab" appear in their names without
029: * prior written permission of Collab.Net.
030: *
031: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
032: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
033: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
034: * IN NO EVENT SHALL COLLAB.NET OR ITS CONTRIBUTORS BE LIABLE FOR ANY
035: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
036: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
037: * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
038: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
039: * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
040: * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
041: * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
042: *
043: * ====================================================================
044: *
045: * This software consists of voluntary contributions made by many
046: * individuals on behalf of Collab.Net.
047: */
048:
049: import java.io.Serializable;
050:
051: import org.apache.commons.lang.ObjectUtils;
052: import org.apache.fulcrum.pool.Recyclable;
053: import org.apache.log4j.Logger;
054:
055: /**
056: *
057: *
058: * @author <a href="mailto:jmcnally@collab.net">John McNally</a>
059: * @version $Id: ScarabCacheKey.java 9255 2004-11-14 21:07:04Z dep4b $
060: */
061: public class ScarabCacheKey implements Serializable, Recyclable {
062: private static final Logger LOG = Logger
063: .getLogger("org.apache.torque");
064:
065: private int n;
066: private Serializable instanceOrClass;
067: private String method;
068: private Serializable arg1;
069: private Serializable arg2;
070: private Serializable arg3;
071: private Serializable[] moreThanThree;
072:
073: /**
074: * The disposed flag.
075: */
076: private boolean disposed;
077:
078: public ScarabCacheKey() {
079: recycle();
080: }
081:
082: public ScarabCacheKey(Serializable instanceOrClass, String method) {
083: init(instanceOrClass, method);
084: }
085:
086: public ScarabCacheKey(Serializable instanceOrClass, String method,
087: Serializable arg1) {
088: init(instanceOrClass, method, arg1);
089: }
090:
091: public ScarabCacheKey(Serializable instanceOrClass, String method,
092: Serializable arg1, Serializable arg2) {
093: init(instanceOrClass, method, arg1, arg2);
094: }
095:
096: public ScarabCacheKey(Serializable instanceOrClass, String method,
097: Serializable arg1, Serializable arg2, Serializable arg3) {
098: init(instanceOrClass, method, arg1, arg2, arg3);
099: }
100:
101: public ScarabCacheKey(Serializable[] moreThanThree) {
102: init(moreThanThree);
103: }
104:
105: /**
106: * Initialize key for method with no arguments.
107: *
108: * @param instanceOrClass the Object on which the method is invoked. if
109: * the method is static, a String representing the class name is used.
110: * @param method the method name
111: */
112: public void init(Serializable instanceOrClass, String method) {
113: n = 0;
114: this .instanceOrClass = instanceOrClass;
115: this .method = method;
116: }
117:
118: /**
119: * Initialize key for method with one argument.
120: *
121: * @param instanceOrClass the Object on which the method is invoked. if
122: * the method is static, a String representing the class name is used.
123: * @param method the method name
124: * @param arg1 first method arg, may be null
125: */
126: public void init(Serializable instanceOrClass, String method,
127: Serializable arg1) {
128: n = 1;
129: this .instanceOrClass = instanceOrClass;
130: this .method = method;
131: this .arg1 = arg1;
132: }
133:
134: /**
135: * Initialize key for method with two arguments.
136: *
137: * @param instanceOrClass the Object on which the method is invoked. if
138: * the method is static, a String representing the class name is used.
139: * @param method the method name
140: * @param arg1 first method arg, may be null
141: * @param arg2 second method arg, may be null
142: */
143: public void init(Serializable instanceOrClass, String method,
144: Serializable arg1, Serializable arg2) {
145: n = 2;
146: this .instanceOrClass = instanceOrClass;
147: this .method = method;
148: this .arg1 = arg1;
149: this .arg2 = arg2;
150: }
151:
152: /**
153: * Initialize key for method with two arguments.
154: *
155: * @param instanceOrClass the Object on which the method is invoked. if
156: * the method is static, a String representing the class name is used.
157: * @param method the method name
158: * @param arg1 first method arg, may be null
159: * @param arg2 second method arg, may be null
160: */
161: public void init(Serializable instanceOrClass, String method,
162: Serializable arg1, Serializable arg2, Serializable arg3) {
163: n = 3;
164: this .instanceOrClass = instanceOrClass;
165: this .method = method;
166: this .arg1 = arg1;
167: this .arg2 = arg2;
168: this .arg3 = arg3;
169: }
170:
171: /**
172: * Initialize key for method with more than two arguments.
173: *
174: * @param keys <code>Serializable[]</code> where
175: * [0]=>the Object on which the method is invoked
176: * if the method is static, a String representing the class name is used.
177: * [1]=>the method name
178: * [n] where n>1 are the method arguments
179: */
180: public void init(Serializable[] keys) {
181: n = keys.length - 2;
182: this .instanceOrClass = keys[0];
183: this .method = (String) keys[1];
184: if (n > 0) {
185: this .arg1 = keys[2];
186: if (n > 1) {
187: this .arg2 = keys[3];
188: if (n > 2) {
189: // TODO: this is a bug, but it matches a bug in torque
190: // and we use this cache as an alternative to the jcs
191: // cache in some cases. Need to update it once we have
192: // time to upgrade torque.
193: //this.arg3 = keys[4];
194: this .arg2 = keys[4];
195: if (n > 3) {
196: this .moreThanThree = keys;
197: }
198: }
199: }
200: }
201: }
202:
203: public boolean equals(Object obj) {
204: boolean equal = false;
205: if (obj instanceof ScarabCacheKey) {
206: ScarabCacheKey sck = (ScarabCacheKey) obj;
207: equal = sck.n == n;
208: equal &= ObjectUtils.equals(sck.instanceOrClass,
209: instanceOrClass);
210: equal &= ObjectUtils.equals(sck.method, method);
211: if (n > 0) {
212: equal &= ObjectUtils.equals(sck.arg1, arg1);
213: if (n > 1) {
214: equal &= ObjectUtils.equals(sck.arg2, arg2);
215: if (n > 2) {
216: equal &= ObjectUtils.equals(sck.arg3, arg3);
217: if (n > 3) {
218: for (int i = 5; i < n + 2; i++) {
219: equal &= ObjectUtils.equals(
220: sck.moreThanThree[i],
221: moreThanThree[i]);
222: }
223: }
224: }
225: }
226: }
227:
228: if (equal) {
229: LOG.debug("Saved db hit on " + instanceOrClass + "::"
230: + method + ". YAY!");
231: }
232: }
233: return equal;
234: }
235:
236: public int hashCode() {
237: int h = instanceOrClass.hashCode();
238: h += method.hashCode();
239: if (n > 0) {
240: h += (arg1 == null ? 0 : arg1.hashCode());
241: if (n > 1) {
242: h += (arg2 == null ? 0 : arg2.hashCode());
243: if (n > 2) {
244: h += (arg3 == null ? 0 : arg3.hashCode());
245: if (n > 3) {
246: for (int i = 5; i < n + 2; i++) {
247: h += (moreThanThree[i] == null ? 0
248: : moreThanThree[i].hashCode());
249: }
250: }
251: }
252: }
253: }
254: return h;
255: }
256:
257: // ****************** Recyclable implementation ************************
258: /**
259: * Recycles the object by removing its disposed flag.
260: */
261: public void recycle() {
262: disposed = false;
263: }
264:
265: /**
266: * Disposes the object after use. The method is called when the
267: * object is returned to its pool. The dispose method must call
268: * its super.
269: */
270: public void dispose() {
271: disposed = true;
272: instanceOrClass = null;
273: method = null;
274: arg1 = null;
275: arg2 = null;
276: arg3 = null;
277: moreThanThree = null;
278: }
279:
280: /**
281: * Checks whether the object is disposed.
282: *
283: * @return true, if the object is disposed.
284: */
285: public boolean isDisposed() {
286: return disposed;
287: }
288: }
|