1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/* 2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Copyright 2004 The Apache Software Foundation. 3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * you may not use this file except in compliance with the License. 6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * You may obtain a copy of the License at 7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * See the License for the specific language governing permissions and 14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * limitations under the License. 15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.commons.logging.impl; 19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.ref.ReferenceQueue; 21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.lang.ref.WeakReference; 22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.*; 23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/** 25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>Implementation of <code>Hashtable</code> that uses <code>WeakReference</code>'s 26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to hold its keys thus allowing them to be reclaimed by the garbage collector. 27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The associated values are retained using strong references.</p> 28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>This class follows the symantics of <code>Hashtable</code> as closely as 30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * possible. It therefore does not accept null values or keys.</p> 31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p><strong>Note:</strong> 33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This is <em>not</em> intended to be a general purpose hash table replacement. 34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This implementation is also tuned towards a particular purpose: for use as a replacement 35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * for <code>Hashtable</code> in <code>LogFactory</code>. This application requires 36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * good liveliness for <code>get</code> and <code>put</code>. Various tradeoffs 37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * have been made with this in mind. 38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <strong>Usage:</strong> typical use case is as a drop-in replacement 41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * for the <code>Hashtable</code> used in <code>LogFactory</code> for J2EE enviroments 42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * running 1.3+ JVMs. Use of this class <i>in most cases</i> (see below) will 43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * allow classloaders to be collected by the garbage collector without the need 44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to call {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release(ClassLoader)}. 45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p><code>org.apache.commons.logging.LogFactory</code> checks whether this class 48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * can be supported by the current JVM, and if so then uses it to store 49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * references to the <code>LogFactory</code> implementationd it loads 50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * (rather than using a standard Hashtable instance). 51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Having this class used instead of <code>Hashtable</code> solves 52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * certain issues related to dynamic reloading of applications in J2EE-style 53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * environments. However this class requires java 1.3 or later (due to its use 54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * of <code>java.lang.ref.WeakReference</code> and associates). 55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * And by the way, this extends <code>Hashtable</code> rather than <code>HashMap</code> 56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * for backwards compatibility reasons. See the documentation 57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * for method <code>LogFactory.createFactoryStore</code> for more details.</p> 58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>The reason all this is necessary is due to a issue which 60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * arises during hot deploy in a J2EE-like containers. 61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Each component running in the container owns one or more classloaders; when 62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the component loads a LogFactory instance via the component classloader 63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * a reference to it gets stored in the static LogFactory.factories member, 64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * keyed by the component's classloader so different components don't 65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * stomp on each other. When the component is later unloaded, the container 66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * sets the component's classloader to null with the intent that all the 67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * component's classes get garbage-collected. However there's still a 68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * reference to the component's classloader from a key in the "global" 69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>LogFactory</code>'s factories member! If <code>LogFactory.release()</code> 70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * is called whenever component is unloaded, the classloaders will be correctly 71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * garbage collected; this <i>should</i> be done by any container that 72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * bundles commons-logging by default. However, holding the classloader 73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * references weakly ensures that the classloader will be garbage collected 74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * without the container performing this step. </p> 75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <strong>Limitations:</strong> 78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * There is still one (unusual) scenario in which a component will not 79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * be correctly unloaded without an explicit release. Though weak references 80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * are used for its keys, it is necessary to use strong references for its values. 81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * </p> 82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> If the abstract class <code>LogFactory</code> is 84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * loaded by the container classloader but a subclass of 85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>LogFactory</code> [LogFactory1] is loaded by the component's 86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * classloader and an instance stored in the static map associated with the 87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * base LogFactory class, then there is a strong reference from the LogFactory 88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * class to the LogFactory1 instance (as normal) and a strong reference from 89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the LogFactory1 instance to the component classloader via 90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <code>getClass().getClassLoader()</code>. This chain of references will prevent 91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * collection of the child classloader.</p> 92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p> 94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Such a situation occurs when the commons-logging.jar is 95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * loaded by a parent classloader (e.g. a server level classloader in a 96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * servlet container) and a custom <code>LogFactory</code> implementation is 97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * loaded by a child classloader (e.g. a web app classloader).</p> 98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <p>To avoid this scenario, ensure 100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * that any custom LogFactory subclass is loaded by the same classloader as 101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the base <code>LogFactory</code>. Creating custom LogFactory subclasses is, 102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * however, rare. The standard LogFactoryImpl class should be sufficient 103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * for most or all users.</p> 104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author Brian Stansberry 107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 1.1 109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic final class WeakHashtable extends Hashtable { 111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The maximum number of times put() or remove() can be called before 114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the map will be purged of all cleared entries. 115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static final int MAX_CHANGES_BEFORE_PURGE = 100; 117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * The maximum number of times put() or remove() can be called before 120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the map will be purged of one cleared entry. 121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private static final int PARTIAL_PURGE_COUNT = 10; 123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /* ReferenceQueue we check for gc'd keys */ 125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private ReferenceQueue queue = new ReferenceQueue(); 126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /* Counter used to control how often we purge gc'd entries */ 127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private int changeCount = 0; 128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Constructs a WeakHashtable with the Hashtable default 131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * capacity and load factor. 132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public WeakHashtable() {} 134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public boolean containsKey(Object key) { 140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // purge should not be required 141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced referenced = new Referenced(key); 142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.containsKey(referenced); 143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Enumeration elements() { 149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.elements(); 151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Set entrySet() { 157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Set referencedEntries = super.entrySet(); 159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Set unreferencedEntries = new HashSet(); 160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project for (Iterator it=referencedEntries.iterator(); it.hasNext();) { 161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Map.Entry entry = (Map.Entry) it.next(); 162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced referencedKey = (Referenced) entry.getKey(); 163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object key = referencedKey.getValue(); 164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object value = entry.getValue(); 165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (key != null) { 166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Entry dereferencedEntry = new Entry(key, value); 167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project unreferencedEntries.add(dereferencedEntry); 168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return unreferencedEntries; 171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object get(Object key) { 177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // for performance reasons, no purge 178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced referenceKey = new Referenced(key); 179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.get(referenceKey); 180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Enumeration keys() { 186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project final Enumeration enumer = super.keys(); 188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return new Enumeration() { 189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public boolean hasMoreElements() { 190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return enumer.hasMoreElements(); 191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object nextElement() { 193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced nextReference = (Referenced) enumer.nextElement(); 194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return nextReference.getValue(); 195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project }; 197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Set keySet() { 204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Set referencedKeys = super.keySet(); 206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Set unreferencedKeys = new HashSet(); 207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project for (Iterator it=referencedKeys.iterator(); it.hasNext();) { 208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced referenceKey = (Referenced) it.next(); 209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object keyValue = referenceKey.getValue(); 210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (keyValue != null) { 211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project unreferencedKeys.add(keyValue); 212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return unreferencedKeys; 215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object put(Object key, Object value) { 221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // check for nulls, ensuring symantics match superclass 222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (key == null) { 223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new NullPointerException("Null keys are not allowed"); 224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (value == null) { 226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new NullPointerException("Null values are not allowed"); 227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // for performance reasons, only purge every 230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // MAX_CHANGES_BEFORE_PURGE times 231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { 232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project changeCount = 0; 234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // do a partial purge more often 236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { 237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purgeOne(); 238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object result = null; 241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced keyRef = new Referenced(key, queue); 242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.put(keyRef, value); 243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public void putAll(Map t) { 249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (t != null) { 250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Set entrySet = t.entrySet(); 251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project for (Iterator it=entrySet.iterator(); it.hasNext();) { 252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Map.Entry entry = (Map.Entry) it.next(); 253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project put(entry.getKey(), entry.getValue()); 254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Collection values() { 262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.values(); 264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object remove(Object key) { 270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // for performance reasons, only purge every 271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // MAX_CHANGES_BEFORE_PURGE times 272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { 273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project changeCount = 0; 275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // do a partial purge more often 277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { 278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purgeOne(); 279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.remove(new Referenced(key)); 281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public boolean isEmpty() { 287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.isEmpty(); 289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public int size() { 295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.size(); 297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *@see Hashtable 301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public String toString() { 303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return super.toString(); 305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @see Hashtable 309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project protected void rehash() { 311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // purge here to save the effort of rehashing dead entries 312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project purge(); 313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project super.rehash(); 314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Purges all entries whose wrapped keys 318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * have been garbage collected. 319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private void purge() { 321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project synchronized (queue) { 322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project WeakKey key; 323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project while ((key = (WeakKey) queue.poll()) != null) { 324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project super.remove(key.getReferenced()); 325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Purges one entry whose wrapped key 331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * has been garbage collected. 332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private void purgeOne() { 334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project synchronized (queue) { 336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project WeakKey key = (WeakKey) queue.poll(); 337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (key != null) { 338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project super.remove(key.getReferenced()); 339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** Entry implementation */ 344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final static class Entry implements Map.Entry { 345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final Object key; 347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final Object value; 348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private Entry(Object key, Object value) { 350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.key = key; 351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.value = value; 352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public boolean equals(Object o) { 355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean result = false; 356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (o != null && o instanceof Map.Entry) { 357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Map.Entry entry = (Map.Entry) o; 358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project result = (getKey()==null ? 359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project entry.getKey() == null : 360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project getKey().equals(entry.getKey())) 361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project && 362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (getValue()==null ? 363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project entry.getValue() == null : 364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project getValue().equals(entry.getValue())); 365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return result; 367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public int hashCode() { 370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return (getKey()==null ? 0 : getKey().hashCode()) ^ 372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project (getValue()==null ? 0 : getValue().hashCode()); 373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object setValue(Object value) { 376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project throw new UnsupportedOperationException("Entry.setValue is not supported."); 377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object getValue() { 380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return value; 381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public Object getKey() { 384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return key; 385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** Wrapper giving correct symantics for equals and hashcode */ 390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final static class Referenced { 391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final WeakReference reference; 393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final int hashCode; 394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws NullPointerException if referant is <code>null</code> 398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private Referenced(Object referant) { 400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project reference = new WeakReference(referant); 401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Calc a permanent hashCode so calls to Hashtable.remove() 402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // work if the WeakReference has been cleared 403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project hashCode = referant.hashCode(); 404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * 408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @throws NullPointerException if key is <code>null</code> 409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private Referenced(Object key, ReferenceQueue queue) { 411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project reference = new WeakKey(key, queue, this); 412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Calc a permanent hashCode so calls to Hashtable.remove() 413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // work if the WeakReference has been cleared 414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project hashCode = key.hashCode(); 415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public int hashCode() { 419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return hashCode; 420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private Object getValue() { 423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return reference.get(); 424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 426069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project public boolean equals(Object o) { 427069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project boolean result = false; 428069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (o instanceof Referenced) { 429069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced otherKey = (Referenced) o; 430069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object thisKeyValue = getValue(); 431069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Object otherKeyValue = otherKey.getValue(); 432069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (thisKeyValue == null) { 433069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project result = (otherKeyValue == null); 434069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 435069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // Since our hashcode was calculated from the original 436069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // non-null referant, the above check breaks the 437069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // hashcode/equals contract, as two cleared Referenced 438069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // objects could test equal but have different hashcodes. 439069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // We can reduce (not eliminate) the chance of this 440069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // happening by comparing hashcodes. 441069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project if (result == true) { 442069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project result = (this.hashCode() == otherKey.hashCode()); 443069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 444069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // In any case, as our c'tor does not allow null referants 445069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // and Hashtable does not do equality checks between 446069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // existing keys, normal hashtable operations should never 447069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project // result in an equals comparison between null referants 448069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 449069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project else 450069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project { 451069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project result = thisKeyValue.equals(otherKeyValue); 452069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 453069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 454069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return result; 455069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 456069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 457069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 458069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project /** 459069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * WeakReference subclass that holds a hard reference to an 460069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * associated <code>value</code> and also makes accessible 461069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * the Referenced object holding it. 462069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */ 463069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final static class WeakKey extends WeakReference { 464069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 465069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private final Referenced referenced; 466069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 467069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private WeakKey(Object key, 468069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project ReferenceQueue queue, 469069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project Referenced referenced) { 470069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project super(key, queue); 471069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project this.referenced = referenced; 472069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 473069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project 474069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project private Referenced getReferenced() { 475069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project return referenced; 476069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 477069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project } 478069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project} 479