You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by dj...@apache.org on 2009/10/05 20:54:56 UTC
svn commit: r821961 [16/30] - in /geronimo/sandbox/djencks/osgi/framework:
./ buildsupport/ buildsupport/car-maven-plugin/
buildsupport/car-maven-plugin/src/main/java/org/apache/geronimo/mavenplugins/car/
buildsupport/geronimo-maven-plugin/src/main/jav...
Added: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/FastMap.java
URL: http://svn.apache.org/viewvc/geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/FastMap.java?rev=821961&view=auto
==============================================================================
--- geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/FastMap.java (added)
+++ geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/FastMap.java Mon Oct 5 18:54:50 2009
@@ -0,0 +1,928 @@
+/*
+ * J.A.D.E. Java(TM) Addition to Default Environment.
+ * Latest release available at http://jade.dautelle.com/
+ * This class is public domain (not copyrighted).
+ */
+package org.apache.geronimo.system.plugin.plexus.util;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.AbstractCollection;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p> This class represents a <code>Map</code> collection with real-time
+ * behavior. Unless the map's size exceeds its current capacity,
+ * no dynamic memory allocation is ever performed and response time is
+ * <b>extremely fast</b> and <b>consistent</b>.</p>
+ *
+ * <p> Our <a href="http://jade.dautelle.com/doc/benchmark.txt">benchmark</a>
+ * indicates that {@link FastMap#put FastMap.put(key, value)} is up to
+ * <b>5x faster</b> than <code>java.util.HashMap.put(key, value)</code>.
+ * This difference is mostly due to the cost of the <code>Map.Entry</code>
+ * allocations that {@link FastMap} avoids by recycling its entries
+ * (see note below).</p>
+ *
+ * <p> {@link FastMap} has a predictable iteration order, which is the order
+ * in which keys were inserted into the map (similar to
+ * <code>java.util.LinkedHashMap</code> collection class).</p>
+ *
+ * <p> Applications may change the resizing policy of {@link FastMap}
+ * by overriding the {@link #sizeChanged} method. For example, to improve
+ * predictability, automatic resizing can be disabled.</p>
+ *
+ * <p> This implementation is not synchronized. Multiple threads accessing
+ * or modifying the collection must be synchronized externally.</p>
+ *
+ * <p> <b>Note:</b> To avoid dynamic memory allocations, {@link FastMap}
+ * maintains an internal pool of <code>Map.Entry</code> objects. The size
+ * of the pool is determined by the map's capacity. When an entry is
+ * removed from the map, it is automatically restored to the pool.</p>
+ *
+ * <p><i> This class is <b>public domain</b> (not copyrighted).</i></p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @version 5.3, October 31 2003
+ */
+public class FastMap implements Map, Cloneable, Serializable {
+
+ /**
+ * Holds the map's hash table.
+ */
+ private transient EntryImpl[] _entries;
+
+ /**
+ * Holds the map's current capacity.
+ */
+ private transient int _capacity;
+
+ /**
+ * Holds the hash code mask.
+ */
+ private transient int _mask;
+
+ /**
+ * Holds the first pool entry (linked list).
+ */
+ private transient EntryImpl _poolFirst;
+
+ /**
+ * Holds the first map entry (linked list).
+ */
+ private transient EntryImpl _mapFirst;
+
+ /**
+ * Holds the last map entry (linked list).
+ */
+ private transient EntryImpl _mapLast;
+
+ /**
+ * Holds the current size.
+ */
+ private transient int _size;
+
+ /**
+ * Creates a {@link FastMap} with a capacity of <code>256</code> entries.
+ */
+ public FastMap() {
+ initialize(256);
+ }
+
+ /**
+ * Creates a {@link FastMap}, copy of the specified <code>Map</code>.
+ * If the specified map is not an instance of {@link FastMap}, the
+ * newly created map has a capacity set to the specified map's size.
+ * The copy has the same order as the original, regardless of the original
+ * map's implementation:<pre>
+ * TreeMap dictionary = ...;
+ * FastMap dictionaryLookup = new FastMap(dictionary);
+ * </pre>
+ *
+ * @param map the map whose mappings are to be placed in this map.
+ */
+ public FastMap(Map map) {
+ int capacity = (map instanceof FastMap) ?
+ ((FastMap)map).capacity() : map.size();
+ initialize(capacity);
+ putAll(map);
+ }
+
+ /**
+ * Creates a {@link FastMap} with the specified capacity. Unless the
+ * capacity is exceeded, operations on this map do not allocate entries.
+ * For optimum performance, the capacity should be of the same order
+ * of magnitude or larger than the expected map's size.
+ *
+ * @param capacity the number of buckets in the hash table; it also
+ * defines the number of pre-allocated entries.
+ */
+ public FastMap(int capacity) {
+ initialize(capacity);
+ }
+
+ /**
+ * Returns the number of key-value mappings in this {@link FastMap}.
+ *
+ * @return this map's size.
+ */
+ public int size() {
+ return _size;
+ }
+
+ /**
+ * Returns the capacity of this {@link FastMap}. The capacity defines
+ * the number of buckets in the hash table, as well as the maximum number
+ * of entries the map may contain without allocating memory.
+ *
+ * @return this map's capacity.
+ */
+ public int capacity() {
+ return _capacity;
+ }
+
+ /**
+ * Indicates if this {@link FastMap} contains no key-value mappings.
+ *
+ * @return <code>true</code> if this map contains no key-value mappings;
+ * <code>false</code> otherwise.
+ */
+ public boolean isEmpty() {
+ return _size == 0;
+ }
+
+ /**
+ * Indicates if this {@link FastMap} contains a mapping for the specified
+ * key.
+ *
+ * @param key the key whose presence in this map is to be tested.
+ * @return <code>true</code> if this map contains a mapping for the
+ * specified key; <code>false</code> otherwise.
+ * @throws NullPointerException if the key is <code>null</code>.
+ */
+ public boolean containsKey(Object key) {
+ EntryImpl entry = _entries[keyHash(key) & _mask];
+ while (entry != null) {
+ if (key.equals(entry._key) ) {
+ return true;
+ }
+ entry = entry._next;
+ }
+ return false;
+ }
+
+ /**
+ * Indicates if this {@link FastMap} maps one or more keys to the
+ * specified value.
+ *
+ * @param value the value whose presence in this map is to be tested.
+ * @return <code>true</code> if this map maps one or more keys to the
+ * specified value.
+ * @throws NullPointerException if the key is <code>null</code>.
+ */
+ public boolean containsValue(Object value) {
+ EntryImpl entry = _mapFirst;
+ while (entry != null) {
+ if (value.equals(entry._value) ) {
+ return true;
+ }
+ entry = entry._after;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the value to which this {@link FastMap} maps the specified key.
+ *
+ * @param key the key whose associated value is to be returned.
+ * @return the value to which this map maps the specified key,
+ * or <code>null</code> if there is no mapping for the key.
+ * @throws NullPointerException if key is <code>null</code>.
+ */
+ public Object get(Object key) {
+ EntryImpl entry = _entries[keyHash(key) & _mask];
+ while (entry != null) {
+ if (key.equals(entry._key) ) {
+ return entry._value;
+ }
+ entry = entry._next;
+ }
+ return null;
+ }
+
+ /**
+ * Returns the entry with the specified key.
+ *
+ * @param key the key whose associated entry is to be returned.
+ * @return the entry for the specified key or <code>null</code> if none.
+ */
+ public Map.Entry getEntry(Object key) {
+ EntryImpl entry = _entries[keyHash(key) & _mask];
+ while (entry != null) {
+ if (key.equals(entry._key)) {
+ return entry;
+ }
+ entry = entry._next;
+ }
+ return null;
+ }
+
+ /**
+ * Associates the specified value with the specified key in this
+ * {@link FastMap}. If the {@link FastMap} previously contained a mapping
+ * for this key, the old value is replaced.
+ *
+ * @param key the key with which the specified value is to be associated.
+ * @param value the value to be associated with the specified key.
+ * @return the previous value associated with specified key,
+ * or <code>null</code> if there was no mapping for key.
+ * A <code>null</code> return can also indicate that the map
+ * previously associated <code>null</code> with the specified key.
+ * @throws NullPointerException if the key is <code>null</code>.
+ */
+ public Object put(Object key, Object value) {
+ EntryImpl entry = _entries[keyHash(key) & _mask];
+ while (entry != null) {
+ if (key.equals(entry._key) ) {
+ Object prevValue = entry._value;
+ entry._value = value;
+ return prevValue;
+ }
+ entry = entry._next;
+ }
+ // No previous mapping.
+ addEntry(key, value);
+ return null;
+ }
+
+ /**
+ * Copies all of the mappings from the specified map to this
+ * {@link FastMap}.
+ *
+ * @param map the mappings to be stored in this map.
+ * @throws NullPointerException the specified map is <code>null</code>, or
+ * the specified map contains <code>null</code> keys.
+ */
+ public void putAll(Map map) {
+ for (Iterator i = map.entrySet().iterator(); i.hasNext(); ) {
+ Map.Entry e = (Map.Entry) i.next();
+ addEntry(e.getKey(), e.getValue());
+ }
+ }
+
+ /**
+ * Removes the mapping for this key from this {@link FastMap} if present.
+ *
+ * @param key the key whose mapping is to be removed from the map.
+ * @return previous value associated with specified key,
+ * or <code>null</code> if there was no mapping for key.
+ * A <code>null</code> return can also indicate that the map
+ * previously associated <code>null</code> with the specified key.
+ * @throws NullPointerException if the key is <code>null</code>.
+ */
+ public Object remove(Object key) {
+ EntryImpl entry = _entries[keyHash(key) & _mask];
+ while (entry != null) {
+ if (key.equals(entry._key) ) {
+ Object prevValue = entry._value;
+ removeEntry(entry);
+ return prevValue;
+ }
+ entry = entry._next;
+ }
+ return null;
+ }
+
+ /**
+ * Removes all mappings from this {@link FastMap}.
+ */
+ public void clear() {
+ // Clears all keys, values and buckets linked lists.
+ for (EntryImpl entry = _mapFirst; entry != null; entry = entry._after) {
+ entry._key = null;
+ entry._value = null;
+ entry._before = null;
+ entry._next = null;
+ if (entry._previous == null) { // First in bucket.
+ _entries[entry._index] = null;
+ } else {
+ entry._previous = null;
+ }
+ }
+
+ // Recycles all entries.
+ if (_mapLast != null) {
+ _mapLast._after = _poolFirst; // Connects to pool.
+ _poolFirst = _mapFirst;
+ _mapFirst = null;
+ _mapLast = null;
+ _size = 0;
+ sizeChanged();
+ }
+ }
+
+ /**
+ * Changes the current capacity of this {@link FastMap}. If the capacity
+ * is increased, new entries are allocated and added to the pool.
+ * If the capacity is decreased, entries from the pool are deallocated
+ * (and are eventually garbage collected). The capacity also determined
+ * the number of buckets for the hash table.
+ *
+ * @param newCapacity the new capacity of this map.
+ */
+ public void setCapacity(int newCapacity) {
+ if (newCapacity > _capacity) { // Capacity increases.
+ for (int i = _capacity; i < newCapacity; i++) {
+ EntryImpl entry = new EntryImpl();
+ entry._after = _poolFirst;
+ _poolFirst = entry;
+ }
+ } else if (newCapacity < _capacity) { // Capacity decreases.
+ for ( int i = newCapacity;
+ (i < _capacity) && (_poolFirst != null); i++) {
+ // Disconnects the entry for gc to do its work.
+ EntryImpl entry = _poolFirst;
+ _poolFirst = entry._after;
+ entry._after = null; // All pointers are now null!
+ }
+ }
+ // Find a power of 2 >= capacity
+ int tableLength = 16;
+ while (tableLength < newCapacity) {
+ tableLength <<= 1;
+ }
+ // Checks if the hash table has to be re-sized.
+ if (_entries.length != tableLength) {
+ _entries = new EntryImpl[tableLength];
+ _mask = tableLength - 1;
+
+ // Repopulates the hash table.
+ EntryImpl entry = _mapFirst;
+ while (entry != null) {
+ int index = keyHash(entry._key) & _mask;
+ entry._index = index;
+
+ // Connects to bucket.
+ entry._previous = null; // Resets previous.
+ EntryImpl next = _entries[index];
+ entry._next = next;
+ if (next != null) {
+ next._previous = entry;
+ }
+ _entries[index] = entry;
+
+ entry = entry._after;
+ }
+ }
+ _capacity = newCapacity;
+ }
+
+ /**
+ * Returns a shallow copy of this {@link FastMap}. The keys and
+ * the values themselves are not cloned.
+ *
+ * @return a shallow copy of this map.
+ */
+ public Object clone() {
+ try {
+ FastMap clone = (FastMap) super.clone();
+ clone.initialize(_capacity);
+ clone.putAll(this);
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ // Should not happen, since we are Cloneable.
+ throw new InternalError();
+ }
+ }
+
+ /**
+ * Compares the specified object with this {@link FastMap} for equality.
+ * Returns <code>true</code> if the given object is also a map and the two
+ * maps represent the same mappings (regardless of collection iteration
+ * order).
+ *
+ * @param obj the object to be compared for equality with this map.
+ * @return <code>true</code> if the specified object is equal to this map;
+ * <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ } else if (obj instanceof Map) {
+ Map that = (Map) obj;
+ if (this.size() == that.size()) {
+ EntryImpl entry = _mapFirst;
+ while (entry != null) {
+ if (!that.entrySet().contains(entry)) {
+ return false;
+ }
+ entry = entry._after;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the hash code value for this {@link FastMap}.
+ *
+ * @return the hash code value for this map.
+ */
+ public int hashCode() {
+ int code = 0;
+ EntryImpl entry = _mapFirst;
+ while (entry != null) {
+ code += entry.hashCode();
+ entry = entry._after;
+ }
+ return code;
+ }
+
+ /**
+ * Returns a <code>String</code> representation of this {@link FastMap}.
+ *
+ * @return <code>this.entrySet().toString();</code>
+ */
+ public String toString() {
+ return entrySet().toString();
+ }
+
+ /**
+ * Returns a collection view of the values contained in this
+ * {@link FastMap}. The collection is backed by the map, so changes to
+ * the map are reflected in the collection, and vice-versa.
+ * The collection supports element removal, which removes the corresponding
+ * mapping from this map, via the
+ * <code>Iterator.remove</code>, <code>Collection.remove</code>,
+ * <code>removeAll</code>, <code>retainAll</code>,
+ * and <code>clear</code> operations. It does not support the
+ * <code>add</code> or <code>addAll</code> operations.
+ *
+ * @return a collection view of the values contained in this map.
+ */
+ public Collection values() {
+ return _values;
+ }
+ private transient Values _values;
+ private class Values extends AbstractCollection {
+ public Iterator iterator() {
+ return new Iterator() {
+ EntryImpl after = _mapFirst;
+ EntryImpl before;
+ public void remove() {
+ removeEntry(before);
+ }
+ public boolean hasNext() {
+ return after != null;
+ }
+ public Object next() {
+ before = after;
+ after = after._after;
+ return before._value;
+ }
+ };
+ }
+ public int size() {
+ return _size;
+ }
+ public boolean contains(Object o) {
+ return containsValue(o);
+ }
+ public void clear() {
+ FastMap.this.clear();
+ }
+ }
+
+ /**
+ * Returns a collection view of the mappings contained in this
+ * {@link FastMap}. Each element in the returned collection is a
+ * <code>Map.Entry</code>. The collection is backed by the map,
+ * so changes to the map are reflected in the collection, and vice-versa.
+ * The collection supports element removal, which removes the corresponding
+ * mapping from this map, via the
+ * <code>Iterator.remove</code>, <code>Collection.remove</code>,
+ * <code>removeAll</code>, <code>retainAll</code>,
+ * and <code>clear</code> operations. It does not support the
+ * <code>add</code> or <code>addAll</code> operations.
+ *
+ * @return a collection view of the mappings contained in this map.
+ */
+ public Set entrySet() {
+ return _entrySet;
+ }
+ private transient EntrySet _entrySet;
+ private class EntrySet extends AbstractSet {
+ public Iterator iterator() {
+ return new Iterator() {
+ EntryImpl after = _mapFirst;
+ EntryImpl before;
+ public void remove() {
+ removeEntry(before);
+ }
+ public boolean hasNext() {
+ return after != null;
+ }
+ public Object next() {
+ before = after;
+ after = after._after;
+ return before;
+ }
+ };
+ }
+ public int size() {
+ return _size;
+ }
+ public boolean contains(Object obj) { // Optimization.
+ if (obj instanceof Map.Entry) {
+ Map.Entry entry = (Map.Entry) obj;
+ Map.Entry mapEntry = getEntry(entry.getKey());
+ return entry.equals(mapEntry);
+ } else {
+ return false;
+ }
+ }
+ public boolean remove(Object obj) { // Optimization.
+ if (obj instanceof Map.Entry) {
+ Map.Entry entry = (Map.Entry)obj;
+ EntryImpl mapEntry = (EntryImpl) getEntry(entry.getKey());
+ if ((mapEntry != null) &&
+ (entry.getValue()).equals(mapEntry._value)) {
+ removeEntry(mapEntry);
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * Returns a set view of the keys contained in this {@link FastMap}.
+ * The set is backed by the map, so changes to the map are reflected
+ * in the set, and vice-versa. The set supports element removal,
+ * which removes the corresponding mapping from this map, via the
+ * <code>Iterator.remove</code>, <code>Collection.remove</code>,
+ * <code>removeAll</code>, <code>retainAll</code>,
+ * and <code>clear</code> operations. It does not support the
+ * <code>add</code> or <code>addAll</code> operations.
+ *
+ * @return a set view of the keys contained in this map.
+ */
+ public Set keySet() {
+ return _keySet;
+ }
+ private transient KeySet _keySet;
+ private class KeySet extends AbstractSet {
+ public Iterator iterator() {
+ return new Iterator() {
+ EntryImpl after = _mapFirst;
+ EntryImpl before;
+ public void remove() {
+ removeEntry(before);
+ }
+ public boolean hasNext() {
+ return after != null;
+ }
+ public Object next() {
+ before = after;
+ after = after._after;
+ return before._key;
+ }
+ };
+ }
+ public int size() {
+ return _size;
+ }
+ public boolean contains(Object obj) { // Optimization.
+ return FastMap.this.containsKey(obj);
+ }
+ public boolean remove(Object obj) { // Optimization.
+ return FastMap.this.remove(obj) != null;
+ }
+ public void clear() { // Optimization.
+ FastMap.this.clear();
+ }
+ }
+
+ /**
+ * This methods is being called when the size of this {@link FastMap}
+ * has changed. The default behavior is to double the map's capacity
+ * when the map's size reaches the current map's capacity.
+ * Sub-class may override this method to implement custom resizing
+ * policies or to disable automatic resizing. For example:<pre>
+ * Map fixedCapacityMap = new FastMap(256) {
+ * protected sizeChanged() {
+ * // Do nothing, automatic resizing disabled.
+ * }
+ * };</pre>
+ * @see #setCapacity
+ */
+ protected void sizeChanged() {
+ if (size() > capacity()) {
+ setCapacity(capacity() * 2);
+ }
+ }
+
+ /**
+ * Returns the hash code for the specified key. The formula being used
+ * is identical to the formula used by <code>java.util.HashMap</code>
+ * (ensures similar behavior for ill-conditioned hashcode keys).
+ *
+ * @param key the key to calculate the hashcode for.
+ * @return the hash code for the specified key.
+ */
+ private static int keyHash(Object key) {
+ // From HashMap.hash(Object) function.
+ int hashCode = key.hashCode();
+ hashCode += ~(hashCode << 9);
+ hashCode ^= (hashCode >>> 14);
+ hashCode += (hashCode << 4);
+ hashCode ^= (hashCode >>> 10);
+ return hashCode;
+ }
+
+ /**
+ * Adds a new entry for the specified key and value.
+ * @param key the entry's key.
+ * @param value the entry's value.
+ */
+ private void addEntry(Object key, Object value) {
+ EntryImpl entry = _poolFirst;
+ if (entry != null) {
+ _poolFirst = entry._after;
+ entry._after = null;
+ } else { // Pool empty.
+ entry = new EntryImpl();
+ }
+
+ // Setup entry paramters.
+ entry._key = key;
+ entry._value = value;
+ int index = keyHash(key) & _mask;
+ entry._index = index;
+
+ // Connects to bucket.
+ EntryImpl next = _entries[index];
+ entry._next = next;
+ if (next != null) {
+ next._previous = entry;
+ }
+ _entries[index] = entry;
+
+ // Connects to collection.
+ if (_mapLast != null) {
+ entry._before = _mapLast;
+ _mapLast._after = entry;
+ } else {
+ _mapFirst = entry;
+ }
+ _mapLast = entry;
+
+ // Updates size.
+ _size++;
+ sizeChanged();
+ }
+
+ /**
+ * Removes the specified entry from the map.
+ *
+ * @param entry the entry to be removed.
+ */
+ private void removeEntry(EntryImpl entry) {
+
+ // Removes from bucket.
+ EntryImpl previous = entry._previous;
+ EntryImpl next = entry._next;
+ if (previous != null) {
+ previous._next = next;
+ entry._previous = null;
+ } else { // First in bucket.
+ _entries[entry._index] = next;
+ }
+ if (next != null) {
+ next._previous = previous;
+ entry._next = null;
+ } // Else do nothing, no last pointer.
+
+ // Removes from collection.
+ EntryImpl before = entry._before;
+ EntryImpl after = entry._after;
+ if (before != null) {
+ before._after = after;
+ entry._before = null;
+ } else { // First in collection.
+ _mapFirst = after;
+ }
+ if (after != null) {
+ after._before = before;
+ } else { // Last in collection.
+ _mapLast = before;
+ }
+
+ // Clears value and key.
+ entry._key = null;
+ entry._value = null;
+
+ // Recycles.
+ entry._after = _poolFirst;
+ _poolFirst = entry;
+
+ // Updates size.
+ _size--;
+ sizeChanged();
+ }
+
+ /**
+ * Initializes this instance for the specified capacity.
+ * Once initialized, operations on this map should not create new objects
+ * (unless the map's size exceeds the specified capacity).
+ *
+ * @param capacity the initial capacity.
+ */
+ private void initialize(int capacity) {
+ // Find a power of 2 >= capacity
+ int tableLength = 16;
+ while (tableLength < capacity) {
+ tableLength <<= 1;
+ }
+ // Allocates hash table.
+ _entries = new EntryImpl[tableLength];
+ _mask = tableLength - 1;
+ _capacity = capacity;
+ _size = 0;
+ // Allocates views.
+ _values = new Values();
+ _entrySet = new EntrySet();
+ _keySet = new KeySet();
+ // Resets pointers.
+ _poolFirst = null;
+ _mapFirst = null;
+ _mapLast = null;
+ // Allocates entries.
+ for (int i=0; i < capacity; i++) {
+ EntryImpl entry = new EntryImpl();
+ entry._after = _poolFirst;
+ _poolFirst = entry;
+ }
+ }
+
+ /**
+ * Requires special handling during de-serialization process.
+ *
+ * @param stream the object input stream.
+ * @throws IOException if an I/O error occurs.
+ * @throws ClassNotFoundException if the class for the object de-serialized
+ * is not found.
+ */
+ private void readObject(ObjectInputStream stream)
+ throws IOException, ClassNotFoundException {
+ int capacity = stream.readInt();
+ initialize(capacity);
+ int size = stream.readInt();
+ for (int i=0; i < size; i++) {
+ Object key = stream.readObject();
+ Object value = stream.readObject();
+ addEntry(key, value);
+ }
+ }
+
+ /**
+ * Requires special handling during serialization process.
+ *
+ * @param stream the object output stream.
+ * @throws IOException if an I/O error occurs.
+ */
+ private void writeObject(ObjectOutputStream stream) throws IOException {
+ stream.writeInt(_capacity);
+ stream.writeInt(_size);
+ int count = 0;
+ EntryImpl entry = _mapFirst;
+ while (entry != null) {
+ stream.writeObject(entry._key);
+ stream.writeObject(entry._value);
+ count++;
+ entry = entry._after;
+ }
+ if (count != _size) {
+ throw new IOException("FastMap Corrupted");
+ }
+ }
+
+ /**
+ * This class represents a {@link FastMap} entry.
+ */
+ private static final class EntryImpl implements Map.Entry {
+
+ /**
+ * Holds the entry key (null when in pool).
+ */
+ private Object _key;
+
+ /**
+ * Holds the entry value (null when in pool).
+ */
+ private Object _value;
+
+ /**
+ * Holds the bucket index (undefined when in pool).
+ */
+ private int _index;
+
+ /**
+ * Holds the previous entry in the same bucket (null when in pool).
+ */
+ private EntryImpl _previous;
+
+ /**
+ * Holds the next entry in the same bucket (null when in pool).
+ */
+ private EntryImpl _next;
+
+ /**
+ * Holds the entry added before this entry (null when in pool).
+ */
+ private EntryImpl _before;
+
+ /**
+ * Holds the entry added after this entry
+ * or the next available entry when in pool.
+ */
+ private EntryImpl _after;
+
+ /**
+ * Returns the key for this entry.
+ *
+ * @return the entry's key.
+ */
+ public Object getKey() {
+ return _key;
+ }
+
+ /**
+ * Returns the value for this entry.
+ *
+ * @return the entry's value.
+ */
+ public Object getValue() {
+ return _value;
+ }
+
+ /**
+ * Sets the value for this entry.
+ *
+ * @param value the new value.
+ * @return the previous value.
+ */
+ public Object setValue(Object value) {
+ Object old = _value;
+ _value = value;
+ return old;
+ }
+
+ /**
+ * Indicates if this entry is considered equals to the specified
+ * entry.
+ *
+ * @param that the object to test for equality.
+ * @return <code>true<code> if both entry are considered equal;
+ * <code>false<code> otherwise.
+ */
+ public boolean equals(Object that) {
+ if (that instanceof Map.Entry) {
+ Map.Entry entry = (Map.Entry) that;
+ return (_key.equals(entry.getKey())) &&
+ ((_value != null) ?
+ _value.equals(entry.getValue()) :
+ (entry.getValue() == null));
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the hash code for this entry.
+ *
+ * @return this entry's hash code.
+ */
+ public int hashCode() {
+ return _key.hashCode() ^ ((_value != null) ? _value.hashCode() : 0);
+ }
+
+ /**
+ * Returns the text representation of this entry.
+ *
+ * @return this entry's textual representation.
+ */
+ public String toString() {
+ return _key + "=" + _value;
+ }
+ }
+}
\ No newline at end of file
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/FastMap.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/FastMap.java
------------------------------------------------------------------------------
svn:keywords = Date Revision
Propchange: geronimo/sandbox/djencks/osgi/framework/modules/geronimo-plugin/src/main/java/org/apache/geronimo/system/plugin/plexus/util/FastMap.java
------------------------------------------------------------------------------
svn:mime-type = text/plain