View Javadoc

1   /*   Open Source Java Caching Service
2    *    Copyright (C) 2002 Frank Karlstrøm
3    *    This library is free software; you can redistribute it and/or
4    *    modify it under the terms of the GNU Lesser General Public
5    *    License as published by the Free Software Foundation; either
6    *    version 2.1 of the License, or (at your option) any later version.
7    *
8    *    This library is distributed in the hope that it will be useful,
9    *    but WITHOUT ANY WARRANTY; without even the implied warranty of
10   *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11   *    Lesser General Public License for more details.
12   *
13   *    You should have received a copy of the GNU Lesser General Public
14   *    License along with this library; if not, write to the Free Software
15   *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16   *
17   *    The author can be contacted by email: fjankk@sourceforge.net
18   */
19  package org.fjank.jcache;
20  
21  import java.io.Serializable;
22  
23  import javax.util.jcache.Attributes;
24  import javax.util.jcache.CacheEventListener;
25  import javax.util.jcache.CacheLoader;
26  import javax.util.jcache.InvalidArgumentException;
27  
28  /**
29   * This class defines the attributes an object in the cache can have.
30   */
31  public final class AttributesImpl implements Cloneable, Serializable, Attributes {
32  	private static final int ONE_DAY = 24;
33  	private static final int ONE_HOUR = 60;
34  	private static final int ONE_MINUTE = 60;
35  	/** the time the associated CacheObject was created. */
36  	private long createTime = System.currentTimeMillis();
37  	/** the default time the associated CacheObject should live in the cache */
38  	private long defaultTTL = -1;
39  	/**
40  	 * Is used to specify wich attributes should be set in the attributes
41  	 * object. The differnet attributes wich is valid is defined as public
42  	 * static variables in the {@link Attributes}class.
43  	 */
44  	private long flags;
45  	/** the time the associated CacheObject should be idle in the cache */
46  	private long idleTime;
47  	/** the CacheListener for the associated CacheObject */
48  	private transient CacheEventListener listener;
49  	/** the CacheLoader for the associated CacheObject */
50  	private transient CacheLoader loader;
51  	/** the size for the associated CacheObject */
52  	private int size;
53  	/** the time the associated CacheObject should be live the cache */
54  	private long timeToLive = -1;
55  	/** the version of the associated CacheObject */
56  	private long version;
57  
58  	/**
59  	 * Creates new Attributes
60  	 */
61  	public AttributesImpl() {
62  	}
63  
64  	public AttributesImpl(Attributes attributes) {
65  		this.defaultTTL = attributes.getDefaultTimeToLive();
66  		this.idleTime = attributes.getIdleTime();
67  
68  		this.listener = attributes.getListener();
69  		this.loader = attributes.getLoader();
70  		this.size = attributes.getSize();
71  		this.timeToLive = attributes.getTimeToLive();
72  		this.version = attributes.getVersion();
73  		long flags = 0;
74  
75  		if (attributes.isSet(Attributes.DISTRIBUTE)) {
76  			flags |= Attributes.DISTRIBUTE;
77  		}
78  		if (attributes.isSet(Attributes.NOFLUSH)) {
79  			flags |= Attributes.NOFLUSH;
80  		}
81  		if (attributes.isSet(Attributes.REPLY)) {
82  			flags |= Attributes.REPLY;
83  		}
84  		if (attributes.isSet(Attributes.SYNCHRONIZE)) {
85  			flags |= Attributes.SYNCHRONIZE;
86  		}
87  		if (attributes.isSet(Attributes.SPOOL)) {
88  			flags |= Attributes.SPOOL;
89  		}
90  		if (attributes.isSet(Attributes.GROUP_TTL_DESTROY)) {
91  			flags |= Attributes.GROUP_TTL_DESTROY;
92  		}
93  		if (attributes.isSet(Attributes.ORIGINAL)) {
94  			flags |= Attributes.ORIGINAL;
95  		}
96  		this.flags = flags;
97  	}
98  
99  	public void applyAttributes(Attributes attributes) {
100 		this.idleTime = attributes.getIdleTime();
101 		this.timeToLive = attributes.getTimeToLive();
102 		this.defaultTTL = attributes.getDefaultTimeToLive();
103 		CacheEventListener listener = attributes.getListener();
104 		setListener(Attributes.INVALIDATE_EVENT, listener);
105 	}
106 
107 	public boolean equals(Object arg0) {
108 		if (arg0 instanceof AttributesImpl) {
109 			AttributesImpl obj = (AttributesImpl) arg0;
110 			if (defaultTTL != obj.defaultTTL)
111 				return false;
112 			if (flags != obj.flags)
113 				return false;
114 			if (listener != obj.listener)
115 				return false;
116 			if (loader != obj.loader)
117 				return false;
118 			if (size != obj.size)
119 				return false;
120 			if (timeToLive != obj.timeToLive)
121 				return false;
122 			if (version != obj.version)
123 				return false;
124 			return true;
125 		}
126 		return super.equals(arg0);
127 	}
128 
129 	/**
130 	 * returns the time the object was loaded into the cache. The time is the
131 	 * number of milliseconds since midnight, January 1, 1970 (UTC).
132 	 * 
133 	 * @return the time the object was loaded into the cache. The time is the
134 	 *         number of milliseconds since midnight, January 1, 1970 (UTC).
135 	 */
136 	public long getCreateTime() {
137 		return createTime;
138 	}
139 
140 	public long getDefaultTimeToLive() {
141 		return defaultTTL;
142 	}
143 
144 	/**
145 	 * returns the current value for the idle time interval.
146 	 * 
147 	 * @return the current value for the idle time interval.
148 	 */
149 	public long getIdleTime() {
150 		return idleTime;
151 	}
152 
153 	/**
154 	 * Gets the CacheEventListener.
155 	 * 
156 	 * @author Philippe Fajeau
157 	 * @return The CacheEventListener.
158 	 */
159 	public CacheEventListener getListener() {
160 		return listener;
161 	}
162 
163 	/**
164 	 * returns the {@link CacheLoader}attribute.
165 	 * 
166 	 * @return the {@link CacheLoader}attribute.
167 	 */
168 	public CacheLoader getLoader() {
169 		return loader;
170 	}
171 
172 	/**
173 	 * returns the size of the object. this size is set by the
174 	 * {@link #setSize(int)} method, or in the case of StreamAccess objects, the
175 	 * size is calculated by the cache.
176 	 * 
177 	 * @todo create and implement an online size calculator.
178 	 * @return the size of the object, or 0 if the size has not been set.
179 	 */
180 	public int getSize() {
181 		return size;
182 	}
183 
184 	/**
185 	 * returns the current value for the time to live interval.
186 	 * 
187 	 * @return the current value for the time to live interval.
188 	 */
189 	public long getTimeToLive() {
190 		if (defaultTTL != -1 && timeToLive == -1) {
191 			return defaultTTL;
192 		}
193 		return timeToLive;
194 	}
195 
196 	/**
197 	 * returns the current value of version.
198 	 * 
199 	 * @return the current value of version.
200 	 */
201 	public long getVersion() {
202 		return version;
203 	}
204 
205 	/**
206 	 * Checks wether the flags are set or not.
207 	 * 
208 	 * @param theFlags
209 	 *            the flags to be checked. may be OR-ed together, for wich this
210 	 *            method will return true only if all flags are set.
211 	 * 
212 	 * @return true if the specified attribute is set, false otherwise.
213 	 */
214 	public boolean isSet(final long theFlags) {
215 		return ((this.flags | theFlags) ^ this.flags) == 0;
216 	}
217 
218 	/**
219 	 * resets the Attributes to its default values. The attributes wich are
220 	 * reset are expiration time attributes, time to live, default time to live,
221 	 * idle time and event handlers.
222 	 * 
223 	 * @todo This method should be package private, thus this class should be
224 	 *       moved to org.fjank.jcache, an interface should be extracted, and
225 	 *       that should be public, and in this package.
226 	 */
227 	public void reset() {
228 		AttributesImpl def = new AttributesImpl();
229 		this.idleTime = def.idleTime;
230 		this.timeToLive = def.timeToLive;
231 		this.defaultTTL = def.defaultTTL;
232 		this.listener = def.listener;
233 	}
234 
235 	/**
236 	 * Sets the createTime.
237 	 * 
238 	 * @param aCreateTime
239 	 *            The createTime to set
240 	 */
241 	public void setCreateTime(final long aCreateTime) {
242 		if (aCreateTime < 0) {
243 			return;
244 		}
245 		this.createTime = aCreateTime;
246 	}
247 
248 	/**
249 	 * Will set the maximum time the associated cache object will stay in the
250 	 * cache before it is invalidated. For regions and groups, this will
251 	 * establish a default time to live that is applied individually to each
252 	 * member in the group or region. It will not cause the entire group or
253 	 * region to time out as a whole. For individual objects, the default time
254 	 * to live is equivalent with time to live. If both are set the default time
255 	 * to live is ignored. The time starts when the object is loaded into the
256 	 * cache(by the {@link CacheLoader}objector put by the
257 	 * {@link CacheAccess#replace(Object, Object)}) or when the time to live
258 	 * attribute is set by the
259 	 * {@link CacheLoader#setAttributes(Object,Attributes)} method.
260 	 * 
261 	 * @param ttl
262 	 *            the time to live in seconds. The
263 	 *            {@link #timeToSeconds(int, int, int, int)} can be used to
264 	 *            convert days, hours, minutes to secounds.
265 	 * 
266 	 * @throws InvalidArgumentException
267 	 *             if a negative value for ttl is supplied.
268 	 */
269 	public void setDefaultTimeToLive(final long ttl) throws InvalidArgumentException {
270 		if (ttl < 0) {
271 			throw new InvalidArgumentException("Default time to live must be a positive number.");
272 		}
273 		this.defaultTTL = ttl;
274 	}
275 
276 	/**
277 	 * Is used to specify wich attributes should be set in the attributes
278 	 * object. The different attributes wich is valid is defined as public
279 	 * static variables in the {@link Attributes}class.
280 	 * 
281 	 * @param theFlags
282 	 *            The attributes to set. the attributes may be OR-ed together.
283 	 *            I.e. Attributes.DISTRIBUTE | Attributes.SYNCHRONIZE Invalid
284 	 *            flags are silently ignored. To reset all flags you use 0 as a
285 	 *            parameter. I.e. setFlags(0)
286 	 */
287 	public void setFlags(final long theFlags) {
288 		if (theFlags < 0) {
289 			return;
290 		}
291 		this.flags = theFlags;
292 	}
293 
294 	/**
295 	 * sets the maximum time the associated cache object will remain in the
296 	 * cache without being referenced before it is invalidated.
297 	 * 
298 	 * @param idle
299 	 *            is in seconds. The {@link #timeToSeconds(int, int, int,int)}
300 	 *            can be used to convert days, hours, minutes to secounds.
301 	 * 
302 	 * @throws InvalidArgumentException
303 	 *             if a negative value for idle is supplied.
304 	 */
305 	public void setIdleTime(final long idle) throws InvalidArgumentException {
306 		if (idle < 0) {
307 			throw new InvalidArgumentException("Idle time must be a positive number.");
308 		}
309 		this.idleTime = idle;
310 	}
311 
312 	/**
313 	 * Register an event listener object to be executed when the specified event
314 	 * occurs with relationship to the associated object. Currently the only
315 	 * invalidate event being monitored is Attributes.INVALIDATE_EVENT. If
316 	 * invalid parameters are passed such as invalid events, or null as
317 	 * listener, this method silently returns without doing any changes to this
318 	 * object.
319 	 * 
320 	 * @param event
321 	 *            The event to listen for.
322 	 * @param aListener
323 	 *            the listener to fire when the event occurs.
324 	 * 
325 	 *@todo Should these Attributes only have one Listener, or should several
326 	 *       be supported?
327 	 */
328 	public void setListener(final int event, final CacheEventListener aListener) {
329 		if ((event == INVALIDATE_EVENT) && (aListener != null)) {
330 			this.listener = aListener;
331 		}
332 	}
333 
334 	/**
335 	 * Will associate a loader object with this object.
336 	 * 
337 	 * @param aLoader
338 	 *            The loader to set. This parameter can be null.
339 	 */
340 	public void setLoader(final CacheLoader aLoader) {
341 		this.loader = aLoader;
342 	}
343 
344 	/**
345 	 * Is used to specify the size in bytes of the object being cached. This is
346 	 * used to determine when the cache capacity is reached. If the cache is not
347 	 * using object size to determine the capacity (It can also use object
348 	 * counts) this value is ignored.
349 	 * 
350 	 * @param aSize
351 	 *            the size to be set. if this parameter is smaller than zero,
352 	 *            this method silently returns.
353 	 */
354 	public void setSize(final int aSize) {
355 		if (aSize < 0) {
356 			return;
357 		}
358 		this.size = aSize;
359 	}
360 
361 	/**
362 	 * Will set the maximum time the associated cache object will stay in the
363 	 * cache before it is invalidated. The time starts when the object is loaded
364 	 * into the cache(by the {@link CacheLoader}object or put by the
365 	 * {@link CacheAccess#replace(Object, Object)}) or when the time to live
366 	 * attribute is set by the
367 	 * {@link CacheLoader#setAttributes(Object, Attributes)} method.
368 	 * 
369 	 * @param ttl
370 	 *            the time to live in seconds. The
371 	 *            {@link #timeToSeconds(int, int, int, int)} can be used to
372 	 *            convert days, hours, minutes to seconds.
373 	 * 
374 	 * @throws InvalidArgumentException
375 	 *             if a negative value for ttl is supplied.
376 	 */
377 	public void setTimeToLive(final long ttl) throws InvalidArgumentException {
378 		if (ttl < 0) {
379 			throw new InvalidArgumentException("Time to live must be a positive number.");
380 		}
381 		this.timeToLive = ttl;
382 	}
383 
384 	/**
385 	 * Sets the version attribute. Is only maintained for user convenience. It
386 	 * is not used internally by the cache.
387 	 * 
388 	 * @param aVersion
389 	 *            the version number to set.
390 	 */
391 	public void setVersion(final long aVersion) {
392 		this.version = aVersion;
393 	}
394 
395 	/**
396 	 * Will convert the time specified into seconds.
397 	 * 
398 	 * @param days
399 	 *            number of days.
400 	 * @param hours
401 	 *            number of hours.
402 	 * @param minutes
403 	 *            number of minutes.
404 	 * @param seconds
405 	 *            number of seconds.
406 	 * 
407 	 * @return the converted time in seconds.
408 	 * 
409 	 * @throws InvalidArgumentException
410 	 *             if any of the parameters are negative values.
411 	 */
412 	public long timeToSeconds(final int days, final int hours, final int minutes, final int seconds) throws InvalidArgumentException {
413 		if (days < 0) {
414 			throw new InvalidArgumentException("Days must be larger than zero.");
415 		}
416 		if (hours < 0) {
417 			throw new InvalidArgumentException("Hours must be larger than zero.");
418 		}
419 		if (minutes < 0) {
420 			throw new InvalidArgumentException("Minutes must be larger than zero.");
421 		}
422 		if (seconds < 0) {
423 			throw new InvalidArgumentException("Seconds must be larger than zero.");
424 		}
425 		return seconds + (ONE_MINUTE * minutes) + (ONE_MINUTE * ONE_HOUR * hours) + (ONE_MINUTE * ONE_HOUR * ONE_DAY * days);
426 	}
427 
428 	/**
429 	 * returns these Attributes as a String.
430 	 * 
431 	 * @return these Attributes as a String.
432 	 */
433 	public String toString() {
434 		return "Attributes {ttl:" + timeToLive + '}'; //$NON-NLS-1$
435 	}
436 }