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