diff --git a/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java b/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java index c0184cffa..fea1c812c 100644 --- a/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java +++ b/src/main/java/org/apache/commons/collections/map/PassiveExpiringMap.java @@ -55,523 +55,484 @@ import java.util.concurrent.TimeUnit; * synchronization. *

* - * @param - * the type of the keys in the map - * - * @param - * the type of the values in the map - * + * @param the type of the keys in the map + * @param the type of the values in the map * @since 4.0 * @version $Id: $ */ -public class PassiveExpiringMap extends AbstractMapDecorator - implements Serializable { +public class PassiveExpiringMap + extends AbstractMapDecorator + implements Serializable { - /** - * A {@link ExpirationPolicy} that returns a expiration time that is a - * constant about of time in the future from the current time. - * - * @param - * the type of the keys in the map - * @param - * the type of the values in the map - * - * @since 4.0 - * @version $Id: $ - */ - public static class ConstantTimeToLiveExpirationPolicy implements - ExpirationPolicy { + /** + * A {@link ExpirationPolicy} that returns a expiration time that is a + * constant about of time in the future from the current time. + * + * @param the type of the keys in the map + * @param the type of the values in the map + * @since 4.0 + * @version $Id: $ + */ + public static class ConstantTimeToLiveExpirationPolicy + implements ExpirationPolicy { - /** Serialization version */ - private static final long serialVersionUID = 1L; + /** Serialization version */ + private static final long serialVersionUID = 1L; - /** the constant time-to-live value measured in milliseconds. */ - private final long timeToLiveMillis; + /** the constant time-to-live value measured in milliseconds. */ + private final long timeToLiveMillis; - /** - * Default constructor. Constructs a policy using a negative - * time-to-live value that results in entries never expiring. - */ - public ConstantTimeToLiveExpirationPolicy() { - this(-1L); - } + /** + * Default constructor. Constructs a policy using a negative + * time-to-live value that results in entries never expiring. + */ + public ConstantTimeToLiveExpirationPolicy() { + this(-1L); + } - /** - * Construct a policy with the given time-to-live constant measured in - * milliseconds. A negative time-to-live value indicates entries never - * expire. A zero time-to-live value indicates entries expire (nearly) - * immediately. - * - * @param timeToLiveMillis - * the constant amount of time (in milliseconds) an entry is - * available before it expires. A negative value results in - * entries that NEVER expire. A zero value results in entries - * that ALWAYS expire. - */ - public ConstantTimeToLiveExpirationPolicy(long timeToLiveMillis) { - super(); - this.timeToLiveMillis = timeToLiveMillis; - } + /** + * Construct a policy with the given time-to-live constant measured in + * milliseconds. A negative time-to-live value indicates entries never + * expire. A zero time-to-live value indicates entries expire (nearly) + * immediately. + * + * @param timeToLiveMillis the constant amount of time (in milliseconds) + * an entry is available before it expires. A negative value + * results in entries that NEVER expire. A zero value results in + * entries that ALWAYS expire. + */ + public ConstantTimeToLiveExpirationPolicy(long timeToLiveMillis) { + super(); + this.timeToLiveMillis = timeToLiveMillis; + } - /** - * Construct a policy with the given time-to-live constant measured in - * the given time unit of measure. - * - * @param timeToLive - * the constant amount of time an entry is available before - * it expires. A negative value results in entries that NEVER - * expire. A zero value results in entries that ALWAYS - * expire. - * @param timeUnit - * the unit of time for the timeToLive - * parameter, must not be null. - * @throws IllegalArgumentException - * if the time unit is null. - */ - public ConstantTimeToLiveExpirationPolicy(long timeToLive, - TimeUnit timeUnit) { - this(validateAndConvertToMillis(timeToLive, TimeUnit.MILLISECONDS)); - } + /** + * Construct a policy with the given time-to-live constant measured in + * the given time unit of measure. + * + * @param timeToLive the constant amount of time an entry is available + * before it expires. A negative value results in entries that + * NEVER expire. A zero value results in entries that ALWAYS + * expire. + * @param timeUnit the unit of time for the timeToLive + * parameter, must not be null. + * @throws IllegalArgumentException if the time unit is null. + */ + public ConstantTimeToLiveExpirationPolicy(long timeToLive, + TimeUnit timeUnit) { + this(validateAndConvertToMillis(timeToLive, TimeUnit.MILLISECONDS)); + } - /** - * Determine the expiration time for the given key-value entry. - * - * @param key - * the key for the entry (ignored). - * @param value - * the value for the entry (ignored). - * @return if {@link #timeToLiveMillis} ≥ 0, an expiration time of - * {@link #timeToLiveMillis} + - * {@link System#currentTimeMillis()} is returned. Otherwise, -1 - * is returned indicating the entry never expires. - */ - public long expirationTime(K key, V value) { - if (timeToLiveMillis >= 0L) { - // avoid numerical overflow - long now = System.currentTimeMillis(); - if (now > Long.MAX_VALUE - timeToLiveMillis) { - // expiration would be greater than Long.MAX_VALUE - // never expire - return -1; - } + /** + * Determine the expiration time for the given key-value entry. + * + * @param key the key for the entry (ignored). + * @param value the value for the entry (ignored). + * @return if {@link #timeToLiveMillis} ≥ 0, an expiration time of + * {@link #timeToLiveMillis} + + * {@link System#currentTimeMillis()} is returned. Otherwise, -1 + * is returned indicating the entry never expires. + */ + public long expirationTime(K key, V value) { + if (timeToLiveMillis >= 0L) { + // avoid numerical overflow + long now = System.currentTimeMillis(); + if (now > Long.MAX_VALUE - timeToLiveMillis) { + // expiration would be greater than Long.MAX_VALUE + // never expire + return -1; + } - // timeToLiveMillis in the future - return now + timeToLiveMillis; - } - - // never expire - return -1L; - } - } + // timeToLiveMillis in the future + return now + timeToLiveMillis; + } - /** - * A policy to determine the expiration time for key-value entries. - * - * @param - * the key object type. - * @param - * the value object type - * - * @since 4.0 - * @version $Id: $ - */ - public static interface ExpirationPolicy extends Serializable { - /** - * Determine the expiration time for the given key-value entry. - * - * @param key - * the key for the entry. - * @param value - * the value for the entry. - * @return the expiration time value measured in milliseconds. A - * negative return value indicates the entry never expires. - */ - long expirationTime(K key, V value); - } + // never expire + return -1L; + } + } - /** Serialization version */ - private static final long serialVersionUID = 1L; + /** + * A policy to determine the expiration time for key-value entries. + * + * @param the key object type. + * @param the value object type + * @since 4.0 + * @version $Id: $ + */ + public static interface ExpirationPolicy + extends Serializable { - /** - * First validate the input parameters. If the parameters are valid, convert - * the given time measured in the given units to the same time measured in - * milliseconds. If the parameters are invalid, an - * {@link IllegalArgumentException} is thrown. - * - * @param timeToLive - * the constant amount of time an entry is available before it - * expires. A negative value results in entries that NEVER - * expire. A zero value results in entries that ALWAYS expire. - * @param timeUnit - * the unit of time for the timeToLive parameter, - * must not be null. - * @throws IllegalArgumentException - * if the time unit is null. - */ - private static long validateAndConvertToMillis(long timeToLive, - TimeUnit timeUnit) { - if (timeUnit == null) { - throw new IllegalArgumentException("Time unit must not be null"); - } - return timeUnit.convert(timeToLive, TimeUnit.MILLISECONDS); - } + /** + * Determine the expiration time for the given key-value entry. + * + * @param key the key for the entry. + * @param value the value for the entry. + * @return the expiration time value measured in milliseconds. A + * negative return value indicates the entry never expires. + */ + long expirationTime(K key, V value); + } - /** map used to manage expiration times for the actual map entries. */ - private final Map expirationMap = new HashMap(); + /** Serialization version */ + private static final long serialVersionUID = 1L; - /** the policy used to determine time-to-live values for map entries. */ - private final ExpirationPolicy expiringPolicy; + /** + * First validate the input parameters. If the parameters are valid, convert + * the given time measured in the given units to the same time measured in + * milliseconds. If the parameters are invalid, an + * {@link IllegalArgumentException} is thrown. + * + * @param timeToLive the constant amount of time an entry is available + * before it expires. A negative value results in entries that NEVER + * expire. A zero value results in entries that ALWAYS expire. + * @param timeUnit the unit of time for the timeToLive + * parameter, must not be null. + * @throws IllegalArgumentException if the time unit is null. + */ + private static long validateAndConvertToMillis(long timeToLive, + TimeUnit timeUnit) { + if (timeUnit == null) { + throw new IllegalArgumentException("Time unit must not be null"); + } + return timeUnit.convert(timeToLive, TimeUnit.MILLISECONDS); + } - /** - * Default constructor. Constructs a map decorator that results in entries - * NEVER expiring. - */ - public PassiveExpiringMap() { - this(-1L); - } + /** map used to manage expiration times for the actual map entries. */ + private final Map expirationMap = new HashMap(); - /** - * Construct a map decorator using the given expiration policy to determine - * expiration times. - * - * @param expiringPolicy - * the policy used to determine expiration times of entries as - * they are added. - */ - public PassiveExpiringMap(ExpirationPolicy expiringPolicy) { - this(expiringPolicy, new HashMap()); - } + /** the policy used to determine time-to-live values for map entries. */ + private final ExpirationPolicy expiringPolicy; - /** - * Construct a map decorator that decorates the given map and uses the given - * expiration policy to determine expiration times. If there are any - * elements already in the map being decorated, they will NEVER expire - * unless they are replaced. - * - * @param expiringPolicy - * the policy used to determine expiration times of entries as - * they are added. - * @param map - * the map to decorate, must not be null. - * @throws IllegalArgumentException - * if the map is null. - */ - public PassiveExpiringMap(ExpirationPolicy expiringPolicy, - Map map) { - super(map); - if (expiringPolicy == null) { - throw new IllegalArgumentException("Policy must not be null."); - } - this.expiringPolicy = expiringPolicy; - } + /** + * Default constructor. Constructs a map decorator that results in entries + * NEVER expiring. + */ + public PassiveExpiringMap() { + this(-1L); + } - /** - * Construct a map decorator that decorates the given map using the given - * time-to-live value measured in milliseconds to create and use a - * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. - * - * @param timeToLiveMillis - * the constant amount of time (in milliseconds) an entry is - * available before it expires. A negative value results in - * entries that NEVER expire. A zero value results in entries - * that ALWAYS expire. - */ - public PassiveExpiringMap(long timeToLiveMillis) { - this(new ConstantTimeToLiveExpirationPolicy(timeToLiveMillis), - new HashMap()); - } + /** + * Construct a map decorator using the given expiration policy to determine + * expiration times. + * + * @param expiringPolicy the policy used to determine expiration times of + * entries as they are added. + */ + public PassiveExpiringMap(ExpirationPolicy expiringPolicy) { + this(expiringPolicy, new HashMap()); + } - /** - * Construct a map decorator using the given time-to-live value measured in - * milliseconds to create and use a - * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. If there - * are any elements already in the map being decorated, they will NEVER - * expire unless they are replaced. - * - * @param timeToLiveMillis - * the constant amount of time (in milliseconds) an entry is - * available before it expires. A negative value results in - * entries that NEVER expire. A zero value results in entries - * that ALWAYS expire. - * @param map - * the map to decorate, must not be null. - * @throws IllegalArgumentException - * if the map is null. - */ - public PassiveExpiringMap(long timeToLiveMillis, Map map) { - this(new ConstantTimeToLiveExpirationPolicy(timeToLiveMillis), - map); - } + /** + * Construct a map decorator that decorates the given map and uses the given + * expiration policy to determine expiration times. If there are any + * elements already in the map being decorated, they will NEVER expire + * unless they are replaced. + * + * @param expiringPolicy the policy used to determine expiration times of + * entries as they are added. + * @param map the map to decorate, must not be null. + * @throws IllegalArgumentException if the map is null. + */ + public PassiveExpiringMap(ExpirationPolicy expiringPolicy, + Map map) { + super(map); + if (expiringPolicy == null) { + throw new IllegalArgumentException("Policy must not be null."); + } + this.expiringPolicy = expiringPolicy; + } - /** - * Construct a map decorator using the given time-to-live value measured in - * the given time units of measure to create and use a - * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. - * - * @param timeToLive - * the constant amount of time an entry is available before it - * expires. A negative value results in entries that NEVER - * expire. A zero value results in entries that ALWAYS expire. - * @param timeUnit - * the unit of time for the timeToLive parameter, - * must not be null. - * @throws IllegalArgumentException - * if the time unit is null. - */ - public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit) { - this(validateAndConvertToMillis(timeToLive, timeUnit)); - } + /** + * Construct a map decorator that decorates the given map using the given + * time-to-live value measured in milliseconds to create and use a + * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. + * + * @param timeToLiveMillis the constant amount of time (in milliseconds) an + * entry is available before it expires. A negative value results in + * entries that NEVER expire. A zero value results in entries that + * ALWAYS expire. + */ + public PassiveExpiringMap(long timeToLiveMillis) { + this(new ConstantTimeToLiveExpirationPolicy(timeToLiveMillis), + new HashMap()); + } - /** - * Construct a map decorator that decorates the given map using the given - * time-to-live value measured in the given time units of measure to create - * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. This policy - * is used to determine expiration times. If there are any elements already - * in the map being decorated, they will NEVER expire unless they are - * replaced. - * - * @param timeToLive - * the constant amount of time an entry is available before it - * expires. A negative value results in entries that NEVER - * expire. A zero value results in entries that ALWAYS expire. - * @param timeUnit - * the unit of time for the timeToLive parameter, - * must not be null. - * @throws IllegalArgumentException - * if the time unit is null. - * @param map - * the map to decorate, must not be null. - * @throws IllegalArgumentException - * if the map is null. - */ - public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit, Map map) { - this(validateAndConvertToMillis(timeToLive, timeUnit), map); - } + /** + * Construct a map decorator using the given time-to-live value measured in + * milliseconds to create and use a + * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. If there + * are any elements already in the map being decorated, they will NEVER + * expire unless they are replaced. + * + * @param timeToLiveMillis the constant amount of time (in milliseconds) an + * entry is available before it expires. A negative value results in + * entries that NEVER expire. A zero value results in entries that + * ALWAYS expire. + * @param map the map to decorate, must not be null. + * @throws IllegalArgumentException if the map is null. + */ + public PassiveExpiringMap(long timeToLiveMillis, Map map) { + this(new ConstantTimeToLiveExpirationPolicy(timeToLiveMillis), + map); + } - /** - * Constructs a map decorator that decorates the given map and results in - * entries NEVER expiring. If there are any elements already in the map - * being decorated, they also will NEVER expire. - * - * @param map - * the map to decorate, must not be null. - * @throws IllegalArgumentException - * if the map is null. - */ - public PassiveExpiringMap(Map map) { - this(-1L, map); - } + /** + * Construct a map decorator using the given time-to-live value measured in + * the given time units of measure to create and use a + * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. + * + * @param timeToLive the constant amount of time an entry is available + * before it expires. A negative value results in entries that NEVER + * expire. A zero value results in entries that ALWAYS expire. + * @param timeUnit the unit of time for the timeToLive + * parameter, must not be null. + * @throws IllegalArgumentException if the time unit is null. + */ + public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit) { + this(validateAndConvertToMillis(timeToLive, timeUnit)); + } - /** - * Normal {@link Map#clear()} behavior with the addition of clearing all - * expiration entries as well. - */ - @Override - public void clear() { - super.clear(); - expirationMap.clear(); - } + /** + * Construct a map decorator that decorates the given map using the given + * time-to-live value measured in the given time units of measure to create + * {@link ConstantTimeToLiveExpirationPolicy} expiration policy. This policy + * is used to determine expiration times. If there are any elements already + * in the map being decorated, they will NEVER expire unless they are + * replaced. + * + * @param timeToLive the constant amount of time an entry is available + * before it expires. A negative value results in entries that NEVER + * expire. A zero value results in entries that ALWAYS expire. + * @param timeUnit the unit of time for the timeToLive + * parameter, must not be null. + * @throws IllegalArgumentException if the time unit is null. + * @param map the map to decorate, must not be null. + * @throws IllegalArgumentException if the map is null. + */ + public PassiveExpiringMap(long timeToLive, TimeUnit timeUnit, Map map) { + this(validateAndConvertToMillis(timeToLive, timeUnit), map); + } - /** - * All expired entries are removed from the map prior to determining the - * contains result. - */ - @Override - public boolean containsKey(Object key) { - removeIfExpired(key, now()); - return super.containsKey(key); - } + /** + * Constructs a map decorator that decorates the given map and results in + * entries NEVER expiring. If there are any elements already in the map + * being decorated, they also will NEVER expire. + * + * @param map the map to decorate, must not be null. + * @throws IllegalArgumentException if the map is null. + */ + public PassiveExpiringMap(Map map) { + this(-1L, map); + } - /** - * All expired entries are removed from the map prior to determining the - * contains result. - */ - @Override - public boolean containsValue(Object value) { - removeAllExpired(now()); - return super.containsValue(value); - } + /** + * Normal {@link Map#clear()} behavior with the addition of clearing all + * expiration entries as well. + */ + @Override + public void clear() { + super.clear(); + expirationMap.clear(); + } - /** - * All expired entries are removed from the map prior to returning the entry - * set. - */ - @Override - public Set> entrySet() { - removeAllExpired(now()); - return super.entrySet(); - } + /** + * All expired entries are removed from the map prior to determining the + * contains result. + */ + @Override + public boolean containsKey(Object key) { + removeIfExpired(key, now()); + return super.containsKey(key); + } - /** - * All expired entries are removed from the map prior to returning the entry - * value. - */ - @Override - public V get(Object key) { - removeIfExpired(key, now()); - return super.get(key); - } + /** + * All expired entries are removed from the map prior to determining the + * contains result. + */ + @Override + public boolean containsValue(Object value) { + removeAllExpired(now()); + return super.containsValue(value); + } - /** - * All expired entries are removed from the map prior to determining if it - * is empty. - */ - @Override - public boolean isEmpty() { - removeAllExpired(now()); - return super.isEmpty(); - } + /** + * All expired entries are removed from the map prior to returning the entry + * set. + */ + @Override + public Set> entrySet() { + removeAllExpired(now()); + return super.entrySet(); + } - /** - * Determines if the given expiration time is less than now - * - * @param now - * the time in milliseconds used to compare against the - * expiration time. - * @param expirationTimeObject - * the expiration time value retrieved from - * {@link #expirationMap}, can be null. - * @return true if expirationTimeObject is ≥ 0 - * and expirationTimeObject < now. - * false otherwise. - */ - private boolean isExpired(long now, Long expirationTimeObject) { - if (expirationTimeObject != null) { - long expirationTime = expirationTimeObject.longValue(); - return (expirationTime >= 0 && now >= expirationTime); - } - return false; - } + /** + * All expired entries are removed from the map prior to returning the entry + * value. + */ + @Override + public V get(Object key) { + removeIfExpired(key, now()); + return super.get(key); + } - /** - * All expired entries are removed from the map prior to returning the key - * set. - */ - @Override - public Set keySet() { - removeAllExpired(now()); - return super.keySet(); - } + /** + * All expired entries are removed from the map prior to determining if it + * is empty. + */ + @Override + public boolean isEmpty() { + removeAllExpired(now()); + return super.isEmpty(); + } - /** - * The current time in milliseconds. - */ - private long now() { - return System.currentTimeMillis(); - } + /** + * Determines if the given expiration time is less than now + * + * @param now the time in milliseconds used to compare against the + * expiration time. + * @param expirationTimeObject the expiration time value retrieved from + * {@link #expirationMap}, can be null. + * @return true if expirationTimeObject is ≥ 0 + * and expirationTimeObject < now. + * false otherwise. + */ + private boolean isExpired(long now, Long expirationTimeObject) { + if (expirationTimeObject != null) { + long expirationTime = expirationTimeObject.longValue(); + return (expirationTime >= 0 && now >= expirationTime); + } + return false; + } - @Override - public V put(K key, V value) { - return put(key, value, now()); - } + /** + * All expired entries are removed from the map prior to returning the key + * set. + */ + @Override + public Set keySet() { + removeAllExpired(now()); + return super.keySet(); + } - /** - * Add the given key-value pair to this map as well as recording the entry's - * expiration time based on the current time in milliseconds, - * now and this map's {@link #expiringPolicy}. - */ - private V put(K key, V value, long now) { - // record expiration time of new entry - long expirationTime = expiringPolicy.expirationTime(key, value); - expirationMap.put(key, Long.valueOf(expirationTime)); + /** + * The current time in milliseconds. + */ + private long now() { + return System.currentTimeMillis(); + } - return super.put(key, value); - } + @Override + public V put(K key, V value) { + return put(key, value, now()); + } - @Override - public void putAll(Map mapToCopy) { - for (Map.Entry entry : mapToCopy.entrySet()) { - put(entry.getKey(), entry.getValue()); - } - } + /** + * Add the given key-value pair to this map as well as recording the entry's + * expiration time based on the current time in milliseconds, + * now and this map's {@link #expiringPolicy}. + */ + private V put(K key, V value, long now) { + // record expiration time of new entry + long expirationTime = expiringPolicy.expirationTime(key, value); + expirationMap.put(key, Long.valueOf(expirationTime)); - /** - * Normal {@link Map#remove(Object)} behavior with the addition of removing - * any expiration entry as well. - */ - @Override - public V remove(Object key) { - expirationMap.remove(key); - return super.remove(key); - } + return super.put(key, value); + } - /** - * Removes all entries in the map whose expiration time is less than - * now. The exceptions are entries with negative expiration - * times; those entries are never removed. - * - * @see #isExpired(long, Long) - */ - private void removeAllExpired(long now) { - Iterator> iter = expirationMap.entrySet() - .iterator(); - while (iter.hasNext()) { - Map.Entry expirationEntry = iter.next(); - if (isExpired(now, expirationEntry.getValue())) { - // remove entry from collection - super.remove(expirationEntry.getKey()); - // remove entry from expiration map - iter.remove(); - } - } - } + @Override + public void putAll(Map mapToCopy) { + for (Map.Entry entry : mapToCopy.entrySet()) { + put(entry.getKey(), entry.getValue()); + } + } - /** - * Removes the entry with the given key if the entry's expiration time is - * less than now. If the entry has a negative expiration time, - * the entry is never removed. - */ - private void removeIfExpired(Object key, long now) { - Long expirationTimeObject = expirationMap.get(key); - if (isExpired(now, expirationTimeObject)) { - remove(key); - } - } + /** + * Normal {@link Map#remove(Object)} behavior with the addition of removing + * any expiration entry as well. + */ + @Override + public V remove(Object key) { + expirationMap.remove(key); + return super.remove(key); + } - /** - * All expired entries are removed from the map prior to returning the size. - */ - @Override - public int size() { - removeAllExpired(now()); - return super.size(); - } + /** + * Removes all entries in the map whose expiration time is less than + * now. The exceptions are entries with negative expiration + * times; those entries are never removed. + * + * @see #isExpired(long, Long) + */ + private void removeAllExpired(long now) { + Iterator> iter = expirationMap.entrySet() + .iterator(); + while (iter.hasNext()) { + Map.Entry expirationEntry = iter.next(); + if (isExpired(now, expirationEntry.getValue())) { + // remove entry from collection + super.remove(expirationEntry.getKey()); + // remove entry from expiration map + iter.remove(); + } + } + } - /** - * Read the map in using a custom routine. - * - * @param in - * the input stream - * @throws IOException - * @throws ClassNotFoundException - */ - @SuppressWarnings("unchecked") - // (1) should only fail if input stream is incorrect - private void readObject(ObjectInputStream in) throws IOException, - ClassNotFoundException { - in.defaultReadObject(); - map = (Map) in.readObject(); // (1) - } + /** + * Removes the entry with the given key if the entry's expiration time is + * less than now. If the entry has a negative expiration time, + * the entry is never removed. + */ + private void removeIfExpired(Object key, long now) { + Long expirationTimeObject = expirationMap.get(key); + if (isExpired(now, expirationTimeObject)) { + remove(key); + } + } - /** - * Write the map out using a custom routine. - * - * @param out - * the output stream - * @throws IOException - */ - private void writeObject(ObjectOutputStream out) throws IOException { - out.defaultWriteObject(); - out.writeObject(map); - } + /** + * All expired entries are removed from the map prior to returning the size. + */ + @Override + public int size() { + removeAllExpired(now()); + return super.size(); + } - /** - * All expired entries are removed from the map prior to returning the value - * collection. - */ - @Override - public Collection values() { - removeAllExpired(now()); - return super.values(); - } + /** + * Read the map in using a custom routine. + * + * @param in the input stream + * @throws IOException + * @throws ClassNotFoundException + */ + @SuppressWarnings("unchecked") + // (1) should only fail if input stream is incorrect + private void readObject(ObjectInputStream in) + throws IOException, ClassNotFoundException { + in.defaultReadObject(); + map = (Map) in.readObject(); // (1) + } + + /** + * Write the map out using a custom routine. + * + * @param out the output stream + * @throws IOException + */ + private void writeObject(ObjectOutputStream out) + throws IOException { + out.defaultWriteObject(); + out.writeObject(map); + } + + /** + * All expired entries are removed from the map prior to returning the value + * collection. + */ + @Override + public Collection values() { + removeAllExpired(now()); + return super.values(); + } } diff --git a/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java b/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java index 97462d809..2817ca542 100644 --- a/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java +++ b/src/test/java/org/apache/commons/collections/map/TestPassiveExpiringMap.java @@ -9,199 +9,201 @@ import junit.framework.Test; import org.apache.commons.collections.BulkTest; import org.apache.commons.collections.map.PassiveExpiringMap.ExpirationPolicy; -public class TestPassiveExpiringMap extends AbstractTestMap { +public class TestPassiveExpiringMap + extends AbstractTestMap { - private static class TestExpirationPolicy implements - ExpirationPolicy { + private static class TestExpirationPolicy + implements ExpirationPolicy { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public long expirationTime(Integer key, String value) { - // odd keys expire immediately, even keys never expire - if (key == null) { - return 0; - } + public long expirationTime(Integer key, String value) { + // odd keys expire immediately, even keys never expire + if (key == null) { + return 0; + } - if (key.intValue() % 2 == 0) { - return -1; - } + if (key.intValue() % 2 == 0) { + return -1; + } - return 0; - } - } + return 0; + } + } - public static Test suite() { - return BulkTest.makeSuite(TestPassiveExpiringMap.class); - } + public static Test suite() { + return BulkTest.makeSuite(TestPassiveExpiringMap.class); + } - public TestPassiveExpiringMap(String testName) { - super(testName); - } + public TestPassiveExpiringMap(String testName) { + super(testName); + } - // public void testCreate() throws Exception { - // writeExternalFormToDisk((java.io.Serializable) makeObject(), - // "PassiveExpiringMap.emptyCollection.version4.obj"); - // - // writeExternalFormToDisk((java.io.Serializable) makeFullMap(), - // "PassiveExpiringMap.fullCollection.version4.obj"); - // } + // public void testCreate() throws Exception { + // writeExternalFormToDisk((java.io.Serializable) makeObject(), + // "PassiveExpiringMap.emptyCollection.version4.obj"); + // + // writeExternalFormToDisk((java.io.Serializable) makeFullMap(), + // "PassiveExpiringMap.fullCollection.version4.obj"); + // } - @Override - public String getCompatibilityVersion() { - return "4"; - } + @Override + public String getCompatibilityVersion() { + return "4"; + } - private Map makeDecoratedTestMap() { - Map m = new HashMap(); - m.put(Integer.valueOf(1), "one"); - m.put(Integer.valueOf(2), "two"); - m.put(Integer.valueOf(3), "three"); - m.put(Integer.valueOf(4), "four"); - m.put(Integer.valueOf(5), "five"); - m.put(Integer.valueOf(6), "six"); - return new PassiveExpiringMap( - new TestExpirationPolicy(), m); - } + private Map makeDecoratedTestMap() { + Map m = new HashMap(); + m.put(Integer.valueOf(1), "one"); + m.put(Integer.valueOf(2), "two"); + m.put(Integer.valueOf(3), "three"); + m.put(Integer.valueOf(4), "four"); + m.put(Integer.valueOf(5), "five"); + m.put(Integer.valueOf(6), "six"); + return new PassiveExpiringMap( + new TestExpirationPolicy(), + m); + } - @Override - public Map makeObject() { - return new PassiveExpiringMap(); - } + @Override + public Map makeObject() { + return new PassiveExpiringMap(); + } - private Map makeTestMap() { - Map m = new PassiveExpiringMap( - new TestExpirationPolicy()); - m.put(Integer.valueOf(1), "one"); - m.put(Integer.valueOf(2), "two"); - m.put(Integer.valueOf(3), "three"); - m.put(Integer.valueOf(4), "four"); - m.put(Integer.valueOf(5), "five"); - m.put(Integer.valueOf(6), "six"); - return m; - } + private Map makeTestMap() { + Map m = new PassiveExpiringMap( + new TestExpirationPolicy()); + m.put(Integer.valueOf(1), "one"); + m.put(Integer.valueOf(2), "two"); + m.put(Integer.valueOf(3), "three"); + m.put(Integer.valueOf(4), "four"); + m.put(Integer.valueOf(5), "five"); + m.put(Integer.valueOf(6), "six"); + return m; + } - public void testConstructors() { - try { - Map map = null; - new PassiveExpiringMap(map); - fail("constructor - exception should have been thrown."); - } catch (IllegalArgumentException ex) { - // success - } + public void testConstructors() { + try { + Map map = null; + new PassiveExpiringMap(map); + fail("constructor - exception should have been thrown."); + } catch (IllegalArgumentException ex) { + // success + } - try { - ExpirationPolicy policy = null; - new PassiveExpiringMap(policy); - fail("constructor - exception should have been thrown."); - } catch (IllegalArgumentException ex) { - // success - } + try { + ExpirationPolicy policy = null; + new PassiveExpiringMap(policy); + fail("constructor - exception should have been thrown."); + } catch (IllegalArgumentException ex) { + // success + } - try { - TimeUnit unit = null; - new PassiveExpiringMap(10L, unit); - fail("constructor - exception should have been thrown."); - } catch (IllegalArgumentException ex) { - // success - } - } + try { + TimeUnit unit = null; + new PassiveExpiringMap(10L, unit); + fail("constructor - exception should have been thrown."); + } catch (IllegalArgumentException ex) { + // success + } + } - public void testContainsKey() { - Map m = makeTestMap(); - assertFalse(m.containsKey(Integer.valueOf(1))); - assertFalse(m.containsKey(Integer.valueOf(3))); - assertFalse(m.containsKey(Integer.valueOf(5))); - assertTrue(m.containsKey(Integer.valueOf(2))); - assertTrue(m.containsKey(Integer.valueOf(4))); - assertTrue(m.containsKey(Integer.valueOf(6))); - } + public void testContainsKey() { + Map m = makeTestMap(); + assertFalse(m.containsKey(Integer.valueOf(1))); + assertFalse(m.containsKey(Integer.valueOf(3))); + assertFalse(m.containsKey(Integer.valueOf(5))); + assertTrue(m.containsKey(Integer.valueOf(2))); + assertTrue(m.containsKey(Integer.valueOf(4))); + assertTrue(m.containsKey(Integer.valueOf(6))); + } - public void testContainsValue() { - Map m = makeTestMap(); - assertFalse(m.containsValue("one")); - assertFalse(m.containsValue("three")); - assertFalse(m.containsValue("five")); - assertTrue(m.containsValue("two")); - assertTrue(m.containsValue("four")); - assertTrue(m.containsValue("six")); - } + public void testContainsValue() { + Map m = makeTestMap(); + assertFalse(m.containsValue("one")); + assertFalse(m.containsValue("three")); + assertFalse(m.containsValue("five")); + assertTrue(m.containsValue("two")); + assertTrue(m.containsValue("four")); + assertTrue(m.containsValue("six")); + } - public void testDecoratedMap() { - // entries shouldn't expire - Map m = makeDecoratedTestMap(); - assertEquals(6, m.size()); - assertEquals("one", m.get(Integer.valueOf(1))); + public void testDecoratedMap() { + // entries shouldn't expire + Map m = makeDecoratedTestMap(); + assertEquals(6, m.size()); + assertEquals("one", m.get(Integer.valueOf(1))); - // removing a single item shouldn't affect any other items - assertEquals("two", m.get(Integer.valueOf(2))); - m.remove(Integer.valueOf(2)); - assertEquals(5, m.size()); - assertEquals("one", m.get(Integer.valueOf(1))); - assertNull(m.get(Integer.valueOf(2))); + // removing a single item shouldn't affect any other items + assertEquals("two", m.get(Integer.valueOf(2))); + m.remove(Integer.valueOf(2)); + assertEquals(5, m.size()); + assertEquals("one", m.get(Integer.valueOf(1))); + assertNull(m.get(Integer.valueOf(2))); - // adding a single, even item shouldn't affect any other items - assertNull(m.get(Integer.valueOf(2))); - m.put(Integer.valueOf(2), "two"); - assertEquals(6, m.size()); - assertEquals("one", m.get(Integer.valueOf(1))); - assertEquals("two", m.get(Integer.valueOf(2))); + // adding a single, even item shouldn't affect any other items + assertNull(m.get(Integer.valueOf(2))); + m.put(Integer.valueOf(2), "two"); + assertEquals(6, m.size()); + assertEquals("one", m.get(Integer.valueOf(1))); + assertEquals("two", m.get(Integer.valueOf(2))); - // adding a single, odd item (one that expires) shouldn't affect any - // other items - // put the entry expires immediately - m.put(Integer.valueOf(1), "one-one"); - assertEquals(5, m.size()); - assertNull(m.get(Integer.valueOf(1))); - assertEquals("two", m.get(Integer.valueOf(2))); - } + // adding a single, odd item (one that expires) shouldn't affect any + // other items + // put the entry expires immediately + m.put(Integer.valueOf(1), "one-one"); + assertEquals(5, m.size()); + assertNull(m.get(Integer.valueOf(1))); + assertEquals("two", m.get(Integer.valueOf(2))); + } - public void testEntrySet() { - Map m = makeTestMap(); - assertEquals(3, m.entrySet().size()); - } + public void testEntrySet() { + Map m = makeTestMap(); + assertEquals(3, m.entrySet().size()); + } - public void testGet() { - Map m = makeTestMap(); - assertNull(m.get(Integer.valueOf(1))); - assertEquals("two", m.get(Integer.valueOf(2))); - assertNull(m.get(Integer.valueOf(3))); - assertEquals("four", m.get(Integer.valueOf(4))); - assertNull(m.get(Integer.valueOf(5))); - assertEquals("six", m.get(Integer.valueOf(6))); - } + public void testGet() { + Map m = makeTestMap(); + assertNull(m.get(Integer.valueOf(1))); + assertEquals("two", m.get(Integer.valueOf(2))); + assertNull(m.get(Integer.valueOf(3))); + assertEquals("four", m.get(Integer.valueOf(4))); + assertNull(m.get(Integer.valueOf(5))); + assertEquals("six", m.get(Integer.valueOf(6))); + } - public void testIsEmpty() { - Map m = makeTestMap(); - assertFalse(m.isEmpty()); + public void testIsEmpty() { + Map m = makeTestMap(); + assertFalse(m.isEmpty()); - // remove just evens - m = makeTestMap(); - m.remove(Integer.valueOf(2)); - m.remove(Integer.valueOf(4)); - m.remove(Integer.valueOf(6)); - assertTrue(m.isEmpty()); - } + // remove just evens + m = makeTestMap(); + m.remove(Integer.valueOf(2)); + m.remove(Integer.valueOf(4)); + m.remove(Integer.valueOf(6)); + assertTrue(m.isEmpty()); + } - public void testKeySet() { - Map m = makeTestMap(); - assertEquals(3, m.keySet().size()); - } + public void testKeySet() { + Map m = makeTestMap(); + assertEquals(3, m.keySet().size()); + } - public void testSize() { - Map m = makeTestMap(); - assertEquals(3, m.size()); - } + public void testSize() { + Map m = makeTestMap(); + assertEquals(3, m.size()); + } - public void testValues() { - Map m = makeTestMap(); - assertEquals(3, m.values().size()); - } + public void testValues() { + Map m = makeTestMap(); + assertEquals(3, m.values().size()); + } - public void testZeroTimeToLive() { - // item should not be available - PassiveExpiringMap m = new PassiveExpiringMap( - 0L); - m.put("a", "b"); - assertNull(m.get("a")); - } + public void testZeroTimeToLive() { + // item should not be available + PassiveExpiringMap m = new PassiveExpiringMap( + 0L); + m.put("a", "b"); + assertNull(m.get("a")); + } }