1 package org.apache.jcs.engine;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.ObjectInputStream;
26 import java.io.ObjectOutputStream;
27 import java.io.Serializable;
28 import java.util.ArrayList;
29
30 import org.apache.jcs.engine.behavior.IElementAttributes;
31 import org.apache.jcs.engine.control.event.behavior.IElementEventHandler;
32
33 /**
34 * This it the element attribute descriptor class. Each element in the cache has an ElementAttribute
35 * object associated with it. An ElementAttributes object can be associated with an element in 3
36 * ways:
37 * <ol>
38 * <li>When the item is put into the cache, you can associate an element attributes object.</li>
39 * <li>If not attributes object is include when the element is put into the cache, then the default
40 * attributes for the region will be used.</li>
41 * <li>The element attributes can be reset. This effectively results in a retrieval followed by a
42 * put. Hence, this is the same as 1.</li>
43 * </ol>
44 */
45 public class ElementAttributes
46 implements IElementAttributes, Serializable, Cloneable
47 {
48 /** Don't change. */
49 private static final long serialVersionUID = 7814990748035017441L;
50
51 /** Can this item be flushed to disk */
52 public boolean IS_SPOOL = true;
53
54 /** Is this item laterally distributable */
55 public boolean IS_LATERAL = true;
56
57 /** Can this item be sent to the remote cache */
58 public boolean IS_REMOTE = true;
59
60 /**
61 * You can turn off expiration by setting this to true. This causes the cache to bypass both max
62 * life and idle time expiration.
63 */
64 public boolean IS_ETERNAL = true;
65
66 /** Max life seconds */
67 public long maxLifeSeconds = -1;
68
69 /**
70 * The maximum time an entry can be idle. Setting this to -1 causes the idle time check to be
71 * ignored.
72 */
73 public long maxIdleTimeSeconds = -1;
74
75 /** The byte size of the field. Must be manually set. */
76 public int size = 0;
77
78 /** The creation time. This is used to enforce the max life. */
79 public long createTime = 0;
80
81 /** The last access time. This is used to enforce the max idel time. */
82 public long lastAccessTime = 0;
83
84 /**
85 * The list of Event handlers to use. This is transient, since the event handlers cannot usually
86 * be serialized. This means that you cannot attach a post serialization event to an item.
87 * <p>
88 * TODO we need to check that when an item is passed to a non-local cache that if the local
89 * cache had a copy with event handlers, that those handlers are used.
90 */
91 public transient ArrayList<IElementEventHandler> eventHandlers;
92
93 /**
94 * Constructor for the IElementAttributes object
95 */
96 public ElementAttributes()
97 {
98 this.createTime = System.currentTimeMillis();
99 this.lastAccessTime = this.createTime;
100 }
101
102 /**
103 * Constructor for the IElementAttributes object
104 * <p>
105 * @param attr
106 */
107 protected ElementAttributes( ElementAttributes attr )
108 {
109 IS_ETERNAL = attr.IS_ETERNAL;
110
111 // waterfall onto disk, for pure disk set memory to 0
112 IS_SPOOL = attr.IS_SPOOL;
113
114 // lateral
115 IS_LATERAL = attr.IS_LATERAL;
116
117 // central rmi store
118 IS_REMOTE = attr.IS_REMOTE;
119
120 maxLifeSeconds = attr.maxLifeSeconds;
121 // time-to-live
122 maxIdleTimeSeconds = attr.maxIdleTimeSeconds;
123 size = attr.size;
124 }
125
126 /**
127 * Copies the attributes, including references to event handlers.
128 * <p>
129 * @return a copy of the Attributes
130 */
131 public IElementAttributes copy()
132 {
133 try
134 {
135 // need to make this more efficient. Just want to insure
136 // a proper copy
137 ElementAttributes attr = new ElementAttributes();
138 attr.setIdleTime( this.getIdleTime() );
139 attr.setIsEternal( this.getIsEternal() );
140 attr.setIsLateral( this.getIsLateral() );
141 attr.setIsRemote( this.getIsRemote() );
142 attr.setIsSpool( this.getIsSpool() );
143 attr.setMaxLifeSeconds( this.getMaxLifeSeconds() );
144 attr.addElementEventHandlers( this.eventHandlers );
145 return attr;
146 }
147 catch ( Exception e )
148 {
149 return new ElementAttributes();
150 }
151 }
152
153 /**
154 * Deep clone the attributes.
155 * <p>
156 * @return a clone of these attributes
157 */
158 public Object clone2()
159 {
160 try
161 {
162 ByteArrayOutputStream baos = new ByteArrayOutputStream( 100 );
163 ObjectOutputStream oos = new ObjectOutputStream( baos );
164 oos.writeObject( this );
165 byte buf[] = baos.toByteArray();
166 oos.close();
167
168 // deserialize byte array into ArrayList
169
170 ByteArrayInputStream bais = new ByteArrayInputStream( buf );
171 ObjectInputStream ois = new ObjectInputStream( bais );
172 ElementAttributes attr = (ElementAttributes) ois.readObject();
173 ois.close();
174
175 attr.createTime = System.currentTimeMillis();
176 return attr;
177 }
178 catch ( IOException e )
179 {
180 // swallow
181 }
182 catch (ClassNotFoundException e)
183 {
184 // swallow
185 }
186 return null;
187 }
188
189 /**
190 * Sets the maxLife attribute of the IAttributes object.
191 * <p>
192 * @param mls The new MaxLifeSeconds value
193 */
194 public void setMaxLifeSeconds( long mls )
195 {
196 this.maxLifeSeconds = mls;
197 }
198
199 /**
200 * Sets the maxLife attribute of the IAttributes object. How many seconds it can live after
201 * creation.
202 * <p>
203 * If this is exceeded the element will not be returned, instead it will be removed. It will be
204 * removed on retrieval, or removed actively if the memory shrinker is turned on.
205 * @return The MaxLifeSeconds value
206 */
207 public long getMaxLifeSeconds()
208 {
209 return this.maxLifeSeconds;
210 }
211
212 /**
213 * Sets the idleTime attribute of the IAttributes object. This is the maximum time the item can
214 * be idle in the cache, that is not accessed.
215 * <p>
216 * If this is exceeded the element will not be returned, instead it will be removed. It will be
217 * removed on retrieval, or removed actively if the memory shrinker is turned on.
218 * @param idle The new idleTime value
219 */
220 public void setIdleTime( long idle )
221 {
222 this.maxIdleTimeSeconds = idle;
223 }
224
225 /**
226 * Size in bytes. This is not used except in the admin pages. It will be -1 by default.
227 * <p>
228 * @param size The new size value
229 */
230 public void setSize( int size )
231 {
232 this.size = size;
233 }
234
235 /**
236 * Gets the size attribute of the IAttributes object
237 * <p>
238 * @return The size value
239 */
240 public int getSize()
241 {
242 return size;
243 }
244
245 /**
246 * Gets the createTime attribute of the IAttributes object.
247 * <p>
248 * This should be the current time in milliseconds returned by the sysutem call when the element
249 * is put in the cache.
250 * <p>
251 * Putting an item in the cache overrides any existing items.
252 * @return The createTime value
253 */
254 public long getCreateTime()
255 {
256 return createTime;
257 }
258
259 /**
260 * Sets the createTime attribute of the IElementAttributes object
261 */
262 public void setCreateTime()
263 {
264 createTime = System.currentTimeMillis();
265 }
266
267 /**
268 * Gets the idleTime attribute of the IAttributes object.
269 * <p>
270 * @return The idleTime value
271 */
272 public long getIdleTime()
273 {
274 return this.maxIdleTimeSeconds;
275 }
276
277 /**
278 * Gets the time left to live of the IAttributes object.
279 * <p>
280 * This is the (max life + create time) - current time.
281 * @return The TimeToLiveSeconds value
282 */
283 public long getTimeToLiveSeconds()
284 {
285 long now = System.currentTimeMillis();
286 return ( ( this.getCreateTime() + ( this.getMaxLifeSeconds() * 1000 ) ) - now ) / 1000;
287 }
288
289 /**
290 * Gets the LastAccess attribute of the IAttributes object.
291 * <p>
292 * @return The LastAccess value.
293 */
294 public long getLastAccessTime()
295 {
296 return this.lastAccessTime;
297 }
298
299 /**
300 * Sets the LastAccessTime as now of the IElementAttributes object
301 */
302 public void setLastAccessTimeNow()
303 {
304 this.lastAccessTime = System.currentTimeMillis();
305 }
306
307 /**
308 * Can this item be spooled to disk
309 * <p>
310 * By default this is true.
311 * @return The spoolable value
312 */
313 public boolean getIsSpool()
314 {
315 return this.IS_SPOOL;
316 }
317
318 /**
319 * Sets the isSpool attribute of the IElementAttributes object
320 * <p>
321 * By default this is true.
322 * @param val The new isSpool value
323 */
324 public void setIsSpool( boolean val )
325 {
326 this.IS_SPOOL = val;
327 }
328
329 /**
330 * Is this item laterally distributable. Can it be sent to auxiliaries of type lateral.
331 * <p>
332 * By default this is true.
333 * @return The isLateral value
334 */
335 public boolean getIsLateral()
336 {
337 return this.IS_LATERAL;
338 }
339
340 /**
341 * Sets the isLateral attribute of the IElementAttributes object
342 * <p>
343 * By default this is true.
344 * @param val The new isLateral value
345 */
346 public void setIsLateral( boolean val )
347 {
348 this.IS_LATERAL = val;
349 }
350
351 /**
352 * Can this item be sent to the remote cache
353 * @return true if the item can be sent to a remote auxiliary
354 */
355 public boolean getIsRemote()
356 {
357 return this.IS_REMOTE;
358 }
359
360 /**
361 * Sets the isRemote attribute of the ElementAttributes object
362 * @param val The new isRemote value
363 */
364 public void setIsRemote( boolean val )
365 {
366 this.IS_REMOTE = val;
367 }
368
369 /**
370 * You can turn off expiration by setting this to true. The max life value will be ignored.
371 * <p>
372 * @return true if the item cannot expire.
373 */
374 public boolean getIsEternal()
375 {
376 return this.IS_ETERNAL;
377 }
378
379 /**
380 * Sets the isEternal attribute of the ElementAttributes object. True means that the item should
381 * never expire. If can still be removed if it is the least recently used, and you are using the
382 * LRUMemory cache. it just will not be filtered for expiration by the cache hub.
383 * <p>
384 * @param val The new isEternal value
385 */
386 public void setIsEternal( boolean val )
387 {
388 this.IS_ETERNAL = val;
389 }
390
391 /**
392 * Adds a ElementEventHandler. Handler's can be registered for multiple events. A registered
393 * handler will be called at every recognized event.
394 * <p>
395 * The alternative would be to register handlers for each event. Or maybe The handler interface
396 * should have a method to return whether it cares about certain events.
397 * <p>
398 * @param eventHandler The ElementEventHandler to be added to the list.
399 */
400 public void addElementEventHandler( IElementEventHandler eventHandler )
401 {
402 // lazy here, no concurrency problems expected
403 if ( this.eventHandlers == null )
404 {
405 this.eventHandlers = new ArrayList<IElementEventHandler>();
406 }
407 this.eventHandlers.add( eventHandler );
408 }
409
410 /**
411 * Sets the eventHandlers of the IElementAttributes object.
412 * <p>
413 * This add the references to the local list. Subsequent changes in the caller's list will not
414 * be reflected.
415 * <p>
416 * @param eventHandlers List of IElementEventHandler objects
417 */
418 public void addElementEventHandlers( ArrayList<IElementEventHandler> eventHandlers )
419 {
420 if ( eventHandlers == null )
421 {
422 return;
423 }
424
425 for (IElementEventHandler handler : eventHandlers)
426 {
427 addElementEventHandler(handler);
428 }
429 }
430
431 /**
432 * Gets the elementEventHandlers. Returns null if none exist. Makes checking easy.
433 * <p>
434 * @return The elementEventHandlers List of IElementEventHandler objects
435 */
436 public ArrayList<IElementEventHandler> getElementEventHandlers()
437 {
438 return this.eventHandlers;
439 }
440
441 /**
442 * For logging and debugging the element IElementAttributes.
443 * <p>
444 * @return String info about the values.
445 */
446 @Override
447 public String toString()
448 {
449 StringBuffer dump = new StringBuffer();
450
451 dump.append( "[ IS_LATERAL = " ).append( IS_LATERAL );
452 dump.append( ", IS_SPOOL = " ).append( IS_SPOOL );
453 dump.append( ", IS_REMOTE = " ).append( IS_REMOTE );
454 dump.append( ", IS_ETERNAL = " ).append( IS_ETERNAL );
455 dump.append( ", MaxLifeSeconds = " ).append( this.getMaxLifeSeconds() );
456 dump.append( ", IdleTime = " ).append( this.getIdleTime() );
457 dump.append( ", CreateTime = " ).append( this.getCreateTime() );
458 dump.append( ", LastAccessTime = " ).append( this.getLastAccessTime() );
459 dump.append( ", getTimeToLiveSeconds() = " ).append( String.valueOf( getTimeToLiveSeconds() ) );
460 dump.append( ", createTime = " ).append( String.valueOf( createTime ) ).append( " ]" );
461
462 return dump.toString();
463 }
464 }