From a46d02ca32f52a7e1734b56dfc9f201e674569c6 Mon Sep 17 00:00:00 2001 From: Florian Schmaus Date: Mon, 17 Mar 2014 10:26:39 +0100 Subject: [PATCH] Remove old Apache commons collections from codebase ChatManager's Chat instances are now removed by Chat.close(), removing the need for a Map with Hard to Weak references. ChatStateManager can simply use WeakHashMap. --- .../java/org/jivesoftware/smack/Chat.java | 3 +- .../org/jivesoftware/smack/ChatManager.java | 11 +- .../org/jivesoftware/smack/util/Cache.java | 65 +- .../collections/AbstractEmptyIterator.java | 89 -- .../util/collections/AbstractHashedMap.java | 1339 ----------------- .../util/collections/AbstractKeyValue.java | 80 - .../util/collections/AbstractMapEntry.java | 89 -- .../collections/AbstractReferenceMap.java | 1026 ------------- .../util/collections/DefaultMapEntry.java | 65 - .../smack/util/collections/EmptyIterator.java | 58 - .../util/collections/EmptyMapIterator.java | 42 - .../smack/util/collections/IterableMap.java | 61 - .../smack/util/collections/KeyValue.java | 46 - .../smack/util/collections/MapIterator.java | 109 -- .../smack/util/collections/ReferenceMap.java | 161 -- .../util/collections/ResettableIterator.java | 38 - .../smackx/chatstates/ChatStateManager.java | 14 +- 17 files changed, 72 insertions(+), 3224 deletions(-) delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/AbstractEmptyIterator.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/AbstractHashedMap.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/AbstractKeyValue.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/AbstractMapEntry.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/AbstractReferenceMap.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/DefaultMapEntry.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/EmptyIterator.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/EmptyMapIterator.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/IterableMap.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/KeyValue.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/MapIterator.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/ReferenceMap.java delete mode 100644 core/src/main/java/org/jivesoftware/smack/util/collections/ResettableIterator.java diff --git a/core/src/main/java/org/jivesoftware/smack/Chat.java b/core/src/main/java/org/jivesoftware/smack/Chat.java index b511914c9..0cdf36696 100644 --- a/core/src/main/java/org/jivesoftware/smack/Chat.java +++ b/core/src/main/java/org/jivesoftware/smack/Chat.java @@ -99,9 +99,8 @@ public class Chat { * and message type of the message will automatically set to those of this chat. * * @param message the message to send. - * @throws XMPPException if an error occurs sending the message. */ - public void sendMessage(Message message) throws XMPPException { + public void sendMessage(Message message) { // Force the recipient, message type, and thread ID since the user elected // to send the message through this chat object. message.setTo(participant); diff --git a/core/src/main/java/org/jivesoftware/smack/ChatManager.java b/core/src/main/java/org/jivesoftware/smack/ChatManager.java index 151d1fe87..6bb216cf2 100644 --- a/core/src/main/java/org/jivesoftware/smack/ChatManager.java +++ b/core/src/main/java/org/jivesoftware/smack/ChatManager.java @@ -19,6 +19,7 @@ package org.jivesoftware.smack; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -33,7 +34,6 @@ import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Message.Type; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smack.util.collections.ReferenceMap; /** * The chat manager keeps track of references to all current chats. It will not hold any references @@ -87,20 +87,17 @@ public class ChatManager { /** * Maps thread ID to chat. */ - private Map threadChats = Collections.synchronizedMap(new ReferenceMap(ReferenceMap.HARD, - ReferenceMap.WEAK)); + private Map threadChats = Collections.synchronizedMap(new HashMap()); /** * Maps jids to chats */ - private Map jidChats = Collections.synchronizedMap(new ReferenceMap(ReferenceMap.HARD, - ReferenceMap.WEAK)); + private Map jidChats = Collections.synchronizedMap(new HashMap()); /** * Maps base jids to chats */ - private Map baseJidChats = Collections.synchronizedMap(new ReferenceMap(ReferenceMap.HARD, - ReferenceMap.WEAK)); + private Map baseJidChats = Collections.synchronizedMap(new HashMap()); private Set chatManagerListeners = new CopyOnWriteArraySet(); diff --git a/core/src/main/java/org/jivesoftware/smack/util/Cache.java b/core/src/main/java/org/jivesoftware/smack/util/Cache.java index a350faaef..0f89cb606 100644 --- a/core/src/main/java/org/jivesoftware/smack/util/Cache.java +++ b/core/src/main/java/org/jivesoftware/smack/util/Cache.java @@ -16,8 +16,6 @@ */ package org.jivesoftware.smack.util; -import org.jivesoftware.smack.util.collections.AbstractMapEntry; - import java.util.*; import java.util.logging.Logger; @@ -675,4 +673,67 @@ public class Cache implements Map { return object.toString(); } } + + static class AbstractMapEntry implements Map.Entry { + final K key; + V value; + + AbstractMapEntry(K key, V value) { + this.key = key; + this.value = value; + } + + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return value; + } + + @Override + public V setValue(V value) { + V answer = this.value; + this.value = value; + return answer; + } + + /** + * Compares this Map Entry with another Map Entry. + *

+ * Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)} + * + * @param obj the object to compare to + * @return true if equal key and value + */ + @SuppressWarnings("rawtypes") + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof Map.Entry == false) { + return false; + } + Map.Entry other = (Map.Entry) obj; + return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) + && (getValue() == null ? other.getValue() == null : getValue().equals( + other.getValue())); + } + + /** + * Gets a hashCode compatible with the equals method. + *

+ * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()} + * + * @return a suitable hash code + */ + @Override + public int hashCode() { + return (getKey() == null ? 0 : getKey().hashCode()) + ^ (getValue() == null ? 0 : getValue().hashCode()); + } + } } diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractEmptyIterator.java b/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractEmptyIterator.java deleted file mode 100644 index 67f0dd4f0..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractEmptyIterator.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * - * Copyright 2004 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. - */ -package org.jivesoftware.smack.util.collections; - -import java.util.NoSuchElementException; - -/** - * Provides an implementation of an empty iterator. - * - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $ - * @since Commons Collections 3.1 - */ -abstract class AbstractEmptyIterator { - - /** - * Constructor. - */ - protected AbstractEmptyIterator() { - super(); - } - - public boolean hasNext() { - return false; - } - - public E next() { - throw new NoSuchElementException("Iterator contains no elements"); - } - - public boolean hasPrevious() { - return false; - } - - public E previous() { - throw new NoSuchElementException("Iterator contains no elements"); - } - - public int nextIndex() { - return 0; - } - - public int previousIndex() { - return -1; - } - - public void add(E obj) { - throw new UnsupportedOperationException("add() not supported for empty Iterator"); - } - - public void set(E obj) { - throw new IllegalStateException("Iterator contains no elements"); - } - - public void remove() { - throw new IllegalStateException("Iterator contains no elements"); - } - - public E getKey() { - throw new IllegalStateException("Iterator contains no elements"); - } - - public E getValue() { - throw new IllegalStateException("Iterator contains no elements"); - } - - public E setValue(E value) { - throw new IllegalStateException("Iterator contains no elements"); - } - - public void reset() { - // do nothing - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractHashedMap.java b/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractHashedMap.java deleted file mode 100644 index e8ec3201d..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractHashedMap.java +++ /dev/null @@ -1,1339 +0,0 @@ -/** - * - * Copyright 2003-2004 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. - */ -// GenericsNote: Converted -- However, null keys will now be represented in the internal structures, a big change. -package org.jivesoftware.smack.util.collections; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.*; - -/** - * An abstract implementation of a hash-based map which provides numerous points for - * subclasses to override. - *

- * This class implements all the features necessary for a subclass hash-based map. - * Key-value entries are stored in instances of the HashEntry class, - * which can be overridden and replaced. The iterators can similarly be replaced, - * without the need to replace the KeySet, EntrySet and Values view classes. - *

- * Overridable methods are provided to change the default hashing behaviour, and - * to change how entries are added to and removed from the map. Hopefully, all you - * need for unusual subclasses is here. - *

- * NOTE: From Commons Collections 3.1 this class extends AbstractMap. - * This is to provide backwards compatibility for ReferenceMap between v3.0 and v3.1. - * This extends clause will be removed in v4.0. - * - * @author java util HashMap - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $ - * @since Commons Collections 3.0 - */ -public class AbstractHashedMap extends AbstractMap implements IterableMap { - - protected static final String NO_NEXT_ENTRY = "No next() entry in the iteration"; - protected static final String NO_PREVIOUS_ENTRY = "No previous() entry in the iteration"; - protected static final String REMOVE_INVALID = "remove() can only be called once after next()"; - protected static final String GETKEY_INVALID = "getKey() can only be called after next() and before remove()"; - protected static final String GETVALUE_INVALID = "getValue() can only be called after next() and before remove()"; - protected static final String SETVALUE_INVALID = "setValue() can only be called after next() and before remove()"; - - /** - * The default capacity to use - */ - protected static final int DEFAULT_CAPACITY = 16; - /** - * The default threshold to use - */ - protected static final int DEFAULT_THRESHOLD = 12; - /** - * The default load factor to use - */ - protected static final float DEFAULT_LOAD_FACTOR = 0.75f; - /** - * The maximum capacity allowed - */ - protected static final int MAXIMUM_CAPACITY = 1 << 30; - /** - * An object for masking null - */ - protected static final Object NULL = new Object(); - - /** - * Load factor, normally 0.75 - */ - protected transient float loadFactor; - /** - * The size of the map - */ - protected transient int size; - /** - * Map entries - */ - protected transient HashEntry[] data; - /** - * Size at which to rehash - */ - protected transient int threshold; - /** - * Modification count for iterators - */ - protected transient int modCount; - /** - * Entry set - */ - protected transient EntrySet entrySet; - /** - * Key set - */ - protected transient KeySet keySet; - /** - * Values - */ - protected transient Values values; - - /** - * Constructor only used in deserialization, do not use otherwise. - */ - protected AbstractHashedMap() { - super(); - } - - /** - * Constructor which performs no validation on the passed in parameters. - * - * @param initialCapacity the initial capacity, must be a power of two - * @param loadFactor the load factor, must be > 0.0f and generally < 1.0f - * @param threshold the threshold, must be sensible - */ - protected AbstractHashedMap(int initialCapacity, float loadFactor, int threshold) { - super(); - this.loadFactor = loadFactor; - this.data = new HashEntry[initialCapacity]; - this.threshold = threshold; - init(); - } - - /** - * Constructs a new, empty map with the specified initial capacity and - * default load factor. - * - * @param initialCapacity the initial capacity - * @throws IllegalArgumentException if the initial capacity is less than one - */ - protected AbstractHashedMap(int initialCapacity) { - this(initialCapacity, DEFAULT_LOAD_FACTOR); - } - - /** - * Constructs a new, empty map with the specified initial capacity and - * load factor. - * - * @param initialCapacity the initial capacity - * @param loadFactor the load factor - * @throws IllegalArgumentException if the initial capacity is less than one - * @throws IllegalArgumentException if the load factor is less than or equal to zero - */ - protected AbstractHashedMap(int initialCapacity, float loadFactor) { - super(); - if (initialCapacity < 1) { - throw new IllegalArgumentException("Initial capacity must be greater than 0"); - } - if (loadFactor <= 0.0f || Float.isNaN(loadFactor)) { - throw new IllegalArgumentException("Load factor must be greater than 0"); - } - this.loadFactor = loadFactor; - this.threshold = calculateThreshold(initialCapacity, loadFactor); - initialCapacity = calculateNewCapacity(initialCapacity); - this.data = new HashEntry[initialCapacity]; - init(); - } - - /** - * Constructor copying elements from another map. - * - * @param map the map to copy - * @throws NullPointerException if the map is null - */ - protected AbstractHashedMap(Map map) { - this(Math.max(2 * map.size(), DEFAULT_CAPACITY), DEFAULT_LOAD_FACTOR); - putAll(map); - } - - /** - * Initialise subclasses during construction, cloning or deserialization. - */ - protected void init() { - } - - //----------------------------------------------------------------------- - /** - * Gets the value mapped to the key specified. - * - * @param key the key - * @return the mapped value, null if no match - */ - public V get(Object key) { - int hashCode = hash((key == null) ? NULL : key); - HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index - while (entry != null) { - if (entry.hashCode == hashCode && isEqualKey(key, entry.key)) { - return entry.getValue(); - } - entry = entry.next; - } - return null; - } - - /** - * Gets the size of the map. - * - * @return the size - */ - public int size() { - return size; - } - - /** - * Checks whether the map is currently empty. - * - * @return true if the map is currently size zero - */ - public boolean isEmpty() { - return (size == 0); - } - - //----------------------------------------------------------------------- - /** - * Checks whether the map contains the specified key. - * - * @param key the key to search for - * @return true if the map contains the key - */ - public boolean containsKey(Object key) { - int hashCode = hash((key == null) ? NULL : key); - HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index - while (entry != null) { - if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) { - return true; - } - entry = entry.next; - } - return false; - } - - /** - * Checks whether the map contains the specified value. - * - * @param value the value to search for - * @return true if the map contains the value - */ - public boolean containsValue(Object value) { - if (value == null) { - for (int i = 0, isize = data.length; i < isize; i++) { - HashEntry entry = data[i]; - while (entry != null) { - if (entry.getValue() == null) { - return true; - } - entry = entry.next; - } - } - } else { - for (int i = 0, isize = data.length; i < isize; i++) { - HashEntry entry = data[i]; - while (entry != null) { - if (isEqualValue(value, entry.getValue())) { - return true; - } - entry = entry.next; - } - } - } - return false; - } - - //----------------------------------------------------------------------- - /** - * Puts a key-value mapping into this map. - * - * @param key the key to add - * @param value the value to add - * @return the value previously mapped to this key, null if none - */ - public V put(K key, V value) { - int hashCode = hash((key == null) ? NULL : key); - int index = hashIndex(hashCode, data.length); - HashEntry entry = data[index]; - while (entry != null) { - if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) { - V oldValue = entry.getValue(); - updateEntry(entry, value); - return oldValue; - } - entry = entry.next; - } - addMapping(index, hashCode, key, value); - return null; - } - - /** - * Puts all the values from the specified map into this map. - *

- * This implementation iterates around the specified map and - * uses {@link #put(Object, Object)}. - * - * @param map the map to add - * @throws NullPointerException if the map is null - */ - public void putAll(Map map) { - int mapSize = map.size(); - if (mapSize == 0) { - return; - } - int newSize = (int) ((size + mapSize) / loadFactor + 1); - ensureCapacity(calculateNewCapacity(newSize)); - // Have to cast here because of compiler inference problems. - for (Iterator it = map.entrySet().iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - put(entry.getKey(), entry.getValue()); - } - } - - /** - * Removes the specified mapping from this map. - * - * @param key the mapping to remove - * @return the value mapped to the removed key, null if key not in map - */ - public V remove(Object key) { - int hashCode = hash((key == null) ? NULL : key); - int index = hashIndex(hashCode, data.length); - HashEntry entry = data[index]; - HashEntry previous = null; - while (entry != null) { - if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) { - V oldValue = entry.getValue(); - removeMapping(entry, index, previous); - return oldValue; - } - previous = entry; - entry = entry.next; - } - return null; - } - - /** - * Clears the map, resetting the size to zero and nullifying references - * to avoid garbage collection issues. - */ - public void clear() { - modCount++; - HashEntry[] data = this.data; - for (int i = data.length - 1; i >= 0; i--) { - data[i] = null; - } - size = 0; - } - - /** - * Gets the hash code for the key specified. - * This implementation uses the additional hashing routine from JDK1.4. - * Subclasses can override this to return alternate hash codes. - * - * @param key the key to get a hash code for - * @return the hash code - */ - protected int hash(Object key) { - // same as JDK 1.4 - int h = key.hashCode(); - h += ~(h << 9); - h ^= (h >>> 14); - h += (h << 4); - h ^= (h >>> 10); - return h; - } - - /** - * Compares two keys, in internal converted form, to see if they are equal. - * This implementation uses the equals method. - * Subclasses can override this to match differently. - * - * @param key1 the first key to compare passed in from outside - * @param key2 the second key extracted from the entry via entry.key - * @return true if equal - */ - protected boolean isEqualKey(Object key1, Object key2) { - return (key1 == key2 || ((key1 != null) && key1.equals(key2))); - } - - /** - * Compares two values, in external form, to see if they are equal. - * This implementation uses the equals method and assumes neither value is null. - * Subclasses can override this to match differently. - * - * @param value1 the first value to compare passed in from outside - * @param value2 the second value extracted from the entry via getValue() - * @return true if equal - */ - protected boolean isEqualValue(Object value1, Object value2) { - return (value1 == value2 || value1.equals(value2)); - } - - /** - * Gets the index into the data storage for the hashCode specified. - * This implementation uses the least significant bits of the hashCode. - * Subclasses can override this to return alternate bucketing. - * - * @param hashCode the hash code to use - * @param dataSize the size of the data to pick a bucket from - * @return the bucket index - */ - protected int hashIndex(int hashCode, int dataSize) { - return hashCode & (dataSize - 1); - } - - //----------------------------------------------------------------------- - /** - * Gets the entry mapped to the key specified. - *

- * This method exists for subclasses that may need to perform a multi-step - * process accessing the entry. The public methods in this class don't use this - * method to gain a small performance boost. - * - * @param key the key - * @return the entry, null if no match - */ - protected HashEntry getEntry(Object key) { - int hashCode = hash((key == null) ? NULL : key); - HashEntry entry = data[hashIndex(hashCode, data.length)]; // no local for hash index - while (entry != null) { - if (entry.hashCode == hashCode && isEqualKey(key, entry.getKey())) { - return entry; - } - entry = entry.next; - } - return null; - } - - //----------------------------------------------------------------------- - /** - * Updates an existing key-value mapping to change the value. - *

- * This implementation calls setValue() on the entry. - * Subclasses could override to handle changes to the map. - * - * @param entry the entry to update - * @param newValue the new value to store - */ - protected void updateEntry(HashEntry entry, V newValue) { - entry.setValue(newValue); - } - - /** - * Reuses an existing key-value mapping, storing completely new data. - *

- * This implementation sets all the data fields on the entry. - * Subclasses could populate additional entry fields. - * - * @param entry the entry to update, not null - * @param hashIndex the index in the data array - * @param hashCode the hash code of the key to add - * @param key the key to add - * @param value the value to add - */ - protected void reuseEntry(HashEntry entry, int hashIndex, int hashCode, K key, V value) { - entry.next = data[hashIndex]; - entry.hashCode = hashCode; - entry.key = key; - entry.value = value; - } - - //----------------------------------------------------------------------- - /** - * Adds a new key-value mapping into this map. - *

- * This implementation calls createEntry(), addEntry() - * and checkCapacity(). - * It also handles changes to modCount and size. - * Subclasses could override to fully control adds to the map. - * - * @param hashIndex the index into the data array to store at - * @param hashCode the hash code of the key to add - * @param key the key to add - * @param value the value to add - */ - protected void addMapping(int hashIndex, int hashCode, K key, V value) { - modCount++; - HashEntry entry = createEntry(data[hashIndex], hashCode, key, value); - addEntry(entry, hashIndex); - size++; - checkCapacity(); - } - - /** - * Creates an entry to store the key-value data. - *

- * This implementation creates a new HashEntry instance. - * Subclasses can override this to return a different storage class, - * or implement caching. - * - * @param next the next entry in sequence - * @param hashCode the hash code to use - * @param key the key to store - * @param value the value to store - * @return the newly created entry - */ - protected HashEntry createEntry(HashEntry next, int hashCode, K key, V value) { - return new HashEntry(next, hashCode, key, value); - } - - /** - * Adds an entry into this map. - *

- * This implementation adds the entry to the data storage table. - * Subclasses could override to handle changes to the map. - * - * @param entry the entry to add - * @param hashIndex the index into the data array to store at - */ - protected void addEntry(HashEntry entry, int hashIndex) { - data[hashIndex] = entry; - } - - //----------------------------------------------------------------------- - /** - * Removes a mapping from the map. - *

- * This implementation calls removeEntry() and destroyEntry(). - * It also handles changes to modCount and size. - * Subclasses could override to fully control removals from the map. - * - * @param entry the entry to remove - * @param hashIndex the index into the data structure - * @param previous the previous entry in the chain - */ - protected void removeMapping(HashEntry entry, int hashIndex, HashEntry previous) { - modCount++; - removeEntry(entry, hashIndex, previous); - size--; - destroyEntry(entry); - } - - /** - * Removes an entry from the chain stored in a particular index. - *

- * This implementation removes the entry from the data storage table. - * The size is not updated. - * Subclasses could override to handle changes to the map. - * - * @param entry the entry to remove - * @param hashIndex the index into the data structure - * @param previous the previous entry in the chain - */ - protected void removeEntry(HashEntry entry, int hashIndex, HashEntry previous) { - if (previous == null) { - data[hashIndex] = entry.next; - } else { - previous.next = entry.next; - } - } - - /** - * Kills an entry ready for the garbage collector. - *

- * This implementation prepares the HashEntry for garbage collection. - * Subclasses can override this to implement caching (override clear as well). - * - * @param entry the entry to destroy - */ - protected void destroyEntry(HashEntry entry) { - entry.next = null; - entry.key = null; - entry.value = null; - } - - //----------------------------------------------------------------------- - /** - * Checks the capacity of the map and enlarges it if necessary. - *

- * This implementation uses the threshold to check if the map needs enlarging - */ - protected void checkCapacity() { - if (size >= threshold) { - int newCapacity = data.length * 2; - if (newCapacity <= MAXIMUM_CAPACITY) { - ensureCapacity(newCapacity); - } - } - } - - /** - * Changes the size of the data structure to the capacity proposed. - * - * @param newCapacity the new capacity of the array (a power of two, less or equal to max) - */ - protected void ensureCapacity(int newCapacity) { - int oldCapacity = data.length; - if (newCapacity <= oldCapacity) { - return; - } - if (size == 0) { - threshold = calculateThreshold(newCapacity, loadFactor); - data = new HashEntry[newCapacity]; - } else { - HashEntry oldEntries[] = data; - HashEntry newEntries[] = new HashEntry[newCapacity]; - - modCount++; - for (int i = oldCapacity - 1; i >= 0; i--) { - HashEntry entry = oldEntries[i]; - if (entry != null) { - oldEntries[i] = null; // gc - do { - HashEntry next = entry.next; - int index = hashIndex(entry.hashCode, newCapacity); - entry.next = newEntries[index]; - newEntries[index] = entry; - entry = next; - } while (entry != null); - } - } - threshold = calculateThreshold(newCapacity, loadFactor); - data = newEntries; - } - } - - /** - * Calculates the new capacity of the map. - * This implementation normalizes the capacity to a power of two. - * - * @param proposedCapacity the proposed capacity - * @return the normalized new capacity - */ - protected int calculateNewCapacity(int proposedCapacity) { - int newCapacity = 1; - if (proposedCapacity > MAXIMUM_CAPACITY) { - newCapacity = MAXIMUM_CAPACITY; - } else { - while (newCapacity < proposedCapacity) { - newCapacity <<= 1; // multiply by two - } - if (newCapacity > MAXIMUM_CAPACITY) { - newCapacity = MAXIMUM_CAPACITY; - } - } - return newCapacity; - } - - /** - * Calculates the new threshold of the map, where it will be resized. - * This implementation uses the load factor. - * - * @param newCapacity the new capacity - * @param factor the load factor - * @return the new resize threshold - */ - protected int calculateThreshold(int newCapacity, float factor) { - return (int) (newCapacity * factor); - } - - //----------------------------------------------------------------------- - /** - * Gets the next field from a HashEntry. - * Used in subclasses that have no visibility of the field. - * - * @param entry the entry to query, must not be null - * @return the next field of the entry - * @throws NullPointerException if the entry is null - * @since Commons Collections 3.1 - */ - protected HashEntry entryNext(HashEntry entry) { - return entry.next; - } - - /** - * Gets the hashCode field from a HashEntry. - * Used in subclasses that have no visibility of the field. - * - * @param entry the entry to query, must not be null - * @return the hashCode field of the entry - * @throws NullPointerException if the entry is null - * @since Commons Collections 3.1 - */ - protected int entryHashCode(HashEntry entry) { - return entry.hashCode; - } - - /** - * Gets the key field from a HashEntry. - * Used in subclasses that have no visibility of the field. - * - * @param entry the entry to query, must not be null - * @return the key field of the entry - * @throws NullPointerException if the entry is null - * @since Commons Collections 3.1 - */ - protected K entryKey(HashEntry entry) { - return entry.key; - } - - /** - * Gets the value field from a HashEntry. - * Used in subclasses that have no visibility of the field. - * - * @param entry the entry to query, must not be null - * @return the value field of the entry - * @throws NullPointerException if the entry is null - * @since Commons Collections 3.1 - */ - protected V entryValue(HashEntry entry) { - return entry.value; - } - - //----------------------------------------------------------------------- - /** - * Gets an iterator over the map. - * Changes made to the iterator affect this map. - *

- * A MapIterator returns the keys in the map. It also provides convenient - * methods to get the key and value, and set the value. - * It avoids the need to create an entrySet/keySet/values object. - * It also avoids creating the Map.Entry object. - * - * @return the map iterator - */ - public MapIterator mapIterator() { - if (size == 0) { - return EmptyMapIterator.INSTANCE; - } - return new HashMapIterator(this); - } - - /** - * MapIterator implementation. - */ - protected static class HashMapIterator extends HashIterator implements MapIterator { - - protected HashMapIterator(AbstractHashedMap parent) { - super(parent); - } - - public K next() { - return super.nextEntry().getKey(); - } - - public K getKey() { - HashEntry current = currentEntry(); - if (current == null) { - throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID); - } - return current.getKey(); - } - - public V getValue() { - HashEntry current = currentEntry(); - if (current == null) { - throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID); - } - return current.getValue(); - } - - public V setValue(V value) { - HashEntry current = currentEntry(); - if (current == null) { - throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID); - } - return current.setValue(value); - } - } - - //----------------------------------------------------------------------- - /** - * Gets the entrySet view of the map. - * Changes made to the view affect this map. - * To simply iterate through the entries, use {@link #mapIterator()}. - * - * @return the entrySet view - */ - public Set> entrySet() { - if (entrySet == null) { - entrySet = new EntrySet(this); - } - return entrySet; - } - - /** - * Creates an entry set iterator. - * Subclasses can override this to return iterators with different properties. - * - * @return the entrySet iterator - */ - protected Iterator> createEntrySetIterator() { - if (size() == 0) { - return EmptyIterator.INSTANCE; - } - return new EntrySetIterator(this); - } - - /** - * EntrySet implementation. - */ - protected static class EntrySet extends AbstractSet> { - /** - * The parent map - */ - protected final AbstractHashedMap parent; - - protected EntrySet(AbstractHashedMap parent) { - super(); - this.parent = parent; - } - - public int size() { - return parent.size(); - } - - public void clear() { - parent.clear(); - } - - public boolean contains(Map.Entry entry) { - Map.Entry e = entry; - Entry match = parent.getEntry(e.getKey()); - return (match != null && match.equals(e)); - } - - public boolean remove(Object obj) { - if (obj instanceof Map.Entry == false) { - return false; - } - if (contains(obj) == false) { - return false; - } - Map.Entry entry = (Map.Entry) obj; - K key = entry.getKey(); - parent.remove(key); - return true; - } - - public Iterator> iterator() { - return parent.createEntrySetIterator(); - } - } - - /** - * EntrySet iterator. - */ - protected static class EntrySetIterator extends HashIterator implements Iterator> { - - protected EntrySetIterator(AbstractHashedMap parent) { - super(parent); - } - - public HashEntry next() { - return super.nextEntry(); - } - } - - //----------------------------------------------------------------------- - /** - * Gets the keySet view of the map. - * Changes made to the view affect this map. - * To simply iterate through the keys, use {@link #mapIterator()}. - * - * @return the keySet view - */ - public Set keySet() { - if (keySet == null) { - keySet = new KeySet(this); - } - return keySet; - } - - /** - * Creates a key set iterator. - * Subclasses can override this to return iterators with different properties. - * - * @return the keySet iterator - */ - protected Iterator createKeySetIterator() { - if (size() == 0) { - return EmptyIterator.INSTANCE; - } - return new KeySetIterator(this); - } - - /** - * KeySet implementation. - */ - protected static class KeySet extends AbstractSet { - /** - * The parent map - */ - protected final AbstractHashedMap parent; - - protected KeySet(AbstractHashedMap parent) { - super(); - this.parent = parent; - } - - public int size() { - return parent.size(); - } - - public void clear() { - parent.clear(); - } - - public boolean contains(Object key) { - return parent.containsKey(key); - } - - public boolean remove(Object key) { - boolean result = parent.containsKey(key); - parent.remove(key); - return result; - } - - public Iterator iterator() { - return parent.createKeySetIterator(); - } - } - - /** - * KeySet iterator. - */ - protected static class KeySetIterator extends HashIterator implements Iterator { - - protected KeySetIterator(AbstractHashedMap parent) { - super(parent); - } - - public K next() { - return super.nextEntry().getKey(); - } - } - - //----------------------------------------------------------------------- - /** - * Gets the values view of the map. - * Changes made to the view affect this map. - * To simply iterate through the values, use {@link #mapIterator()}. - * - * @return the values view - */ - public Collection values() { - if (values == null) { - values = new Values(this); - } - return values; - } - - /** - * Creates a values iterator. - * Subclasses can override this to return iterators with different properties. - * - * @return the values iterator - */ - protected Iterator createValuesIterator() { - if (size() == 0) { - return EmptyIterator.INSTANCE; - } - return new ValuesIterator(this); - } - - /** - * Values implementation. - */ - protected static class Values extends AbstractCollection { - /** - * The parent map - */ - protected final AbstractHashedMap parent; - - protected Values(AbstractHashedMap parent) { - super(); - this.parent = parent; - } - - public int size() { - return parent.size(); - } - - public void clear() { - parent.clear(); - } - - public boolean contains(Object value) { - return parent.containsValue(value); - } - - public Iterator iterator() { - return parent.createValuesIterator(); - } - } - - /** - * Values iterator. - */ - protected static class ValuesIterator extends HashIterator implements Iterator { - - protected ValuesIterator(AbstractHashedMap parent) { - super(parent); - } - - public V next() { - return super.nextEntry().getValue(); - } - } - - //----------------------------------------------------------------------- - /** - * HashEntry used to store the data. - *

- * If you subclass AbstractHashedMap but not HashEntry - * then you will not be able to access the protected fields. - * The entryXxx() methods on AbstractHashedMap exist - * to provide the necessary access. - */ - protected static class HashEntry implements Map.Entry, KeyValue { - /** - * The next entry in the hash chain - */ - protected HashEntry next; - /** - * The hash code of the key - */ - protected int hashCode; - /** - * The key - */ - private K key; - /** - * The value - */ - private V value; - - protected HashEntry(HashEntry next, int hashCode, K key, V value) { - super(); - this.next = next; - this.hashCode = hashCode; - this.key = key; - this.value = value; - } - - public K getKey() { - return key; - } - - public void setKey(K key) { - this.key = key; - } - - public V getValue() { - return value; - } - - public V setValue(V value) { - V old = this.value; - this.value = value; - return old; - } - - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof Map.Entry == false) { - return false; - } - Map.Entry other = (Map.Entry) obj; - return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue())); - } - - public int hashCode() { - return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); - } - - public String toString() { - return new StringBuilder().append(getKey()).append('=').append(getValue()).toString(); - } - } - - /** - * Base Iterator - */ - protected static abstract class HashIterator { - - /** - * The parent map - */ - protected final AbstractHashedMap parent; - /** - * The current index into the array of buckets - */ - protected int hashIndex; - /** - * The last returned entry - */ - protected HashEntry last; - /** - * The next entry - */ - protected HashEntry next; - /** - * The modification count expected - */ - protected int expectedModCount; - - protected HashIterator(AbstractHashedMap parent) { - super(); - this.parent = parent; - HashEntry[] data = parent.data; - int i = data.length; - HashEntry next = null; - while (i > 0 && next == null) { - next = data[--i]; - } - this.next = next; - this.hashIndex = i; - this.expectedModCount = parent.modCount; - } - - public boolean hasNext() { - return (next != null); - } - - protected HashEntry nextEntry() { - if (parent.modCount != expectedModCount) { - throw new ConcurrentModificationException(); - } - HashEntry newCurrent = next; - if (newCurrent == null) { - throw new NoSuchElementException(AbstractHashedMap.NO_NEXT_ENTRY); - } - HashEntry[] data = parent.data; - int i = hashIndex; - HashEntry n = newCurrent.next; - while (n == null && i > 0) { - n = data[--i]; - } - next = n; - hashIndex = i; - last = newCurrent; - return newCurrent; - } - - protected HashEntry currentEntry() { - return last; - } - - public void remove() { - if (last == null) { - throw new IllegalStateException(AbstractHashedMap.REMOVE_INVALID); - } - if (parent.modCount != expectedModCount) { - throw new ConcurrentModificationException(); - } - parent.remove(last.getKey()); - last = null; - expectedModCount = parent.modCount; - } - - public String toString() { - if (last != null) { - return "Iterator[" + last.getKey() + "=" + last.getValue() + "]"; - } else { - return "Iterator[]"; - } - } - } - - //----------------------------------------------------------------------- - /** - * Writes the map data to the stream. This method must be overridden if a - * subclass must be setup before put() is used. - *

- * Serialization is not one of the JDK's nicest topics. Normal serialization will - * initialise the superclass before the subclass. Sometimes however, this isn't - * what you want, as in this case the put() method on read can be - * affected by subclass state. - *

- * The solution adopted here is to serialize the state data of this class in - * this protected method. This method must be called by the - * writeObject() of the first serializable subclass. - *

- * Subclasses may override if they have a specific field that must be present - * on read before this implementation will work. Generally, the read determines - * what must be serialized here, if anything. - * - * @param out the output stream - */ - protected void doWriteObject(ObjectOutputStream out) throws IOException { - out.writeFloat(loadFactor); - out.writeInt(data.length); - out.writeInt(size); - for (MapIterator it = mapIterator(); it.hasNext();) { - out.writeObject(it.next()); - out.writeObject(it.getValue()); - } - } - - /** - * Reads the map data from the stream. This method must be overridden if a - * subclass must be setup before put() is used. - *

- * Serialization is not one of the JDK's nicest topics. Normal serialization will - * initialise the superclass before the subclass. Sometimes however, this isn't - * what you want, as in this case the put() method on read can be - * affected by subclass state. - *

- * The solution adopted here is to deserialize the state data of this class in - * this protected method. This method must be called by the - * readObject() of the first serializable subclass. - *

- * Subclasses may override if the subclass has a specific field that must be present - * before put() or calculateThreshold() will work correctly. - * - * @param in the input stream - */ - protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - loadFactor = in.readFloat(); - int capacity = in.readInt(); - int size = in.readInt(); - init(); - data = new HashEntry[capacity]; - for (int i = 0; i < size; i++) { - K key = (K) in.readObject(); - V value = (V) in.readObject(); - put(key, value); - } - threshold = calculateThreshold(data.length, loadFactor); - } - - //----------------------------------------------------------------------- - /** - * Clones the map without cloning the keys or values. - *

- * To implement clone(), a subclass must implement the - * Cloneable interface and make this method public. - * - * @return a shallow clone - */ - protected Object clone() { - try { - AbstractHashedMap cloned = (AbstractHashedMap) super.clone(); - cloned.data = new HashEntry[data.length]; - cloned.entrySet = null; - cloned.keySet = null; - cloned.values = null; - cloned.modCount = 0; - cloned.size = 0; - cloned.init(); - cloned.putAll(this); - return cloned; - - } catch (CloneNotSupportedException ex) { - return null; // should never happen - } - } - - /** - * Compares this map with another. - * - * @param obj the object to compare to - * @return true if equal - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof Map == false) { - return false; - } - Map map = (Map) obj; - if (map.size() != size()) { - return false; - } - MapIterator it = mapIterator(); - try { - while (it.hasNext()) { - Object key = it.next(); - Object value = it.getValue(); - if (value == null) { - if (map.get(key) != null || map.containsKey(key) == false) { - return false; - } - } else { - if (value.equals(map.get(key)) == false) { - return false; - } - } - } - } catch (ClassCastException ignored) { - return false; - } catch (NullPointerException ignored) { - return false; - } - return true; - } - - /** - * Gets the standard Map hashCode. - * - * @return the hash code defined in the Map interface - */ - public int hashCode() { - int total = 0; - Iterator it = createEntrySetIterator(); - while (it.hasNext()) { - total += it.next().hashCode(); - } - return total; - } - - /** - * Gets the map as a String. - * - * @return a string version of the map - */ - public String toString() { - if (size() == 0) { - return "{}"; - } - StringBuilder buf = new StringBuilder(32 * size()); - buf.append('{'); - - MapIterator it = mapIterator(); - boolean hasNext = it.hasNext(); - while (hasNext) { - Object key = it.next(); - Object value = it.getValue(); - buf.append(key == this ? "(this Map)" : key).append('=').append(value == this ? "(this Map)" : value); - - hasNext = it.hasNext(); - if (hasNext) { - buf.append(',').append(' '); - } - } - - buf.append('}'); - return buf.toString(); - } -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractKeyValue.java b/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractKeyValue.java deleted file mode 100644 index 8a7d5fdcc..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractKeyValue.java +++ /dev/null @@ -1,80 +0,0 @@ -/** - * - * Copyright 2003-2004 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. - */ -package org.jivesoftware.smack.util.collections; - - -/** - * Abstract pair class to assist with creating KeyValue and MapEntry implementations. - * - * @author James Strachan - * @author Michael A. Smith - * @author Neil O'Toole - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $ - * @since Commons Collections 3.0 - */ -public abstract class AbstractKeyValue implements KeyValue { - - /** - * The key - */ - protected K key; - /** - * The value - */ - protected V value; - - /** - * Constructs a new pair with the specified key and given value. - * - * @param key the key for the entry, may be null - * @param value the value for the entry, may be null - */ - protected AbstractKeyValue(K key, V value) { - super(); - this.key = key; - this.value = value; - } - - /** - * Gets the key from the pair. - * - * @return the key - */ - public K getKey() { - return key; - } - - /** - * Gets the value from the pair. - * - * @return the value - */ - public V getValue() { - return value; - } - - /** - * Gets a debugging String view of the pair. - * - * @return a String view of the entry - */ - public String toString() { - return new StringBuilder().append(getKey()).append('=').append(getValue()).toString(); - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractMapEntry.java b/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractMapEntry.java deleted file mode 100644 index 99c39593b..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractMapEntry.java +++ /dev/null @@ -1,89 +0,0 @@ -/** - * - * Copyright 2003-2004 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. - */ -package org.jivesoftware.smack.util.collections; - -import java.util.Map; - -/** - * Abstract Pair class to assist with creating correct Map Entry implementations. - * - * @author James Strachan - * @author Michael A. Smith - * @author Neil O'Toole - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $ - * @since Commons Collections 3.0 - */ -public abstract class AbstractMapEntry extends AbstractKeyValue implements Map.Entry { - - /** - * Constructs a new entry with the given key and given value. - * - * @param key the key for the entry, may be null - * @param value the value for the entry, may be null - */ - protected AbstractMapEntry(K key, V value) { - super(key, value); - } - - // Map.Entry interface - //------------------------------------------------------------------------- - /** - * Sets the value stored in this Map Entry. - *

- * This Map Entry is not connected to a Map, so only the local data is changed. - * - * @param value the new value - * @return the previous value - */ - public V setValue(V value) { - V answer = this.value; - this.value = value; - return answer; - } - - /** - * Compares this Map Entry with another Map Entry. - *

- * Implemented per API documentation of {@link java.util.Map.Entry#equals(Object)} - * - * @param obj the object to compare to - * @return true if equal key and value - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof Map.Entry == false) { - return false; - } - Map.Entry other = (Map.Entry) obj; - return (getKey() == null ? other.getKey() == null : getKey().equals(other.getKey())) && (getValue() == null ? other.getValue() == null : getValue().equals(other.getValue())); - } - - /** - * Gets a hashCode compatible with the equals method. - *

- * Implemented per API documentation of {@link java.util.Map.Entry#hashCode()} - * - * @return a suitable hash code - */ - public int hashCode() { - return (getKey() == null ? 0 : getKey().hashCode()) ^ (getValue() == null ? 0 : getValue().hashCode()); - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractReferenceMap.java b/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractReferenceMap.java deleted file mode 100644 index 0b51ab0a9..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/AbstractReferenceMap.java +++ /dev/null @@ -1,1026 +0,0 @@ -/** - * - * Copyright 2002-2004 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. - */ -// Converted, with some major refactors required. Not as memory-efficient as before, could use additional refactoring. -// Perhaps use four different types of HashEntry classes for max efficiency: -// normal HashEntry for HARD,HARD -// HardRefEntry for HARD,(SOFT|WEAK) -// RefHardEntry for (SOFT|WEAK),HARD -// RefRefEntry for (SOFT|WEAK),(SOFT|WEAK) -package org.jivesoftware.smack.util.collections; - -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.*; - -/** - * An abstract implementation of a hash-based map that allows the entries to - * be removed by the garbage collector. - *

- * This class implements all the features necessary for a subclass reference - * hash-based map. Key-value entries are stored in instances of the - * ReferenceEntry class which can be overridden and replaced. - * The iterators can similarly be replaced, without the need to replace the KeySet, - * EntrySet and Values view classes. - *

- * Overridable methods are provided to change the default hashing behaviour, and - * to change how entries are added to and removed from the map. Hopefully, all you - * need for unusual subclasses is here. - *

- * When you construct an AbstractReferenceMap, 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 Reference}. - *

- * 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 - * - * WeakHashMap. 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. - *

- * This {@link Map} implementation does not allow null elements. - * Attempting to add a null key or value to the map will raise a - * NullPointerException. - *

- * All the available iterators can be reset back to the start by casting to - * ResettableIterator and calling reset(). - *

- * This implementation is not synchronized. - * You can use {@link java.util.Collections#synchronizedMap} to - * provide synchronized access to a ReferenceMap. - * - * @author Paul Jack - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $ - * @see java.lang.ref.Reference - * @since Commons Collections 3.1 (extracted from ReferenceMap in 3.0) - */ -public abstract class AbstractReferenceMap extends AbstractHashedMap { - - /** - * Constant indicating that hard references should be used - */ - public static final int HARD = 0; - - /** - * Constant indicating that soft references should be used - */ - public static final int SOFT = 1; - - /** - * Constant indicating that weak references should be used - */ - public static final int WEAK = 2; - - /** - * The reference type for keys. Must be HARD, SOFT, WEAK. - * - * @serial - */ - protected int keyType; - - /** - * The reference type for values. Must be HARD, SOFT, WEAK. - * - * @serial - */ - protected int valueType; - - /** - * Should the value be automatically purged when the associated key has been collected? - */ - protected boolean purgeValues; - - /** - * ReferenceQueue used to eliminate stale mappings. - * See purge. - */ - private transient ReferenceQueue queue; - - //----------------------------------------------------------------------- - /** - * Constructor used during deserialization. - */ - protected AbstractReferenceMap() { - super(); - } - - /** - * Constructs a new empty map with the specified reference types, - * load factor and initial capacity. - * - * @param keyType the type of reference to use for keys; - * must be {@link #SOFT} or {@link #WEAK} - * @param valueType the type of reference to use for values; - * must be {@link #SOFT} or {@link #WEAK} - * @param capacity the initial capacity for the map - * @param loadFactor the load factor for the map - * @param purgeValues should the value be automatically purged when the - * key is garbage collected - */ - protected AbstractReferenceMap(int keyType, int valueType, int capacity, float loadFactor, boolean purgeValues) { - super(capacity, loadFactor); - verify("keyType", keyType); - verify("valueType", valueType); - this.keyType = keyType; - this.valueType = valueType; - this.purgeValues = purgeValues; - } - - /** - * Initialise this subclass during construction, cloning or deserialization. - */ - protected void init() { - queue = new ReferenceQueue(); - } - - //----------------------------------------------------------------------- - /** - * Checks the type int is a valid value. - * - * @param name the name for error messages - * @param type the type value to check - * @throws IllegalArgumentException if the value if invalid - */ - private static void verify(String name, int type) { - if ((type < HARD) || (type > WEAK)) { - throw new IllegalArgumentException(name + " must be HARD, SOFT, WEAK."); - } - } - - //----------------------------------------------------------------------- - /** - * Gets the size of the map. - * - * @return the size - */ - public int size() { - purgeBeforeRead(); - return super.size(); - } - - /** - * Checks whether the map is currently empty. - * - * @return true if the map is currently size zero - */ - public boolean isEmpty() { - purgeBeforeRead(); - return super.isEmpty(); - } - - /** - * Checks whether the map contains the specified key. - * - * @param key the key to search for - * @return true if the map contains the key - */ - public boolean containsKey(Object key) { - purgeBeforeRead(); - Entry entry = getEntry(key); - if (entry == null) { - return false; - } - return (entry.getValue() != null); - } - - /** - * Checks whether the map contains the specified value. - * - * @param value the value to search for - * @return true if the map contains the value - */ - public boolean containsValue(Object value) { - purgeBeforeRead(); - if (value == null) { - return false; - } - return super.containsValue(value); - } - - /** - * Gets the value mapped to the key specified. - * - * @param key the key - * @return the mapped value, null if no match - */ - public V get(Object key) { - purgeBeforeRead(); - Entry entry = getEntry(key); - if (entry == null) { - return null; - } - return entry.getValue(); - } - - - /** - * Puts a key-value mapping into this map. - * Neither the key nor the value may be null. - * - * @param key the key to add, must not be null - * @param value the value to add, must not be null - * @return the value previously mapped to this key, null if none - * @throws NullPointerException if either the key or value is null - */ - public V put(K key, V value) { - if (key == null) { - throw new NullPointerException("null keys not allowed"); - } - if (value == null) { - throw new NullPointerException("null values not allowed"); - } - - purgeBeforeWrite(); - return super.put(key, value); - } - - /** - * Removes the specified mapping from this map. - * - * @param key the mapping to remove - * @return the value mapped to the removed key, null if key not in map - */ - public V remove(Object key) { - if (key == null) { - return null; - } - purgeBeforeWrite(); - return super.remove(key); - } - - /** - * Clears this map. - */ - public void clear() { - super.clear(); - while (queue.poll() != null) { - } // drain the queue - } - - //----------------------------------------------------------------------- - /** - * Gets a MapIterator over the reference map. - * The iterator only returns valid key/value pairs. - * - * @return a map iterator - */ - public MapIterator mapIterator() { - return new ReferenceMapIterator(this); - } - - /** - * Returns a set view of this map's entries. - * An iterator returned entry is valid until next() is called again. - * The setValue() method on the toArray entries has no effect. - * - * @return a set view of this map's entries - */ - public Set> entrySet() { - if (entrySet == null) { - entrySet = new ReferenceEntrySet(this); - } - 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) { - keySet = new ReferenceKeySet(this); - } - return keySet; - } - - /** - * Returns a collection view of this map's values. - * - * @return a set view of this map's values - */ - public Collection values() { - if (values == null) { - values = new ReferenceValues(this); - } - return values; - } - - //----------------------------------------------------------------------- - /** - * Purges stale mappings from this map before read operations. - *

- * This implementation calls {@link #purge()} to maintain a consistent state. - */ - protected void purgeBeforeRead() { - purge(); - } - - /** - * Purges stale mappings from this map before write operations. - *

- * This implementation calls {@link #purge()} to maintain a consistent state. - */ - protected void purgeBeforeWrite() { - purge(); - } - - /** - * Purges stale mappings from this map. - *

- * 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. - */ - protected void purge() { - Reference ref = queue.poll(); - while (ref != null) { - purge(ref); - ref = queue.poll(); - } - } - - /** - * Purges the specified reference. - * - * @param ref the reference to purge - */ - protected 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(); - int index = hashIndex(hash, data.length); - HashEntry previous = null; - HashEntry entry = data[index]; - while (entry != null) { - if (((ReferenceEntry) entry).purge(ref)) { - if (previous == null) { - data[index] = entry.next; - } else { - previous.next = entry.next; - } - this.size--; - return; - } - previous = entry; - entry = entry.next; - } - - } - - //----------------------------------------------------------------------- - /** - * Gets the entry mapped to the key specified. - * - * @param key the key - * @return the entry, null if no match - */ - protected HashEntry getEntry(Object key) { - if (key == null) { - return null; - } else { - return super.getEntry(key); - } - } - - /** - * Gets the hash code for a MapEntry. - * Subclasses can override this, for example to use the identityHashCode. - * - * @param key the key to get a hash code for, may be null - * @param value the value to get a hash code for, may be null - * @return the hash code, as per the MapEntry specification - */ - protected int hashEntry(Object key, Object value) { - return (key == null ? 0 : key.hashCode()) ^ (value == null ? 0 : value.hashCode()); - } - - /** - * Compares two keys, in internal converted form, to see if they are equal. - *

- * This implementation converts the key from the entry to a real reference - * before comparison. - * - * @param key1 the first key to compare passed in from outside - * @param key2 the second key extracted from the entry via entry.key - * @return true if equal - */ - protected boolean isEqualKey(Object key1, Object key2) { - //if ((key1 == null) && (key2 != null) || (key1 != null) || (key2 == null)) { - // return false; - //} - // GenericsNote: Conversion from reference handled by getKey() which replaced all .key references - //key2 = (keyType > HARD ? ((Reference) key2).get() : key2); - return (key1 == key2 || key1.equals(key2)); - } - - /** - * Creates a ReferenceEntry instead of a HashEntry. - * - * @param next the next entry in sequence - * @param hashCode the hash code to use - * @param key the key to store - * @param value the value to store - * @return the newly created entry - */ - public HashEntry createEntry(HashEntry next, int hashCode, K key, V value) { - return new ReferenceEntry(this, (ReferenceEntry) next, hashCode, key, value); - } - - /** - * Creates an entry set iterator. - * - * @return the entrySet iterator - */ - protected Iterator> createEntrySetIterator() { - return new ReferenceEntrySetIterator(this); - } - - /** - * Creates an key set iterator. - * - * @return the keySet iterator - */ - protected Iterator createKeySetIterator() { - return new ReferenceKeySetIterator(this); - } - - /** - * Creates an values iterator. - * - * @return the values iterator - */ - protected Iterator createValuesIterator() { - return new ReferenceValuesIterator(this); - } - - //----------------------------------------------------------------------- - /** - * EntrySet implementation. - */ - static class ReferenceEntrySet extends EntrySet { - - protected ReferenceEntrySet(AbstractHashedMap parent) { - super(parent); - } - - public Object[] toArray() { - return toArray(new Object[0]); - } - - public T[] toArray(T[] arr) { - // special implementation to handle disappearing entries - ArrayList> list = new ArrayList>(); - Iterator> iterator = iterator(); - while (iterator.hasNext()) { - Map.Entry e = iterator.next(); - list.add(new DefaultMapEntry(e.getKey(), e.getValue())); - } - return list.toArray(arr); - } - } - - //----------------------------------------------------------------------- - /** - * KeySet implementation. - */ - static class ReferenceKeySet extends KeySet { - - protected ReferenceKeySet(AbstractHashedMap parent) { - super(parent); - } - - public Object[] toArray() { - return toArray(new Object[0]); - } - - public T[] toArray(T[] arr) { - // special implementation to handle disappearing keys - List list = new ArrayList(parent.size()); - for (Iterator it = iterator(); it.hasNext();) { - list.add(it.next()); - } - return list.toArray(arr); - } - } - - //----------------------------------------------------------------------- - /** - * Values implementation. - */ - static class ReferenceValues extends Values { - - protected ReferenceValues(AbstractHashedMap parent) { - super(parent); - } - - public Object[] toArray() { - return toArray(new Object[0]); - } - - public T[] toArray(T[] arr) { - // special implementation to handle disappearing values - List list = new ArrayList(parent.size()); - for (Iterator it = iterator(); it.hasNext();) { - list.add(it.next()); - } - return list.toArray(arr); - } - } - - //----------------------------------------------------------------------- - /** - * A MapEntry implementation for the map. - *

- * If getKey() or getValue() returns null, it means - * the mapping is stale and should be removed. - * - * @since Commons Collections 3.1 - */ - protected static class ReferenceEntry extends HashEntry { - /** - * The parent map - */ - protected final AbstractReferenceMap parent; - - protected Reference refKey; - protected Reference refValue; - - /** - * Creates a new entry object for the ReferenceMap. - * - * @param parent the parent map - * @param next the next entry in the hash bucket - * @param hashCode the hash code of the key - * @param key the key - * @param value the value - */ - public ReferenceEntry(AbstractReferenceMap parent, ReferenceEntry next, int hashCode, K key, V value) { - super(next, hashCode, null, null); - this.parent = parent; - if (parent.keyType != HARD) { - refKey = toReference(parent.keyType, key, hashCode); - } else { - this.setKey(key); - } - if (parent.valueType != HARD) { - refValue = toReference(parent.valueType, value, hashCode); // the key hashCode is passed in deliberately - } else { - this.setValue(value); - } - } - - /** - * Gets the key from the entry. - * This method dereferences weak and soft keys and thus may return null. - * - * @return the key, which may be null if it was garbage collected - */ - public K getKey() { - return (parent.keyType > HARD) ? refKey.get() : super.getKey(); - } - - /** - * Gets the value from the entry. - * This method dereferences weak and soft value and thus may return null. - * - * @return the value, which may be null if it was garbage collected - */ - public V getValue() { - return (parent.valueType > HARD) ? refValue.get() : super.getValue(); - } - - /** - * Sets the value of the entry. - * - * @param obj the object to store - * @return the previous value - */ - public V setValue(V obj) { - V old = getValue(); - if (parent.valueType > HARD) { - refValue.clear(); - refValue = toReference(parent.valueType, obj, hashCode); - } else { - super.setValue(obj); - } - return old; - } - - /** - * Compares this map entry to another. - *

- * This implementation uses isEqualKey and - * isEqualValue on the main map for comparison. - * - * @param obj the other map entry to compare to - * @return true if equal, false if not - */ - public boolean equals(Object obj) { - if (obj == this) { - return true; - } - if (obj instanceof Map.Entry == false) { - return false; - } - - Map.Entry entry = (Map.Entry) obj; - Object entryKey = entry.getKey(); // convert to hard reference - Object entryValue = entry.getValue(); // convert to hard reference - if ((entryKey == null) || (entryValue == null)) { - return false; - } - // compare using map methods, aiding identity subclass - // note that key is direct access and value is via method - return parent.isEqualKey(entryKey, getKey()) && parent.isEqualValue(entryValue, getValue()); - } - - /** - * Gets the hashcode of the entry using temporary hard references. - *

- * This implementation uses hashEntry on the main map. - * - * @return the hashcode of the entry - */ - public int hashCode() { - return parent.hashEntry(getKey(), getValue()); - } - - /** - * 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 key of the mapping; - * this number might be different from referent.hashCode() if - * the referent represents a value and not a key - */ - protected Reference toReference(int type, T referent, int hash) { - switch (type) { - case SOFT: - return new SoftRef(hash, referent, parent.queue); - case WEAK: - return new WeakRef(hash, referent, parent.queue); - default: - throw new Error("Attempt to create hard reference in ReferenceMap!"); - } - } - - /** - * Purges the specified reference - * - * @param ref the reference to purge - * @return true or false - */ - boolean purge(Reference ref) { - boolean r = (parent.keyType > HARD) && (refKey == ref); - r = r || ((parent.valueType > HARD) && (refValue == ref)); - if (r) { - if (parent.keyType > HARD) { - refKey.clear(); - } - if (parent.valueType > HARD) { - refValue.clear(); - } else if (parent.purgeValues) { - setValue(null); - } - } - return r; - } - - /** - * Gets the next entry in the bucket. - * - * @return the next entry in the bucket - */ - protected ReferenceEntry next() { - return (ReferenceEntry) next; - } - } - - //----------------------------------------------------------------------- - /** - * The EntrySet iterator. - */ - static class ReferenceIteratorBase { - /** - * The parent map - */ - final AbstractReferenceMap parent; - - // These fields keep track of where we are in the table. - int index; - ReferenceEntry entry; - ReferenceEntry 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. - K nextKey; - V nextValue; - K currentKey; - V currentValue; - - int expectedModCount; - - public ReferenceIteratorBase(AbstractReferenceMap parent) { - super(); - this.parent = parent; - index = (parent.size() != 0 ? parent.data.length : 0); - // have to do this here! size() invocation above - // may have altered the modCount. - expectedModCount = parent.modCount; - } - - public boolean hasNext() { - checkMod(); - while (nextNull()) { - ReferenceEntry e = entry; - int i = index; - while ((e == null) && (i > 0)) { - i--; - e = (ReferenceEntry) parent.data[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 (parent.modCount != expectedModCount) { - throw new ConcurrentModificationException(); - } - } - - private boolean nextNull() { - return (nextKey == null) || (nextValue == null); - } - - protected ReferenceEntry nextEntry() { - checkMod(); - if (nextNull() && !hasNext()) { - throw new NoSuchElementException(); - } - previous = entry; - entry = entry.next(); - currentKey = nextKey; - currentValue = nextValue; - nextKey = null; - nextValue = null; - return previous; - } - - protected ReferenceEntry currentEntry() { - checkMod(); - return previous; - } - - public ReferenceEntry superNext() { - return nextEntry(); - } - - public void remove() { - checkMod(); - if (previous == null) { - throw new IllegalStateException(); - } - parent.remove(currentKey); - previous = null; - currentKey = null; - currentValue = null; - expectedModCount = parent.modCount; - } - } - - /** - * The EntrySet iterator. - */ - static class ReferenceEntrySetIterator extends ReferenceIteratorBase implements Iterator> { - - public ReferenceEntrySetIterator(AbstractReferenceMap abstractReferenceMap) { - super(abstractReferenceMap); - } - - public ReferenceEntry next() { - return superNext(); - } - - } - - /** - * The keySet iterator. - */ - static class ReferenceKeySetIterator extends ReferenceIteratorBase implements Iterator { - - ReferenceKeySetIterator(AbstractReferenceMap parent) { - super(parent); - } - - public K next() { - return nextEntry().getKey(); - } - } - - /** - * The values iterator. - */ - static class ReferenceValuesIterator extends ReferenceIteratorBase implements Iterator { - - ReferenceValuesIterator(AbstractReferenceMap parent) { - super(parent); - } - - public V next() { - return nextEntry().getValue(); - } - } - - /** - * The MapIterator implementation. - */ - static class ReferenceMapIterator extends ReferenceIteratorBase implements MapIterator { - - protected ReferenceMapIterator(AbstractReferenceMap parent) { - super(parent); - } - - public K next() { - return nextEntry().getKey(); - } - - public K getKey() { - HashEntry current = currentEntry(); - if (current == null) { - throw new IllegalStateException(AbstractHashedMap.GETKEY_INVALID); - } - return current.getKey(); - } - - public V getValue() { - HashEntry current = currentEntry(); - if (current == null) { - throw new IllegalStateException(AbstractHashedMap.GETVALUE_INVALID); - } - return current.getValue(); - } - - public V setValue(V value) { - HashEntry current = currentEntry(); - if (current == null) { - throw new IllegalStateException(AbstractHashedMap.SETVALUE_INVALID); - } - return current.setValue(value); - } - } - - //----------------------------------------------------------------------- - // 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. - - /** - * A soft reference holder. - */ - static class SoftRef extends SoftReference { - /** - * the hashCode of the key (even if the reference points to a value) - */ - private int hash; - - public SoftRef(int hash, T r, ReferenceQueue q) { - super(r, q); - this.hash = hash; - } - - public int hashCode() { - return hash; - } - } - - /** - * A weak reference holder. - */ - static class WeakRef extends WeakReference { - /** - * the hashCode of the key (even if the reference points to a value) - */ - private int hash; - - public WeakRef(int hash, T r, ReferenceQueue q) { - super(r, q); - this.hash = hash; - } - - public int hashCode() { - return hash; - } - } - - //----------------------------------------------------------------------- - /** - * Replaces the superclass method to store the state of this class. - *

- * Serialization is not one of the JDK's nicest topics. Normal serialization will - * initialise the superclass before the subclass. Sometimes however, this isn't - * what you want, as in this case the put() method on read can be - * affected by subclass state. - *

- * The solution adopted here is to serialize the state data of this class in - * this protected method. This method must be called by the - * writeObject() of the first serializable subclass. - *

- * Subclasses may override if they have a specific field that must be present - * on read before this implementation will work. Generally, the read determines - * what must be serialized here, if anything. - * - * @param out the output stream - */ - protected void doWriteObject(ObjectOutputStream out) throws IOException { - out.writeInt(keyType); - out.writeInt(valueType); - out.writeBoolean(purgeValues); - out.writeFloat(loadFactor); - out.writeInt(data.length); - for (MapIterator it = mapIterator(); it.hasNext();) { - out.writeObject(it.next()); - out.writeObject(it.getValue()); - } - out.writeObject(null); // null terminate map - // do not call super.doWriteObject() as code there doesn't work for reference map - } - - /** - * Replaces the superclassm method to read the state of this class. - *

- * Serialization is not one of the JDK's nicest topics. Normal serialization will - * initialise the superclass before the subclass. Sometimes however, this isn't - * what you want, as in this case the put() method on read can be - * affected by subclass state. - *

- * The solution adopted here is to deserialize the state data of this class in - * this protected method. This method must be called by the - * readObject() of the first serializable subclass. - *

- * Subclasses may override if the subclass has a specific field that must be present - * before put() or calculateThreshold() will work correctly. - * - * @param in the input stream - */ - protected void doReadObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - this.keyType = in.readInt(); - this.valueType = in.readInt(); - this.purgeValues = in.readBoolean(); - this.loadFactor = in.readFloat(); - int capacity = in.readInt(); - init(); - data = new HashEntry[capacity]; - while (true) { - K key = (K) in.readObject(); - if (key == null) { - break; - } - V value = (V) in.readObject(); - put(key, value); - } - threshold = calculateThreshold(data.length, loadFactor); - // do not call super.doReadObject() as code there doesn't work for reference map - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/DefaultMapEntry.java b/core/src/main/java/org/jivesoftware/smack/util/collections/DefaultMapEntry.java deleted file mode 100644 index dbf5b4ee5..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/DefaultMapEntry.java +++ /dev/null @@ -1,65 +0,0 @@ -/** - * - * Copyright 2001-2004 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. - */ -package org.jivesoftware.smack.util.collections; - - -import java.util.Map; - -/** - * A restricted implementation of {@link java.util.Map.Entry} that prevents - * the MapEntry contract from being broken. - * - * @author James Strachan - * @author Michael A. Smith - * @author Neil O'Toole - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $ - * @since Commons Collections 3.0 - */ -public final class DefaultMapEntry extends AbstractMapEntry { - - /** - * Constructs a new entry with the specified key and given value. - * - * @param key the key for the entry, may be null - * @param value the value for the entry, may be null - */ - public DefaultMapEntry(final K key, final V value) { - super(key, value); - } - - /** - * Constructs a new entry from the specified KeyValue. - * - * @param pair the pair to copy, must not be null - * @throws NullPointerException if the entry is null - */ - public DefaultMapEntry(final KeyValue pair) { - super(pair.getKey(), pair.getValue()); - } - - /** - * Constructs a new entry from the specified MapEntry. - * - * @param entry the entry to copy, must not be null - * @throws NullPointerException if the entry is null - */ - public DefaultMapEntry(final Map.Entry entry) { - super(entry.getKey(), entry.getValue()); - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/EmptyIterator.java b/core/src/main/java/org/jivesoftware/smack/util/collections/EmptyIterator.java deleted file mode 100644 index bfe00f217..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/EmptyIterator.java +++ /dev/null @@ -1,58 +0,0 @@ -/** - * - * Copyright 2004 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. - */ -package org.jivesoftware.smack.util.collections; - -import java.util.Iterator; - -/** - * Provides an implementation of an empty iterator. - *

- * This class provides an implementation of an empty iterator. - * This class provides for binary compatability between Commons Collections - * 2.1.1 and 3.1 due to issues with IteratorUtils. - * - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $ - * @since Commons Collections 2.1.1 and 3.1 - */ -public class EmptyIterator extends AbstractEmptyIterator implements ResettableIterator { - - /** - * Singleton instance of the iterator. - * - * @since Commons Collections 3.1 - */ - public static final ResettableIterator RESETTABLE_INSTANCE = new EmptyIterator(); - /** - * Singleton instance of the iterator. - * - * @since Commons Collections 2.1.1 and 3.1 - */ - public static final Iterator INSTANCE = RESETTABLE_INSTANCE; - - public static Iterator getInstance() { - return INSTANCE; - } - - /** - * Constructor. - */ - protected EmptyIterator() { - super(); - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/EmptyMapIterator.java b/core/src/main/java/org/jivesoftware/smack/util/collections/EmptyMapIterator.java deleted file mode 100644 index 7e9ba9379..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/EmptyMapIterator.java +++ /dev/null @@ -1,42 +0,0 @@ -/** - * - * Copyright 2004 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. - */ -package org.jivesoftware.smack.util.collections; - -/** - * Provides an implementation of an empty map iterator. - * - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:24 $ - * @since Commons Collections 3.1 - */ -public class EmptyMapIterator extends AbstractEmptyIterator implements MapIterator, ResettableIterator { - - /** - * Singleton instance of the iterator. - * - * @since Commons Collections 3.1 - */ - public static final MapIterator INSTANCE = new EmptyMapIterator(); - - /** - * Constructor. - */ - protected EmptyMapIterator() { - super(); - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/IterableMap.java b/core/src/main/java/org/jivesoftware/smack/util/collections/IterableMap.java deleted file mode 100644 index 15d50c871..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/IterableMap.java +++ /dev/null @@ -1,61 +0,0 @@ -/** - * - * Copyright 2003-2004 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. - */ -package org.jivesoftware.smack.util.collections; - -import java.util.Map; - -/** - * Defines a map that can be iterated directly without needing to create an entry set. - *

- * A map iterator is an efficient way of iterating over maps. - * There is no need to access the entry set or cast to Map Entry objects. - *

- * IterableMap map = new HashedMap();
- * MapIterator it = map.mapIterator();
- * while (it.hasNext()) {
- *   Object key = it.next();
- *   Object value = it.getValue();
- *   it.setValue("newValue");
- * }
- * 
- * - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $ - * @since Commons Collections 3.0 - */ -public interface IterableMap extends Map { - - /** - * Obtains a MapIterator over the map. - *

- * A map iterator is an efficient way of iterating over maps. - * There is no need to access the entry set or cast to Map Entry objects. - *

-     * IterableMap map = new HashedMap();
-     * MapIterator it = map.mapIterator();
-     * while (it.hasNext()) {
-     *   Object key = it.next();
-     *   Object value = it.getValue();
-     *   it.setValue("newValue");
-     * }
-     * 
- * - * @return a map iterator - */ - MapIterator mapIterator(); - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/KeyValue.java b/core/src/main/java/org/jivesoftware/smack/util/collections/KeyValue.java deleted file mode 100644 index a51e26d05..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/KeyValue.java +++ /dev/null @@ -1,46 +0,0 @@ -/** - * - * Copyright 2003-2004 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. - */ -package org.jivesoftware.smack.util.collections; - -/** - * Defines a simple key value pair. - *

- * A Map Entry has considerable additional semantics over and above a simple - * key-value pair. This interface defines the minimum key value, with just the - * two get methods. - * - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $ - * @since Commons Collections 3.0 - */ -public interface KeyValue { - - /** - * Gets the key from the pair. - * - * @return the key - */ - K getKey(); - - /** - * Gets the value from the pair. - * - * @return the value - */ - V getValue(); - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/MapIterator.java b/core/src/main/java/org/jivesoftware/smack/util/collections/MapIterator.java deleted file mode 100644 index 37396b2b0..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/MapIterator.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * - * Copyright 2003-2004 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. - */ -package org.jivesoftware.smack.util.collections; - -import java.util.Iterator; - -/** - * Defines an iterator that operates over a Map. - *

- * This iterator is a special version designed for maps. It can be more - * efficient to use this rather than an entry set iterator where the option - * is available, and it is certainly more convenient. - *

- * A map that provides this interface may not hold the data internally using - * Map Entry objects, thus this interface can avoid lots of object creation. - *

- * In use, this iterator iterates through the keys in the map. After each call - * to next(), the getValue() method provides direct - * access to the value. The value can also be set using setValue(). - *

- * MapIterator it = map.mapIterator();
- * while (it.hasNext()) {
- *   Object key = it.next();
- *   Object value = it.getValue();
- *   it.setValue(newValue);
- * }
- * 
- * - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $ - * @since Commons Collections 3.0 - */ -public interface MapIterator extends Iterator { - - /** - * Checks to see if there are more entries still to be iterated. - * - * @return true if the iterator has more elements - */ - boolean hasNext(); - - /** - * Gets the next key from the Map. - * - * @return the next key in the iteration - * @throws java.util.NoSuchElementException - * if the iteration is finished - */ - K next(); - - //----------------------------------------------------------------------- - /** - * Gets the current key, which is the key returned by the last call - * to next(). - * - * @return the current key - * @throws IllegalStateException if next() has not yet been called - */ - K getKey(); - - /** - * Gets the current value, which is the value associated with the last key - * returned by next(). - * - * @return the current value - * @throws IllegalStateException if next() has not yet been called - */ - V getValue(); - - //----------------------------------------------------------------------- - /** - * Removes the last returned key from the underlying Map (optional operation). - *

- * This method can be called once per call to next(). - * - * @throws UnsupportedOperationException if remove is not supported by the map - * @throws IllegalStateException if next() has not yet been called - * @throws IllegalStateException if remove() has already been called - * since the last call to next() - */ - void remove(); - - /** - * Sets the value associated with the current key (optional operation). - * - * @param value the new value - * @return the previous value - * @throws UnsupportedOperationException if setValue is not supported by the map - * @throws IllegalStateException if next() has not yet been called - * @throws IllegalStateException if remove() has been called since the - * last call to next() - */ - V setValue(V value); - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/ReferenceMap.java b/core/src/main/java/org/jivesoftware/smack/util/collections/ReferenceMap.java deleted file mode 100644 index 4d8745c23..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/ReferenceMap.java +++ /dev/null @@ -1,161 +0,0 @@ -/** - * - * Copyright 2002-2004 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. - */ -package org.jivesoftware.smack.util.collections; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -/** - * A Map implementation that allows mappings to be - * removed by the garbage collector. - *

- * When you construct a ReferenceMap, 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}. - *

- * 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 - * - * WeakHashMap. 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. - *

- * This map is similar to ReferenceIdentityMap. - * It differs in that keys and values in this class are compared using equals(). - *

- * This {@link java.util.Map} implementation does not allow null elements. - * Attempting to add a null key or value to the map will raise a NullPointerException. - *

- * This implementation is not synchronized. - * You can use {@link java.util.Collections#synchronizedMap} to - * provide synchronized access to a ReferenceMap. - * Remember that synchronization will not stop the garbage collecter removing entries. - *

- * All the available iterators can be reset back to the start by casting to - * ResettableIterator and calling reset(). - *

- * NOTE: As from Commons Collections 3.1 this map extends AbstractReferenceMap - * (previously it extended AbstractMap). As a result, the implementation is now - * extensible and provides a MapIterator. - * - * @author Paul Jack - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:32 $ - * @see java.lang.ref.Reference - * @since Commons Collections 3.0 (previously in main package v2.1) - */ -public class ReferenceMap extends AbstractReferenceMap implements Serializable { - - /** - * Serialization version - */ - private static final long serialVersionUID = 1555089888138299607L; - - /** - * Constructs a new ReferenceMap that will - * use hard references to keys and soft references to values. - */ - public ReferenceMap() { - super(HARD, SOFT, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false); - } - - /** - * Constructs a new ReferenceMap 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) { - super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, false); - } - - /** - * Constructs a new ReferenceMap 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} - * @param purgeValues should the value be automatically purged when the - * key is garbage collected - */ - public ReferenceMap(int keyType, int valueType, boolean purgeValues) { - super(keyType, valueType, DEFAULT_CAPACITY, DEFAULT_LOAD_FACTOR, purgeValues); - } - - /** - * Constructs a new ReferenceMap 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 - */ - public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor) { - super(keyType, valueType, capacity, loadFactor, false); - } - - /** - * Constructs a new ReferenceMap 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 purgeValues should the value be automatically purged when the - * key is garbage collected - */ - public ReferenceMap(int keyType, int valueType, int capacity, float loadFactor, boolean purgeValues) { - super(keyType, valueType, capacity, loadFactor, purgeValues); - } - - //----------------------------------------------------------------------- - /** - * Write the map out using a custom routine. - */ - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - doWriteObject(out); - } - - /** - * Read the map in using a custom routine. - */ - private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - doReadObject(in); - } - -} diff --git a/core/src/main/java/org/jivesoftware/smack/util/collections/ResettableIterator.java b/core/src/main/java/org/jivesoftware/smack/util/collections/ResettableIterator.java deleted file mode 100644 index ac2af2d84..000000000 --- a/core/src/main/java/org/jivesoftware/smack/util/collections/ResettableIterator.java +++ /dev/null @@ -1,38 +0,0 @@ -/** - * - * Copyright 2003-2004 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. - */ -package org.jivesoftware.smack.util.collections; - -import java.util.Iterator; - -/** - * Defines an iterator that can be reset back to an initial state. - *

- * This interface allows an iterator to be repeatedly reused. - * - * @author Matt Hall, John Watkinson, Stephen Colebourne - * @version $Revision: 1.1 $ $Date: 2005/10/11 17:05:19 $ - * @since Commons Collections 3.0 - */ -public interface ResettableIterator extends Iterator { - - /** - * Resets the iterator back to the position at which the iterator - * was created. - */ - public void reset(); - -} diff --git a/extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java b/extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java index 76959f2cc..a90cf5b4a 100644 --- a/extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java +++ b/extensions/src/main/java/org/jivesoftware/smackx/chatstates/ChatStateManager.java @@ -26,20 +26,18 @@ import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.Manager; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.PacketInterceptor; -import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.filter.NotFilter; import org.jivesoftware.smack.filter.PacketExtensionFilter; import org.jivesoftware.smack.filter.PacketFilter; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smack.packet.Packet; import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smack.util.collections.ReferenceMap; import org.jivesoftware.smackx.chatstates.packet.ChatStateExtension; import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; /** * Handles chat state for all chats on a particular XMPPConnection. This class manages both the - * packet extensions and the disco response neccesary for compliance with + * packet extensions and the disco response necessary for compliance with * XEP-0085. * * NOTE: {@link org.jivesoftware.smackx.chatstates.ChatStateManager#getInstance(org.jivesoftware.smack.XMPPConnection)} @@ -80,8 +78,7 @@ public class ChatStateManager extends Manager { /** * Maps chat to last chat state. */ - private final Map chatStates = - new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.HARD); + private final Map chatStates = new WeakHashMap(); private ChatStateManager(XMPPConnection connection) { super(connection); @@ -100,11 +97,8 @@ public class ChatStateManager extends Manager { * * @param newState the new state of the chat * @param chat the chat. - * @throws org.jivesoftware.smack.XMPPException - * when there is an error sending the message - * packet. */ - public void setCurrentState(ChatState newState, Chat chat) throws XMPPException { + public void setCurrentState(ChatState newState, Chat chat) { if(chat == null || newState == null) { throw new IllegalArgumentException("Arguments cannot be null."); } @@ -133,7 +127,7 @@ public class ChatStateManager extends Manager { return connection().hashCode(); } - private boolean updateChatState(Chat chat, ChatState newState) { + private synchronized boolean updateChatState(Chat chat, ChatState newState) { ChatState lastChatState = chatStates.get(chat); if (lastChatState != newState) { chatStates.put(chat, newState);