Package org.apache.ojb.broker.util

Source Code of org.apache.ojb.broker.util.ReferenceMap$WeakRef

package org.apache.ojb.broker.util;

/* Copyright 2004-2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.AbstractCollection;
import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

/**
* <p>
* Modified version of {@link org.apache.commons.collections.ReferenceMap}, using
* object identity for key comparison (). This class
* simply extended {@link org.apache.commons.collections.ReferenceMap} with an extra field
* "useSystemIdentity" which is initialized in constructor and is used every time we
* want to compare (or hash) keys or values.
* </p>
* <p>
* Javadoc of ReferenceMap starts here:
* <br/>
* Hashtable-based {@link java.util.Map} implementation that allows
*  mappings to be removed by the garbage collector.
* </p>
* <P>
*  When you construct a <Code>ReferenceMap</Code>, you can
*  specify what kind of references are used to store the
*  map's keys and values.  If non-hard references are
*  used, then the garbage collector can remove mappings
*  if a key or value becomes unreachable, or if the
*  JVM's memory is running low.  For information on how
*  the different reference types behave, see
{@link java.lang.ref.Reference}.<P>
*
*  Different types of references can be specified for keys
*  and values.  The keys can be configured to be weak but
*  the values hard, in which case this class will behave
*  like a <A HREF="http://java.sun.com/j2se/1.4/docs/api/java/util/WeakHashMap.html">
<Code>WeakHashMap</Code></A>.  However, you
*  can also specify hard keys and weak values, or any other
*  combination.  The default constructor uses hard keys
*  and soft values, providing a memory-sensitive cache.<P>
*
*  The algorithms used are basically the same as those
*  in {@link java.util.HashMap}.  In particular, you
*  can specify a load factor and capacity to suit your
*  needs.  All optional {@link java.util.Map} operations are
*  supported.<P>
*
*  However, this {@link java.util.Map} implementation does <I>not</I>
*  allow null elements.  Attempting to add a null key or
*  or a null value to the map will raise a
<Code>NullPointerException</Code>.<P>
*
*  As usual, this implementation is not synchronized.  You
*  can use {@link java.util.Collections#synchronizedMap} to
*  provide synchronized access to a <Code>ReferenceMap</Code>.
*
* @deprecated use {@link org.apache.commons.collections.map.ReferenceIdentityMap} instead.
@author Andy Malakov
@version $Id: ReferenceMap.java,v 1.6.2.2 2005/12/21 22:27:47 tomdz Exp $
*/
public class ReferenceMap extends AbstractMap
{

    /**
     *  For serialization.
     */
    final private static long serialVersionUID = -3370601314380922368L;


    /**
     *  Constant indicating that hard references should be used.
     */
    final public static int HARD = 0;


    /**
     *  Constant indiciating that soft references should be used.
     */
    final public static int SOFT = 1;


    /**
     *  Constant indicating that weak references should be used.
     */
    final public static int WEAK = 2;


    // --- serialized instance variables:


    /**
     *  The reference type for keys.  Must be HARD, SOFT, WEAK.
     *  Note: I originally marked this field as final, but then this class
     *   didn't compile under JDK1.2.2.
     *  @serial
     */
    private int keyType;


    /**
     *  The reference type for values.  Must be HARD, SOFT, WEAK.
     *  Note: I originally marked this field as final, but then this class
     *   didn't compile under JDK1.2.2.
     *  @serial
     */
    private int valueType;


    /**
     *  The threshold variable is calculated by multiplying
     *  table.length and loadFactor.
     *  Note: I originally marked this field as final, but then this class
     *   didn't compile under JDK1.2.2.
     *  @serial
     */
    private float loadFactor;


    // -- Non-serialized instance variables

    /**
     *  ReferenceQueue used to eliminate stale mappings.
     *  @see #purge
     */
    private transient ReferenceQueue queue = new ReferenceQueue();


    /**
     *  The hash table.  Its length is always a power of two.
     */
    private transient Entry[] table;


    /**
     *  Number of mappings in this map.
     */
    private transient int size;


    /**
     *  When size reaches threshold, the map is resized.
     *  @see #resize
     */
    private transient int threshold;


    /**
     *  Number of times this map has been modified.
     */
    private transient volatile int modCount;


    /**
     *  Cached key set.  May be null if key set is never accessed.
     */
    private transient Set keySet;


    /**
     *  Cached entry set.  May be null if entry set is never accessed.
     */
    private transient Set entrySet;


    /**
     *  Cached values.  May be null if values() is never accessed.
     */
    private transient Collection values;

  /**
    *  Note: I originally marked this field as final, but then this class
    *   didn't compile under JDK1.2.2.
    */
    private boolean useSystemIdentity;

    /**
     *  Constructs a new <Code>ReferenceMap</Code> that will
     *  use hard references to keys and soft references to values.
     */
    public ReferenceMap()
    {
        this(HARD, SOFT);
    }


    /**
     *  Constructs a new <Code>ReferenceMap</Code> that will
     *  use the specified types of references.
     *
     *  @param keyType  the type of reference to use for keys;
     *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
     @param valueType  the type of reference to use for values;
     *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
     */
    public ReferenceMap(int keyType, int valueType)
    {
        this(keyType, valueType, 16, 0.75f, false);
    }


    /**
     *  Constructs a new <Code>ReferenceMap</Code> with the
     *  specified reference types, load factor and initial
     *  capacity.
     *
     *  @param keyType  the type of reference to use for keys;
     *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
     @param valueType  the type of reference to use for values;
     *   must be {@link #HARD}, {@link #SOFT}, {@link #WEAK}
     @param capacity  the initial capacity for the map
     *  @param loadFactor  the load factor for the map
     *  @param useSystemIdentity if true System.identityHashCode() and comparision operator (==) will be used
     *         in place of Object.hashCode and Object.equals (Please read {@link java.util.WeakHashMap}
     *         java doc for more information).
     */
    public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor, boolean useSystemIdentity)
    {
        super();

        verify("keyType", keyType);
        verify("valueType", valueType);

        this.useSystemIdentity = useSystemIdentity;

        if (capacity <= 0)
        {
            throw new IllegalArgumentException("capacity must be positive");
        }
        if ((loadFactor <= 0.0f) || (loadFactor >= 1.0f))
        {
            throw new IllegalArgumentException("Load factor must be greater than 0 and less than 1.");
        }

        this.keyType = keyType;
        this.valueType = valueType;

        int v = 1;
        while (v < capacity) v *= 2;

        this.table = new Entry[v];
        this.loadFactor = loadFactor;
        this.threshold = (int) (v * loadFactor);
    }


    // used by constructor
    private static void verify(String name, int type)
    {
        if ((type < HARD) || (type > WEAK))
        {
            throw new IllegalArgumentException(name +
                    " must be HARD, SOFT, WEAK.");
        }
    }


    /**
     *  Writes this object to the given output stream.
     *
     *  @param out  the output stream to write to
     *  @throws java.io.IOException  if the stream raises it
     */
    private void writeObject(ObjectOutputStream out) throws IOException
    {
        out.defaultWriteObject();
        out.writeInt(table.length);

        // Have to use null-terminated list because size might shrink
        // during iteration

        for (Iterator iter = entrySet().iterator(); iter.hasNext();)
        {
            Map.Entry entry = (Map.Entry) iter.next();
            out.writeObject(entry.getKey());
            out.writeObject(entry.getValue());
        }
        out.writeObject(null);
    }


    /**
     *  Reads the contents of this object from the given input stream.
     *
     *  @param inp  the input stream to read from
     *  @throws java.io.IOException  if the stream raises it
     *  @throws java.lang.ClassNotFoundException  if the stream raises it
     */
    private void readObject(ObjectInputStream inp) throws IOException, ClassNotFoundException
    {
        inp.defaultReadObject();
        table = new Entry[inp.readInt()];
        threshold = (int) (table.length * loadFactor);
        queue = new ReferenceQueue();
        Object key = inp.readObject();
        while (key != null)
        {
            Object value = inp.readObject();
            put(key, value);
            key = inp.readObject();
        }
    }


    /**
     *  Constructs a reference of the given type to the given
     *  referent.  The reference is registered with the queue
     *  for later purging.
     *
     *  @param type  HARD, SOFT or WEAK
     *  @param referent  the object to refer to
     *  @param hash  the hash code of the <I>key</I> of the mapping;
     *    this number might be different from referent.hashCode() if
     *    the referent represents a value and not a key
     */
    private Object toReference(int type, Object referent, int hash)
    {
        switch (type)
        {
            case HARD:
                return referent;
            case SOFT:
                return new SoftRef(hash, referent, queue);
            case WEAK:
                return new WeakRef(hash, referent, queue);
            default:
                throw new Error();
        }
    }

    /**
     *  Returns the entry associated with the given key.
     *
     *  @param key  the key of the entry to look up
     *  @return  the entry associated with that key, or null
     *    if the key is not in this map
     */
    private Entry getEntry(Object key)
    {
        if (key == null) return null;
        int hash = hashCode(key);
        int index = indexFor(hash);
        for (Entry entry = table[index]; entry != null; entry = entry.next)
        {
            if ((entry.hash == hash) && equals(key, entry.getKey()))
            {
                return entry;
            }
        }
        return null;
    }


    /**
     *  Converts the given hash code into an index into the
     *  hash table.
     */
    private int indexFor(int hash)
    {
        // mix the bits to avoid bucket collisions...
        hash += ~(hash << 15);
        hash ^= (hash >>> 10);
        hash += (hash << 3);
        hash ^= (hash >>> 6);
        hash += ~(hash << 11);
        hash ^= (hash >>> 16);
        return hash & (table.length - 1);
    }


    /**
     *  Resizes this hash table by doubling its capacity.
     *  This is an expensive operation, as entries must
     *  be copied from the old smaller table to the new
     *  bigger table.
     */
    private void resize()
    {
        Entry[] old = table;
        table = new Entry[old.length * 2];

        for (int i = 0; i < old.length; i++)
        {
            Entry next = old[i];
            while (next != null)
            {
                Entry entry = next;
                next = next.next;
                int index = indexFor(entry.hash);
                entry.next = table[index];
                table[index] = entry;
            }
            old[i] = null;
        }
        threshold = (int) (table.length * loadFactor);
    }


    /**
     *  Purges stale mappings from this map.<P>
     *
     *  Ordinarily, stale mappings are only removed during
     *  a write operation; typically a write operation will
     *  occur often enough that you'll never need to manually
     *  invoke this method.<P>
     *
     *  Note that this method is not synchronized!  Special
     *  care must be taken if, for instance, you want stale
     *  mappings to be removed on a periodic basis by some
     *  background thread.
     */
    private void purge()
    {
        Reference ref = queue.poll();
        while (ref != null)
        {
            purge(ref);
            ref = queue.poll();
        }
    }


    private void purge(Reference ref)
    {
        // The hashCode of the reference is the hashCode of the
        // mapping key, even if the reference refers to the
        // mapping value...
        int hash = ref.hashCode(); // note: hashCode() is referined
        int index = indexFor(hash);
        Entry previous = null;
        Entry entry = table[index];
        while (entry != null)
        {
            if (entry.purge(ref))
            {
                if (previous == null)
                    table[index] = entry.next;
                else
                    previous.next = entry.next;
                this.size--;
                return;
            }
            previous = entry;
            entry = entry.next;
        }

    }


    /**
     *  Returns the size of this map.
     *
     *  @return  the size of this map
     */
    public int size()
    {
        purge();
        return size;
    }


    /**
     *  Returns <Code>true</Code> if this map is empty.
     *
     *  @return <Code>true</Code> if this map is empty
     */
    public boolean isEmpty()
    {
        purge();
        return size == 0;
    }


    /**
     *  Returns <Code>true</Code> if this map contains the given key.
     *
     *  @return true if the given key is in this map
     */
    public boolean containsKey(Object key)
    {
        purge();
        Entry entry = getEntry(key);
        if (entry == null) return false;
        return entry.getValue() != null;
    }


    /**
     *  Returns the value associated with the given key, if any.
     *
     *  @return the value associated with the given key, or <Code>null</Code>
     *   if the key maps to no value
     */
    public Object get(Object key)
    {
        purge();
        Entry entry = getEntry(key);
        if (entry == null) return null;
        return entry.getValue();
    }


    /**
     *  Associates the given key with the given value.<P>
     *  Neither the key nor the value may be null.
     *
     *  @param key  the key of the mapping
     *  @param value  the value of the mapping
     *  @return  the last value associated with that key, or
     *   null if no value was associated with the key
     *  @throws java.lang.NullPointerException if either the key or value
     *   is null
     */
    public Object put(Object key, Object value)
    {
        if (key == null) throw new NullPointerException("null keys not allowed");
        if (value == null) throw new NullPointerException("null values not allowed");

        purge();
        if (size + 1 > threshold) resize();

        int hash = hashCode(key);
        int index = indexFor(hash);
        Entry entry = table[index];
        while (entry != null)
        {
            if ((hash == entry.hash) && equals(key, entry.getKey()))
            {
                Object result = entry.getValue();
                entry.setValue(value);
                return result;
            }
            entry = entry.next;
        }
        this.size++;
        modCount++;
        key = toReference(keyType, key, hash);
        value = toReference(valueType, value, hash);
        table[index] = new Entry(key, hash, value, table[index]);
        return null;
    }


    /**
     *  Removes the key and its associated value from this map.
     *
     *  @param key  the key to remove
     *  @return the value associated with that key, or null if
     *   the key was not in the map
     */
    public Object remove(Object key)
    {
        if (key == null) return null;
        purge();
        int hash = hashCode(key);
        int index = indexFor(hash);
        Entry previous = null;
        Entry entry = table[index];
        while (entry != null)
        {
            if ((hash == entry.hash) && equals(key, entry.getKey()))
            {
                if (previous == null)
                    table[index] = entry.next;
                else
                    previous.next = entry.next;
                this.size--;
                modCount++;
                return entry.getValue();
            }
            previous = entry;
            entry = entry.next;
        }
        return null;
    }


    /**
     *  Clears this map.
     */
    public void clear()
    {
        Arrays.fill(table, null);
        size = 0;
        while (queue.poll() != null)
        {
            // drain the queue
        }
    }


    /**
     *  Returns a set view of this map's entries.
     *
     *  @return a set view of this map's entries
     */
    public Set entrySet()
    {
        if (entrySet != null) return entrySet;
        entrySet = new AbstractSet()
        {
            public int size()
            {
                return ReferenceMap.this.size();
            }


            public void clear()
            {
                ReferenceMap.this.clear();
            }


            public boolean contains(Object o)
            {
                if (o == null) return false;
                if (!(o instanceof Map.Entry)) return false;
                Map.Entry e = (Map.Entry) o;
                Entry e2 = getEntry(e.getKey());
                return (e2 != null) && e.equals(e2);
            }


            public boolean remove(Object o)
            {
                boolean r = contains(o);
                if (r)
                {
                    Map.Entry e = (Map.Entry) o;
                    ReferenceMap.this.remove(e.getKey());
                }
                return r;
            }


            public Iterator iterator()
            {
                return new EntryIterator();
            }

            public Object[] toArray()
            {
                return toArray(new Object[0]);
            }


            public Object[] toArray(Object[] arr)
            {
                ArrayList list = new ArrayList();
                Iterator iterator = iterator();
                while (iterator.hasNext())
                {
                    Entry e = (Entry) iterator.next();
                    list.add(new DefaultMapEntry(e.getKey(), e.getValue()));
                }
                return list.toArray(arr);
            }
        };
        return entrySet;
    }


    /**
     *  Returns a set view of this map's keys.
     *
     *  @return a set view of this map's keys
     */
    public Set keySet()
    {
        if (keySet != null) return keySet;
        keySet = new AbstractSet()
        {
            public int size()
            {
                return size;
            }

            public Iterator iterator()
            {
                return new KeyIterator();
            }

            public boolean contains(Object o)
            {
                return containsKey(o);
            }


            public boolean remove(Object o)
            {
                Object r = ReferenceMap.this.remove(o);
                return r != null;
            }

            public void clear()
            {
                ReferenceMap.this.clear();
            }

        };
        return keySet;
    }


    /**
     *  Returns a collection view of this map's values.
     *
     *  @return a collection view of this map's values.
     */
    public Collection values()
    {
        if (values != null) return values;
        values = new AbstractCollection()
        {
            public int size()
            {
                return size;
            }

            public void clear()
            {
                ReferenceMap.this.clear();
            }

            public Iterator iterator()
            {
                return new ValueIterator();
            }
        };
        return values;
    }


    // If getKey() or getValue() returns null, it means
    // the mapping is stale and should be removed.
    private class Entry implements Map.Entry
    {

        Object key;
        Object value;
        int hash;
        Entry next;


        public Entry(Object key, int hash, Object value, Entry next)
        {
            this.key = key;
            this.hash = hash;
            this.value = value;
            this.next = next;
        }


        public Object getKey()
        {
            return (keyType > HARD) ? ((Reference) key).get() : key;
        }


        public Object getValue()
        {
            return (valueType > HARD) ? ((Reference) value).get() : value;
        }


        public Object setValue(Object object)
        {
            Object old = getValue();
            if (valueType > HARD) ((Reference) value).clear();
            value = toReference(valueType, object, hash);
            return old;
        }


        public boolean equals(Object o)
        {
            if (o == null) return false;
            if (o == this) return true;
            if (!(o instanceof Map.Entry)) return false;

            Map.Entry entry = (Map.Entry) o;
            Object _key = entry.getKey();
            Object _value = entry.getValue();
            if ((_key == null) || (_value == null)) return false;
            return ReferenceMap.this.equals(_key, getKey()) &&
                    ReferenceMap.this.equals(_value, getValue());
        }


        public int hashCode()
        {
            Object v = getValue();
            return hash ^ ((v == null) ? 0 : v.hashCode());
        }


        public String toString()
        {
            return getKey() + "=" + getValue();
        }


        boolean purge(Reference ref)
        {
            boolean r = (keyType > HARD) && (key == ref);
            r = r || ((valueType > HARD) && (value == ref));
            if (r)
            {
                if (keyType > HARD) ((Reference) key).clear();
                if (valueType > HARD) ((Reference) value).clear();
            }
            return r;
        }
    }


    private class EntryIterator implements Iterator
    {
        // These fields keep track of where we are in the table.
        int index;
        Entry entry;
        Entry previous;

        // These Object fields provide hard references to the
        // current and next entry; this assures that if hasNext()
        // returns true, next() will actually return a valid element.
        Object nextKey, nextValue;
        Object currentKey, currentValue;

        int expectedModCount;


        public EntryIterator()
        {
            index = (size() != 0 ? table.length : 0);
            // have to do this here!  size() invocation above
            // may have altered the modCount.
            expectedModCount = modCount;
        }


        public boolean hasNext()
        {
            checkMod();
            while (nextNull())
            {
                Entry e = entry;
                int i = index;
                while ((e == null) && (i > 0))
                {
                    i--;
                    e = table[i];
                }
                entry = e;
                index = i;
                if (e == null)
                {
                    currentKey = null;
                    currentValue = null;
                    return false;
                }
                nextKey = e.getKey();
                nextValue = e.getValue();
                if (nextNull()) entry = entry.next;
            }
            return true;
        }


        private void checkMod()
        {
            if (modCount != expectedModCount)
            {
                throw new ConcurrentModificationException();
            }
        }


        private boolean nextNull()
        {
            return (nextKey == null) || (nextValue == null);
        }

        protected Entry nextEntry()
        {
            checkMod();
            if (nextNull() && !hasNext()) throw new NoSuchElementException();
            previous = entry;
            entry = entry.next;
            currentKey = nextKey;
            currentValue = nextValue;
            nextKey = null;
            nextValue = null;
            return previous;
        }


        public Object next()
        {
            return nextEntry();
        }


        public void remove()
        {
            checkMod();
            if (previous == null) throw new IllegalStateException();
            ReferenceMap.this.remove(currentKey);
            previous = null;
            currentKey = null;
            currentValue = null;
            expectedModCount = modCount;
        }

    }


    private class ValueIterator extends EntryIterator
    {
        public Object next()
        {
            return nextEntry().getValue();
        }
    }


    private class KeyIterator extends EntryIterator
    {
        public Object next()
        {
            return nextEntry().getKey();
        }
    }



    // These two classes store the hashCode of the key of
    // of the mapping, so that after they're dequeued a quick
    // lookup of the bucket in the table can occur.


    private static class SoftRef extends SoftReference
    {
        private int hash;


        public SoftRef(int hash, Object r, ReferenceQueue q)
        {
            super(r, q);
            this.hash = hash;
        }


        public int hashCode()
        {
            return hash;
        }
    }


    private static class WeakRef extends WeakReference
    {
        private int hash;


        public WeakRef(int hash, Object r, ReferenceQueue q)
        {
            super(r, q);
            this.hash = hash;
        }


        public int hashCode()
        {
            return hash;
        }
    }

    private int hashCode(Object obj)
    {
        return useSystemIdentity ? System.identityHashCode(obj) : obj.hashCode(); // null keys|values are not supported
    }

    private boolean equals(Object obj1, Object obj2)
    {
        return (obj1 == obj2) ||
                (!useSystemIdentity && obj1.equals(obj2)); // null keys|values are not supported
    }

    //***********************************************
    // inner class
    //***********************************************
    /** A default implementation of {@link java.util.Map.Entry}
      *
      * @since 1.0
      * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
      * @author <a href="mailto:mas@apache.org">Michael A. Smith</a>
      */

    public class DefaultMapEntry implements Map.Entry {

        private Object key;
        private Object value;

        /**
         *  Constructs a new <Code>DefaultMapEntry</Code> with a null key
         *  and null value.
         */
        public DefaultMapEntry() {
        }

        /**
         *  Constructs a new <Code>DefaultMapEntry</Code> with the given
         *  key and given value.
         *
         *  @param key  the key for the entry, may be null
         *  @param value  the value for the entyr, may be null
         */
        public DefaultMapEntry(Object key, Object value) {
            this.key = key;
            this.value = value;
        }

        /**
         *  Implemented per API documentation of
         *  {@link java.util.Map.Entry#equals(java.lang.Object)}
         **/
        public boolean equals(Object o) {
            if( o == null ) return false;
            if( o == this ) return true;

            if ( ! (o instanceof Map.Entry ) )
                return false;
            Map.Entry e2 = (Map.Entry)o;
            return ((getKey() == null ?
                     e2.getKey() == null : getKey().equals(e2.getKey())) &&
                    (getValue() == null ?
                     e2.getValue() == null : getValue().equals(e2.getValue())));
        }


        /**
         *  Implemented per API documentation of
         *  {@link java.util.Map.Entry#hashCode()}
         **/
        public int hashCode() {
            return ( ( getKey() == null ? 0 : getKey().hashCode() ) ^
                     ( getValue() == null ? 0 : getValue().hashCode() ) );
        }



        // Map.Entry interface
        //-------------------------------------------------------------------------

        /**
         *  Returns the key.
         *
         *  @return the key
         */
        public Object getKey() {
            return key;
        }


        /**
         *  Returns the value.
         *
         *  @return the value
         */
        public Object getValue() {
            return value;
        }

        // Properties
        //-------------------------------------------------------------------------

        /**
         *  Sets the key.  This method does not modify any map.
         *
         *  @param key  the new key
         */
        public void setKey(Object key) {
            this.key = key;
        }

        /** Note that this method only sets the local reference inside this object and
          * does not modify the original Map.
          *
          * @return the old value of the value
          * @param value the new value
          */
        public Object setValue(Object value) {
            Object answer = this.value;
            this.value = value;
            return answer;
        }

    }
}
TOP

Related Classes of org.apache.ojb.broker.util.ReferenceMap$WeakRef

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.