001 /** 002 * ======================================== 003 * JFreeReport : a free Java report library 004 * ======================================== 005 * 006 * Project Info: http://reporting.pentaho.org/ 007 * 008 * (C) Copyright 2000-2007, by Object Refinery Limited, Pentaho Corporation and Contributors. 009 * 010 * This library is free software; you can redistribute it and/or modify it under the terms 011 * of the GNU Lesser General Public License as published by the Free Software Foundation; 012 * either version 2.1 of the License, or (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 016 * See the GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public License along with this 019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 020 * Boston, MA 02111-1307, USA. 021 * 022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 023 * in the United States and other countries.] 024 * 025 * ------------ 026 * $Id: WeakReferenceList.java 3048 2007-07-28 18:02:42Z tmorgner $ 027 * ------------ 028 * (C) Copyright 2000-2005, by Object Refinery Limited. 029 * (C) Copyright 2005-2007, by Pentaho Corporation. 030 */ 031 032 package org.jfree.report.util; 033 034 import java.io.IOException; 035 import java.io.Serializable; 036 import java.lang.ref.Reference; 037 import java.lang.ref.WeakReference; 038 039 /** 040 * The WeakReference list uses <code>java.lang.ref.WeakReference</code>s to store its 041 * contents. In contrast to the WeakHashtable, this list knows how to restore missing 042 * content, so that garbage collected elements can be restored when they are accessed. 043 * <p/> 044 * By default this list can contain 25 elements, where the first element is stored using a 045 * strong reference, which is not garbage collected. 046 * <p/> 047 * Restoring the elements is not implemented, concrete implementations will have to 048 * override the <code>restoreChild(int)</code> method. The <code>getMaxChildCount</code> 049 * method defines the maxmimum number of children in the list. When more than 050 * <code>maxChildCount</code> elements are contained in this list, add will always return 051 * false to indicate that adding the element failed. 052 * <p/> 053 * To customize the list, override createReference to create a different kind of 054 * reference. 055 * <p/> 056 * This list is able to add or clearFromParent elements, but inserting or removing of elements is 057 * not possible. 058 * <p/> 059 * 060 * @author Thomas Morgner 061 */ 062 public abstract class WeakReferenceList implements Serializable, Cloneable 063 { 064 /** 065 * The master element. 066 */ 067 private Object master; 068 069 /** 070 * Storage for the references. 071 */ 072 private Reference[] childs; 073 074 /** 075 * The current number of elements. 076 */ 077 private int size; 078 079 /** 080 * The maximum number of elements. 081 */ 082 private final int maxChilds; 083 084 /** 085 * Creates a new weak reference list. The storage of the list is limited to 086 * getMaxChildCount() elements. 087 * 088 * @param maxChildCount the maximum number of elements. 089 */ 090 protected WeakReferenceList (final int maxChildCount) 091 { 092 this.maxChilds = maxChildCount; 093 this.childs = new Reference[maxChildCount - 1]; 094 } 095 096 /** 097 * Returns the maximum number of children in this list. 098 * 099 * @return the maximum number of elements in this list. 100 */ 101 protected final int getMaxChildCount () 102 { 103 return maxChilds; 104 } 105 106 /** 107 * Returns the master element of this list. The master element is the element stored by 108 * a strong reference and cannot be garbage collected. 109 * 110 * @return the master element 111 */ 112 protected Object getMaster () 113 { 114 return master; 115 } 116 117 /** 118 * Attempts to restore the child stored on the given index. 119 * 120 * @param index the index. 121 * @return null if the child could not be restored or the restored child. 122 */ 123 protected abstract Object restoreChild (int index); 124 125 /** 126 * Returns the child stored at the given index. If the child has been garbage collected, 127 * it gets restored using the restoreChild function. 128 * 129 * @param index the index. 130 * @return the object. 131 */ 132 public Object get (final int index) 133 { 134 if (isMaster(index)) 135 { 136 return master; 137 } 138 else 139 { 140 final Reference ref = childs[getChildPos(index)]; 141 if (ref == null) 142 { 143 throw new IllegalStateException("State: " + index); 144 } 145 Object ob = ref.get(); 146 if (ob == null) 147 { 148 ob = restoreChild(index); 149 childs[getChildPos(index)] = createReference(ob); 150 } 151 return ob; 152 } 153 } 154 155 /** 156 * Replaces the child stored at the given index with the new child which can be null. 157 * 158 * @param report the object. 159 * @param index the index. 160 */ 161 public void set (final Object report, final int index) 162 { 163 if (isMaster(index)) 164 { 165 master = report; 166 } 167 else 168 { 169 childs[getChildPos(index)] = createReference(report); 170 } 171 } 172 173 /** 174 * Creates a new reference for the given object. 175 * 176 * @param o the object. 177 * @return a WeakReference for the object o without any ReferenceQueue attached. 178 */ 179 private Reference createReference (final Object o) 180 { 181 return new WeakReference(o); 182 } 183 184 /** 185 * Adds the element to the list. If the maximum size of the list is exceeded, this 186 * function returns false to indicate that adding failed. 187 * 188 * @param rs the object. 189 * @return true, if the object was successfully added to the list, false otherwise 190 */ 191 public boolean add (final Object rs) 192 { 193 if (size == 0) 194 { 195 master = rs; 196 size = 1; 197 return true; 198 } 199 else 200 { 201 if (size < getMaxChildCount()) 202 { 203 childs[size - 1] = createReference(rs); 204 size++; 205 return true; 206 } 207 else 208 { 209 // was not able to add this to this list, maximum number of entries reached. 210 return false; 211 } 212 } 213 } 214 215 /** 216 * Returns true, if the given index denotes a master index of this list. 217 * 218 * @param index the index. 219 * @return true if the index is a master index. 220 */ 221 protected boolean isMaster (final int index) 222 { 223 return index % getMaxChildCount() == 0; 224 } 225 226 /** 227 * Returns the internal storage position for the child. 228 * 229 * @param index the index. 230 * @return the internal storage index. 231 */ 232 protected int getChildPos (final int index) 233 { 234 return index % getMaxChildCount() - 1; 235 } 236 237 /** 238 * Returns the size of the list. 239 * 240 * @return the size. 241 */ 242 public int getSize () 243 { 244 return size; 245 } 246 247 /** 248 * Serialisation support. The transient child elements are not saved. 249 * 250 * @param out the output stream. 251 * @throws IOException if there is an I/O error. 252 */ 253 private void writeObject (final java.io.ObjectOutputStream out) 254 throws IOException 255 { 256 final Reference[] orgChilds = childs; 257 try 258 { 259 childs = null; 260 out.defaultWriteObject(); 261 } 262 finally 263 { 264 childs = orgChilds; 265 } 266 } 267 268 /** 269 * Serialisation support. The transient child elements were not saved. 270 * 271 * @param in the input stream. 272 * @throws IOException if there is an I/O error. 273 * @throws ClassNotFoundException if a serialized class is not defined on this system. 274 */ 275 private void readObject (final java.io.ObjectInputStream in) 276 throws IOException, ClassNotFoundException 277 { 278 in.defaultReadObject(); 279 childs = new Reference[getMaxChildCount() - 1]; 280 for (int i = 0; i < childs.length; i++) 281 { 282 childs[i] = createReference(null); 283 } 284 } 285 286 /** 287 * Creates and returns a copy of this object. The precise meaning of "copy" may depend 288 * on the class of the object. The general intent is that, for any object <tt>x</tt>, 289 * the expression: <blockquote> 290 * <pre> 291 * x.clone() != x</pre></blockquote> 292 * will be true, and that the expression: <blockquote> 293 * <pre> 294 * x.clone().getClass() == x.getClass()</pre></blockquote> 295 * will be <tt>true</tt>, but these are not absolute requirements. While it is typically 296 * the case that: <blockquote> 297 * <pre> 298 * x.clone().equals(x)</pre></blockquote> 299 * will be <tt>true</tt>, this is not an absolute requirement. 300 * <p/> 301 * By convention, the returned object should be obtained by calling 302 * <tt>super.clone</tt>. If a class and all of its superclasses (except 303 * <tt>Object</tt>) obey this convention, it will be the case that 304 * <tt>x.clone().getClass() == x.getClass()</tt>. 305 * <p/> 306 * By convention, the object returned by this method should be independent of this 307 * object (which is being cloned). To achieve this independence, it may be necessary to 308 * modify one or more fields of the object returned by <tt>super.clone</tt> before 309 * returning it. Typically, this means copying any mutable objects that comprise the 310 * internal "deep structure" of the object being cloned and replacing the references to 311 * these objects with references to the copies. If a class contains only primitive 312 * fields or references to immutable objects, then it is usually the case that no fields 313 * in the object returned by <tt>super.clone</tt> need to be modified. 314 * <p/> 315 * The method <tt>clone</tt> for class <tt>Object</tt> performs a specific cloning 316 * operation. First, if the class of this object does not implement the interface 317 * <tt>Cloneable</tt>, then a <tt>CloneNotSupportedException</tt> is thrown. Note that 318 * all arrays are considered to implement the interface <tt>Cloneable</tt>. Otherwise, 319 * this method creates a new instance of the class of this object and initializes all 320 * its fields with exactly the contents of the corresponding fields of this object, as 321 * if by assignment; the contents of the fields are not themselves cloned. Thus, this 322 * method performs a "shallow copy" of this object, not a "deep copy" operation. 323 * <p/> 324 * The class <tt>Object</tt> does not itself implement the interface <tt>Cloneable</tt>, 325 * so calling the <tt>clone</tt> method on an object whose class is <tt>Object</tt> will 326 * result in throwing an exception at run time. 327 * 328 * @return a clone of this instance. 329 * 330 * @throws CloneNotSupportedException if the object's class does not support the 331 * <code>Cloneable</code> interface. Subclasses that 332 * override the <code>clone</code> method can also 333 * throw this exception to indicate that an instance 334 * cannot be cloned. 335 * @see Cloneable 336 */ 337 protected Object clone () 338 throws CloneNotSupportedException 339 { 340 final WeakReferenceList list = (WeakReferenceList) super.clone(); 341 list.childs = (Reference[]) childs.clone(); 342 return list; 343 } 344 }