Author: jason.greene(a)jboss.com
Date: 2008-08-07 00:21:36 -0400 (Thu, 07 Aug 2008)
New Revision: 6536
Added:
core/trunk/src/main/java/org/jboss/cache/util/Immutables.java
Removed:
core/trunk/src/main/java/org/jboss/cache/util/ImmutableMapCopy.java
core/trunk/src/main/java/org/jboss/cache/util/ImmutableSetCopy.java
Modified:
core/trunk/src/main/java/org/jboss/cache/Fqn.java
core/trunk/src/main/java/org/jboss/cache/PessimisticUnversionedNode.java
core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyGroup.java
core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java
core/trunk/src/main/java/org/jboss/cache/invocation/AbstractInvocationContext.java
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java
core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java
core/trunk/src/main/java/org/jboss/cache/loader/AsyncCacheLoader.java
core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java
core/trunk/src/main/java/org/jboss/cache/transaction/AbstractTransactionContext.java
core/trunk/src/main/java/org/jboss/cache/util/ImmutableListCopy.java
core/trunk/src/test/java/org/jboss/cache/util/ImmutableListCopyTest.java
Log:
Convert all immutable usage to new Immutables factory.
Drop ImmutableMapCopy and ImmutableSetCopy in favor of map/set wrappers
Add immutable wrappers which are detectable (unlike Collections.unmodifiable*)
Modified: core/trunk/src/main/java/org/jboss/cache/Fqn.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/Fqn.java 2008-08-06 16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/Fqn.java 2008-08-07 04:21:36 UTC (rev 6536)
@@ -7,9 +7,6 @@
package org.jboss.cache;
-import net.jcip.annotations.Immutable;
-import org.jboss.cache.util.ImmutableListCopy;
-
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
@@ -19,6 +16,10 @@
import java.util.Collections;
import java.util.List;
+import net.jcip.annotations.Immutable;
+
+import org.jboss.cache.util.Immutables;
+
/**
* A Fully Qualified Name (Fqn) is a list of names (typically Strings but can be any
Object),
* which represent a path to a particular {@link Node} or sometimes a {@link Region} in a
{@link Cache}.
@@ -114,7 +115,7 @@
if (names != null)
{
// if not safe make a defensive copy
- elements = safe ? names : new ImmutableListCopy<Object>(names);
+ elements = safe ? names : Immutables.immutableListCopy(names);
size = elements.size();
}
else
@@ -126,7 +127,7 @@
protected Fqn(Fqn base, List<Object> relative)
{
- elements = new ImmutableListCopy<Object>(base.elements, relative);
+ elements = Immutables.immutableListMerge(base.elements, relative);
size = elements.size();
}
@@ -232,8 +233,8 @@
return root();
String toMatch = stringRepresentation.startsWith(SEPARATOR) ?
stringRepresentation.substring(1) : stringRepresentation;
- Object[] el = toMatch.split("/");
- return new Fqn(new ImmutableListCopy(el), true);
+ Object[] el = toMatch.split(SEPARATOR);
+ return new Fqn(Immutables.immutableListWrap(el), true);
}
/**
Modified: core/trunk/src/main/java/org/jboss/cache/PessimisticUnversionedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/PessimisticUnversionedNode.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/PessimisticUnversionedNode.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -1,6 +1,13 @@
package org.jboss.cache;
import static org.jboss.cache.AbstractNode.NodeFlags.VALID;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentMap;
+
import org.jboss.cache.commands.CommandsFactory;
import org.jboss.cache.commands.legacy.write.CreateNodeCommand;
import org.jboss.cache.invocation.InvocationContext;
@@ -9,14 +16,8 @@
import org.jboss.cache.marshall.MarshalledValue;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.util.FastCopyHashMap;
-import org.jboss.cache.util.ImmutableSetCopy;
+import org.jboss.cache.util.Immutables;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-
/**
* UnversionedNode specific to pessimistic locking, with legacy code.
*
@@ -290,7 +291,7 @@
{
if (children != null && !children.isEmpty())
{
- return new ImmutableSetCopy(children.values());
+ return Immutables.immutableSetConvert(children.values());
}
else
{
Modified: core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-08-06 16:17:53 UTC
(rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/UnversionedNode.java 2008-08-07 04:21:36 UTC
(rev 6536)
@@ -6,13 +6,11 @@
*/
package org.jboss.cache;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import static org.jboss.cache.AbstractNode.NodeFlags.*;
-import org.jboss.cache.marshall.MarshalledValue;
-import org.jboss.cache.util.FastCopyHashMap;
-import org.jboss.cache.util.ImmutableSetCopy;
-import org.jboss.cache.util.concurrent.SelfInitializingConcurrentHashMap;
+import static org.jboss.cache.AbstractNode.NodeFlags.CHILDREN_LOADED;
+import static org.jboss.cache.AbstractNode.NodeFlags.DATA_LOADED;
+import static org.jboss.cache.AbstractNode.NodeFlags.LOCK_FOR_CHILD_INSERT_REMOVE;
+import static org.jboss.cache.AbstractNode.NodeFlags.REMOVED;
+import static org.jboss.cache.AbstractNode.NodeFlags.VALID;
import java.util.Collections;
import java.util.HashMap;
@@ -22,6 +20,13 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.marshall.MarshalledValue;
+import org.jboss.cache.util.FastCopyHashMap;
+import org.jboss.cache.util.Immutables;
+import org.jboss.cache.util.concurrent.SelfInitializingConcurrentHashMap;
+
/**
* Basic data node class. Throws {@link UnsupportedOperationException} for
version-specific methods like {@link #getVersion()} and
* {@link #setVersion(org.jboss.cache.optimistic.DataVersion)}, defined in {@link
org.jboss.cache.NodeSPI}.
@@ -208,7 +213,7 @@
{
if (!children.isEmpty())
{
- return new ImmutableSetCopy<InternalNode<K,
V>>(children().values());
+ return Immutables.immutableSetConvert(children().values());
}
else
{
@@ -370,9 +375,10 @@
if (data != null) data.clear();
}
+ @SuppressWarnings("unchecked")
public Set<Object> getChildrenNames()
{
- return children.isEmpty() ? Collections.emptySet() : new
ImmutableSetCopy<Object>(children.keySet());
+ return children.isEmpty() ? Collections.emptySet() :
Immutables.immutableSetCopy(children.keySet());
}
public Set<K> getKeys()
@@ -381,7 +387,7 @@
{
return Collections.emptySet();
}
- return new ImmutableSetCopy<K>(data.keySet());
+ return Immutables.immutableSetCopy(data.keySet());
}
public boolean removeChild(Object childName)
Modified: core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyGroup.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyGroup.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/buddyreplication/BuddyGroup.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -6,16 +6,17 @@
*/
package org.jboss.cache.buddyreplication;
-import net.jcip.annotations.ThreadSafe;
-import org.jboss.cache.util.ImmutableListCopy;
-import org.jgroups.Address;
-
import java.io.Serializable;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Vector;
+import net.jcip.annotations.ThreadSafe;
+
+import org.jboss.cache.util.Immutables;
+import org.jgroups.Address;
+
/**
* Value object that represents a buddy group
*
@@ -65,7 +66,7 @@
public List<Address> getBuddies()
{
// defensive copy and immutable.
- return new ImmutableListCopy<Address>(buddies);
+ return Immutables.immutableListCopy(buddies);
}
protected void addBuddies(Collection<Address> buddies)
Modified: core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java 2008-08-06
16:17:53 UTC (rev 6535)
+++
core/trunk/src/main/java/org/jboss/cache/commands/read/GetDataMapCommand.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -4,7 +4,7 @@
import org.jboss.cache.NodeSPI;
import org.jboss.cache.commands.Visitor;
import org.jboss.cache.invocation.InvocationContext;
-import org.jboss.cache.util.ImmutableMapCopy;
+import org.jboss.cache.util.Immutables;
/**
* Implements functionality defined by {@link
org.jboss.cache.Cache#getData(org.jboss.cache.Fqn)}
@@ -35,9 +35,9 @@
*/
public Object perform(InvocationContext ctx)
{
- NodeSPI n = ctx.lookUpNode(fqn);
+ NodeSPI<?,?> n = ctx.lookUpNode(fqn);
if (n == null || n.isDeleted()) return null;
- return new ImmutableMapCopy(n.getDataDirect());
+ return Immutables.immutableMapCopy(n.getDataDirect());
}
public Object acceptVisitor(InvocationContext ctx, Visitor visitor) throws Throwable
Modified:
core/trunk/src/main/java/org/jboss/cache/invocation/AbstractInvocationContext.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/invocation/AbstractInvocationContext.java 2008-08-06
16:17:53 UTC (rev 6535)
+++
core/trunk/src/main/java/org/jboss/cache/invocation/AbstractInvocationContext.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -6,6 +6,12 @@
*/
package org.jboss.cache.invocation;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import javax.transaction.Transaction;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.commands.VisitableCommand;
@@ -14,13 +20,8 @@
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionContext;
import org.jboss.cache.transaction.TransactionTable;
-import org.jboss.cache.util.ImmutableListCopy;
+import org.jboss.cache.util.Immutables;
-import javax.transaction.Transaction;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-
/**
* This context holds information specific to a method invocation. This is used for
Optimistic and Pessimisic Node Locking Schemes.
*
@@ -117,7 +118,7 @@
{
// first check transactional scope
if (transactionContext != null) return transactionContext.getLocks();
- return invocationLocks == null || invocationLocks.isEmpty() ?
Collections.emptyList() : new ImmutableListCopy(invocationLocks);
+ return invocationLocks == null || invocationLocks.isEmpty() ?
Collections.emptyList() : Immutables.immutableListConvert(invocationLocks);
}
@SuppressWarnings("unchecked")
Modified:
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java 2008-08-06
16:17:53 UTC (rev 6535)
+++
core/trunk/src/main/java/org/jboss/cache/invocation/CacheInvocationDelegate.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -1,5 +1,13 @@
package org.jboss.cache.invocation;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheException;
@@ -31,8 +39,8 @@
import org.jboss.cache.commands.write.RemoveKeyCommand;
import org.jboss.cache.commands.write.RemoveNodeCommand;
import org.jboss.cache.config.Configuration;
+import org.jboss.cache.config.Option;
import org.jboss.cache.config.Configuration.NodeLockingScheme;
-import org.jboss.cache.config.Option;
import org.jboss.cache.factories.annotations.Inject;
import org.jboss.cache.factories.annotations.NonVolatile;
import org.jboss.cache.factories.annotations.Start;
@@ -44,16 +52,9 @@
import org.jboss.cache.statetransfer.StateTransferManager;
import org.jboss.cache.transaction.GlobalTransaction;
import org.jboss.cache.transaction.TransactionTable;
-import org.jboss.cache.util.ImmutableSetCopy;
+import org.jboss.cache.util.Immutables;
import org.jgroups.Address;
-import javax.transaction.Transaction;
-import javax.transaction.TransactionManager;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
/**
* The delegate that users (and ChainedInterceptor authors) interact with when they
create a cache by using a cache factory.
* This wrapper delegates calls down the interceptor chain.
@@ -589,7 +590,7 @@
GetChildrenNamesCommand command =
commandsFactory.buildGetChildrenNamesCommand(fqn);
Set<Object> retval = (Set<Object>) invoker.invoke(ctx, command);
if (retval != null)
- retval = new ImmutableSetCopy<Object>(retval);
+ retval = Immutables.immutableSetWrap(retval); // this is already copied in the
command
else
retval = Collections.emptySet();
return retval;
Modified: core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/loader/AbstractCacheLoader.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -6,6 +6,14 @@
*/
package org.jboss.cache.loader;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.CacheException;
@@ -20,16 +28,8 @@
import org.jboss.cache.marshall.NodeData;
import org.jboss.cache.marshall.NodeDataExceptionMarker;
import org.jboss.cache.marshall.NodeDataMarker;
-import org.jboss.cache.util.ImmutableMapCopy;
+import org.jboss.cache.util.Immutables;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-
/**
* A convenience abstract implementation of a {@link CacheLoader}. Specific methods to
note are methods like
* {@link #storeState(org.jboss.cache.Fqn,java.io.ObjectInputStream)}, {@link
#loadState(org.jboss.cache.Fqn,java.io.ObjectOutputStream)},
@@ -64,7 +64,7 @@
}
// JBCACHE-769 -- make a defensive copy
- Map<Object, Object> attrs = (attributes == null ? null : new
ImmutableMapCopy<Object, Object>(attributes));
+ Map<Object, Object> attrs = (attributes == null ? null :
Immutables.immutableMapCopy(attributes));
put(fqn, attrs);
}
Modified: core/trunk/src/main/java/org/jboss/cache/loader/AsyncCacheLoader.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/loader/AsyncCacheLoader.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/loader/AsyncCacheLoader.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -3,14 +3,6 @@
*/
package org.jboss.cache.loader;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.jboss.cache.CacheException;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Modification;
-import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
-import org.jboss.cache.util.ImmutableMapCopy;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
@@ -26,6 +18,14 @@
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.cache.CacheException;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Modification;
+import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig;
+import org.jboss.cache.util.Immutables;
+
/**
* The AsyncCacheLoader is a delegating cache loader that extends
* AbstractDelegatingCacheLoader overriding methods to that should not
@@ -191,7 +191,7 @@
if (config.getUseAsyncPut())
{
// JBCACHE-769 -- make a defensive copy
- Map attrs = (attributes == null ? null : new ImmutableMapCopy(attributes));
+ Map attrs = (attributes == null ? null :
Immutables.immutableMapCopy(attributes));
Modification mod = new Modification(Modification.ModificationType.PUT_DATA,
name, attrs);
enqueue(mod);
}
Modified: core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/marshall/CacheMarshaller200.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -6,20 +6,6 @@
*/
package org.jboss.cache.marshall;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.Region;
-import static org.jboss.cache.Region.Status;
-import org.jboss.cache.buddyreplication.GravitateResult;
-import org.jboss.cache.commands.CommandsFactory;
-import org.jboss.cache.commands.ReplicableCommand;
-import org.jboss.cache.factories.annotations.Inject;
-import org.jboss.cache.optimistic.DefaultDataVersion;
-import org.jboss.cache.transaction.GlobalTransaction;
-import org.jboss.cache.util.FastCopyHashMap;
-import org.jboss.cache.util.ImmutableMapCopy;
-import org.jgroups.Address;
-import org.jgroups.stack.IpAddress;
-
import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInputStream;
@@ -36,6 +22,20 @@
import java.util.TreeMap;
import java.util.TreeSet;
+import org.jboss.cache.Fqn;
+import org.jboss.cache.Region;
+import org.jboss.cache.Region.Status;
+import org.jboss.cache.buddyreplication.GravitateResult;
+import org.jboss.cache.commands.CommandsFactory;
+import org.jboss.cache.commands.ReplicableCommand;
+import org.jboss.cache.factories.annotations.Inject;
+import org.jboss.cache.optimistic.DefaultDataVersion;
+import org.jboss.cache.transaction.GlobalTransaction;
+import org.jboss.cache.util.FastCopyHashMap;
+import org.jboss.cache.util.Immutables;
+import org.jgroups.Address;
+import org.jgroups.stack.IpAddress;
+
/**
* An enhanced marshaller for RPC calls between CacheImpl instances.
*
@@ -349,7 +349,7 @@
out.writeByte(MAGICNUMBER_FASTCOPY_HASHMAP);
marshallMap((Map) o, out, refMap);
}
- else if (o.getClass().equals(ImmutableMapCopy.class))
+ else if (o instanceof Map && Immutables.isImmutable(o))
{
out.writeByte(MAGICNUMBER_IMMUTABLE_MAPCOPY);
marshallMap((Map) o, out, refMap);
@@ -748,7 +748,7 @@
{
// read in as a HashMap first
Map m = unmarshallHashMap(in, refMap);
- return new ImmutableMapCopy(m);
+ return Immutables.immutableMapWrap(m);
}
private Map unmarshallTreeMap(ObjectInputStream in, UnmarshalledReferences refMap)
throws Exception
Modified: core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/notifications/NotifierImpl.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -6,6 +6,43 @@
*/
package org.jboss.cache.notifications;
+import static org.jboss.cache.notifications.event.Event.Type.BUDDY_GROUP_CHANGED;
+import static org.jboss.cache.notifications.event.Event.Type.CACHE_BLOCKED;
+import static org.jboss.cache.notifications.event.Event.Type.CACHE_STARTED;
+import static org.jboss.cache.notifications.event.Event.Type.CACHE_STOPPED;
+import static org.jboss.cache.notifications.event.Event.Type.CACHE_UNBLOCKED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_ACTIVATED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_CREATED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_EVICTED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_INVALIDATED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_LOADED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_MODIFIED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_MOVED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_PASSIVATED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_REMOVED;
+import static org.jboss.cache.notifications.event.Event.Type.NODE_VISITED;
+import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_COMPLETED;
+import static org.jboss.cache.notifications.event.Event.Type.TRANSACTION_REGISTERED;
+import static org.jboss.cache.notifications.event.Event.Type.VIEW_CHANGED;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import javax.transaction.Transaction;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.cache.Cache;
@@ -21,30 +58,49 @@
import org.jboss.cache.factories.annotations.Stop;
import org.jboss.cache.invocation.InvocationContext;
import org.jboss.cache.marshall.MarshalledValueMap;
-import org.jboss.cache.notifications.annotation.*;
-import org.jboss.cache.notifications.event.*;
-import static org.jboss.cache.notifications.event.Event.Type.*;
-import org.jboss.cache.util.ImmutableMapCopy;
+import org.jboss.cache.notifications.annotation.BuddyGroupChanged;
+import org.jboss.cache.notifications.annotation.CacheBlocked;
+import org.jboss.cache.notifications.annotation.CacheListener;
+import org.jboss.cache.notifications.annotation.CacheStarted;
+import org.jboss.cache.notifications.annotation.CacheStopped;
+import org.jboss.cache.notifications.annotation.CacheUnblocked;
+import org.jboss.cache.notifications.annotation.NodeActivated;
+import org.jboss.cache.notifications.annotation.NodeCreated;
+import org.jboss.cache.notifications.annotation.NodeEvicted;
+import org.jboss.cache.notifications.annotation.NodeInvalidated;
+import org.jboss.cache.notifications.annotation.NodeLoaded;
+import org.jboss.cache.notifications.annotation.NodeModified;
+import org.jboss.cache.notifications.annotation.NodeMoved;
+import org.jboss.cache.notifications.annotation.NodePassivated;
+import org.jboss.cache.notifications.annotation.NodeRemoved;
+import org.jboss.cache.notifications.annotation.NodeVisited;
+import org.jboss.cache.notifications.annotation.TransactionCompleted;
+import org.jboss.cache.notifications.annotation.TransactionRegistered;
+import org.jboss.cache.notifications.annotation.ViewChanged;
+import org.jboss.cache.notifications.event.BuddyGroupChangedEvent;
+import org.jboss.cache.notifications.event.CacheBlockedEvent;
+import org.jboss.cache.notifications.event.CacheStartedEvent;
+import org.jboss.cache.notifications.event.CacheStoppedEvent;
+import org.jboss.cache.notifications.event.CacheUnblockedEvent;
+import org.jboss.cache.notifications.event.Event;
+import org.jboss.cache.notifications.event.EventImpl;
+import org.jboss.cache.notifications.event.NodeActivatedEvent;
+import org.jboss.cache.notifications.event.NodeCreatedEvent;
+import org.jboss.cache.notifications.event.NodeEvictedEvent;
+import org.jboss.cache.notifications.event.NodeInvalidatedEvent;
+import org.jboss.cache.notifications.event.NodeLoadedEvent;
+import org.jboss.cache.notifications.event.NodeModifiedEvent;
+import org.jboss.cache.notifications.event.NodeMovedEvent;
+import org.jboss.cache.notifications.event.NodePassivatedEvent;
+import org.jboss.cache.notifications.event.NodeRemovedEvent;
+import org.jboss.cache.notifications.event.NodeVisitedEvent;
+import org.jboss.cache.notifications.event.TransactionCompletedEvent;
+import org.jboss.cache.notifications.event.TransactionRegisteredEvent;
+import org.jboss.cache.notifications.event.ViewChangedEvent;
+import org.jboss.cache.util.Immutables;
import org.jboss.cache.util.concurrent.WithinThreadExecutor;
import org.jgroups.View;
-import javax.transaction.Transaction;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.atomic.AtomicInteger;
-
/**
* Helper class that handles all notifications to registered listeners.
*
@@ -606,7 +662,7 @@
if (data == null) return null;
if (data.isEmpty()) return Collections.emptyMap();
if (safe(data)) return useMarshalledValueMaps ? new MarshalledValueMap(data) :
data;
- Map defensivelyCopiedData = new ImmutableMapCopy(data);
+ Map defensivelyCopiedData = Immutables.immutableMapCopy(data);
return useMarshalledValueMaps ? new MarshalledValueMap(defensivelyCopiedData) :
defensivelyCopiedData;
}
@@ -643,7 +699,7 @@
*/
private static boolean safe(Map map)
{
- return map == null || map instanceof ImmutableMapCopy ||
map.getClass().equals(emptyMap) || map.getClass().equals(singletonMap);
+ return map == null || Immutables.isImmutable(map) ||
map.getClass().equals(emptyMap) || map.getClass().equals(singletonMap);
}
/**
Modified:
core/trunk/src/main/java/org/jboss/cache/transaction/AbstractTransactionContext.java
===================================================================
---
core/trunk/src/main/java/org/jboss/cache/transaction/AbstractTransactionContext.java 2008-08-06
16:17:53 UTC (rev 6535)
+++
core/trunk/src/main/java/org/jboss/cache/transaction/AbstractTransactionContext.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -7,21 +7,22 @@
package org.jboss.cache.transaction;
-import org.jboss.cache.Fqn;
-import org.jboss.cache.commands.WriteCommand;
-import org.jboss.cache.config.Option;
-import org.jboss.cache.interceptors.OrderedSynchronizationHandler;
-import org.jboss.cache.util.ImmutableListCopy;
-
-import javax.transaction.RollbackException;
-import javax.transaction.SystemException;
-import javax.transaction.Transaction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+
+import org.jboss.cache.Fqn;
+import org.jboss.cache.commands.WriteCommand;
+import org.jboss.cache.config.Option;
+import org.jboss.cache.interceptors.OrderedSynchronizationHandler;
+import org.jboss.cache.util.Immutables;
+
/**
* An abstract transaction context
*/
@@ -159,7 +160,7 @@
@SuppressWarnings("unchecked")
public List getLocks()
{
- return transactionLocks == null || transactionLocks.isEmpty() ?
Collections.emptyList() : new ImmutableListCopy(transactionLocks);
+ return transactionLocks == null || transactionLocks.isEmpty() ?
Collections.emptyList() : Immutables.immutableListConvert(transactionLocks);
}
Modified: core/trunk/src/main/java/org/jboss/cache/util/ImmutableListCopy.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/ImmutableListCopy.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/util/ImmutableListCopy.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -29,7 +29,7 @@
* @since 3.0
*/
@Immutable
-public class ImmutableListCopy<E> extends AbstractList<E> implements
Externalizable
+public class ImmutableListCopy<E> extends AbstractList<E> implements
Externalizable, Immutables.Immutable
{
private static final long serialVersionUID = 10929568968966L;
private E[] elements;
Deleted: core/trunk/src/main/java/org/jboss/cache/util/ImmutableMapCopy.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/ImmutableMapCopy.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/util/ImmutableMapCopy.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -1,149 +0,0 @@
-package org.jboss.cache.util;
-
-import net.jcip.annotations.Immutable;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.AbstractMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Along the lines of ImmutableListCopy and ImmutableSetCopy. This lightweight wrapper
primarily meant for iteration.
- * performance of get() and containsKey() are not as efficient as that of a {@link
java.util.HashMap}, but iteration is
- * fast since the entry table is a fixed size immutable array.
- * <p/>
- * Typically used in place of the common idiom:
- * <code>
- * return Collections.unmodifiableMap(new HashMap( myInternalMap ));
- * </code>
- *
- * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
- * @since 3.0
- */
-@Immutable
-public class ImmutableMapCopy<K, V> extends AbstractMap<K, V> implements
Externalizable // externalizable for client code that may serialize this map
-{
- private static final long serialVersionUID = 10929568968766L;
- private Entry<K, V>[] table;
- private int size;
-
- /**
- * For Externalizable
- */
- public ImmutableMapCopy()
- {
- }
-
- @SuppressWarnings("unchecked")
- public ImmutableMapCopy(Map<K, V> map)
- {
- size = map.size();
- table = new ImmutableEntry[size];
- int i = 0;
- for (Map.Entry<K, V> me : map.entrySet())
- {
- table[i++] = new ImmutableEntry<K, V>(me);
- }
- }
-
- @Override
- public int size()
- {
- return size;
- }
-
- @Override
- public final V remove(Object key)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public final void putAll(Map<? extends K, ? extends V> t)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public final void clear()
- {
- throw new UnsupportedOperationException();
- }
-
- public final Set<Entry<K, V>> entrySet()
- {
- return new ImmutableSetCopy<Map.Entry<K, V>>(table);
- }
-
- /**
- * Format:
- * - entry array size (int)
- * - entry key-value pairs (Object, Object)
- *
- * @param out stream to write to
- * @throws IOException
- */
- public void writeExternal(ObjectOutput out) throws IOException
- {
- out.writeInt(size);
- for (Entry e : table)
- {
- out.writeObject(e.getKey());
- out.writeObject(e.getValue());
- }
- }
-
- /**
- * See {@link #writeExternal(java.io.ObjectOutput)} for serialization format
- *
- * @param in stream
- * @throws IOException
- * @throws ClassNotFoundException
- */
- @SuppressWarnings("unchecked")
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
- {
- size = in.readInt();
- table = new Entry[size];
- for (int i = 0; i < size; i++)
- {
- table[i] = new ImmutableEntry(in.readObject(), in.readObject());
- }
- }
-
- private static class ImmutableEntry<K, V> implements Map.Entry<K, V>
- {
- K k;
- V v;
-
- private ImmutableEntry(Map.Entry<K, V> entry)
- {
- k = entry.getKey();
- v = entry.getValue();
- }
-
- private ImmutableEntry(K k, V v)
- {
- this.k = k;
- this.v = v;
- }
-
- public K getKey()
- {
- return k;
- }
-
- public V getValue()
- {
- return v;
- }
-
- public V setValue(V value)
- {
- throw new UnsupportedOperationException();
- }
- }
-}
Deleted: core/trunk/src/main/java/org/jboss/cache/util/ImmutableSetCopy.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/ImmutableSetCopy.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/main/java/org/jboss/cache/util/ImmutableSetCopy.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -1,143 +0,0 @@
-package org.jboss.cache.util;
-
-import net.jcip.annotations.Immutable;
-
-import java.io.Externalizable;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import java.util.AbstractSet;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-/**
- * This is based on an ImmutableListCopy, with the assumption that the set passed in
would ensure uniqueness of elements.
- * <p/>
- * The constructor takes in a collection so the onus is on the caller to ensure that the
collection passed in adheres to
- * Set semantics.
- * <p/>
- * Typically used in place of the common idiom:
- * <code>
- * return Collections.unmodifiableSet(new HashSet( myInternalSet ));
- * </code>
- *
- * @author Manik Surtani (<a
href="mailto:manik@jboss.org">manik@jboss.org</a>)
- * @see org.jboss.cache.util.ImmutableListCopy
- * @since 3.0
- */
-@Immutable
-public class ImmutableSetCopy<E> extends AbstractSet<E> implements
Externalizable
-{
- private static final long serialVersionUID = 11929568968766L;
- private E[] elements;
- private int size;
-
- @SuppressWarnings("unchecked")
- public ImmutableSetCopy(Collection<E> set)
- {
- size = set.size();
- E[] tempElements = (E[]) new Object[size]; // no room for growth
- elements = set.toArray(tempElements);
- }
-
- /**
- * Assumes that the array passed in is "safe", i.e., is not referenced from
elsewhere. Also assumes the array contains
- * elements such that the uniqueness required by a set is adhered to. Use with care!
- *
- * @param array to reference
- */
- public ImmutableSetCopy(E[] array)
- {
- elements = array;
- size = elements.length;
- }
-
- @Override
- public boolean remove(Object o)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean addAll(Collection<? extends E> c)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean retainAll(Collection<?> c)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean removeAll(Collection<?> c)
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void clear()
- {
- throw new UnsupportedOperationException();
- }
-
- public Iterator<E> iterator()
- {
- return new Iterator<E>()
- {
- int cursor = 0;
-
- public boolean hasNext()
- {
- return cursor < size;
- }
-
- public E next()
- {
- if (cursor >= size) throw new NoSuchElementException();
- return elements[cursor++];
- }
-
- public void remove()
- {
- throw new UnsupportedOperationException();
- }
- };
- }
-
- public int size()
- {
- return size;
- }
-
- /**
- * Format:
- * - entry array size (int)
- * - elements (Object)
- *
- * @param out stream to write to
- * @throws IOException
- */
- public void writeExternal(ObjectOutput out) throws IOException
- {
- out.writeInt(size);
- for (E e : elements) out.writeObject(e);
- }
-
- /**
- * See {@link #writeExternal(java.io.ObjectOutput)} for serialization format
- *
- * @param in stream
- * @throws IOException
- * @throws ClassNotFoundException
- */
- @SuppressWarnings("unchecked")
- public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException
- {
- size = in.readInt();
- elements = (E[]) new Object[size];
- for (int i = 0; i < size; i++) elements[i] = (E) in.readObject();
- }
-}
Added: core/trunk/src/main/java/org/jboss/cache/util/Immutables.java
===================================================================
--- core/trunk/src/main/java/org/jboss/cache/util/Immutables.java
(rev 0)
+++ core/trunk/src/main/java/org/jboss/cache/util/Immutables.java 2008-08-07 04:21:36 UTC
(rev 6536)
@@ -0,0 +1,541 @@
+/*
+* JBoss, Home of Professional Open Source
+* Copyright 2005, JBoss Inc., and individual contributors as indicated
+* by the @authors tag. See the copyright.txt in the distribution for a
+* full listing of individual contributors.
+*
+* This is free software; you can redistribute it and/or modify it
+* under the terms of the GNU Lesser General Public License as
+* published by the Free Software Foundation; either version 2.1 of
+* the License, or (at your option) any later version.
+*
+* This software is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this software; if not, write to the Free
+* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+* 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+*/
+package org.jboss.cache.util;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Map.Entry;
+
+/**
+ * Factory for generating immutable type wrappers.
+ *
+ * @author Jason T. Greene
+ */
+public class Immutables
+{
+ /**
+ * Whether or not this collection type is immutable
+ *
+ * @param a Collection, Set, List, or Map
+ * @return true if immutable, false if not
+ */
+ public static boolean isImmutable(Object o)
+ {
+ return o instanceof Immutable;
+ }
+
+ /**
+ * Converts a Collection to an immutable List by copying it.
+ *
+ * @param source the collection to convert
+ * @return a copied/converted immutable list
+ */
+ public static <T> List<T> immutableListConvert(Collection<? extends
T> source)
+ {
+ return new ImmutableListCopy<T>(source);
+ }
+
+ /**
+ * Creates an immutable copy of the list.
+ *
+ * @param list the list to copy
+ * @return the immutable copy
+ */
+ public static <T> List<T> immutableListCopy(List<? extends T> list)
+ {
+ return new ImmutableListCopy<T>(list);
+ }
+
+ /**
+ * Wraps an array with an immutable list. There is no copying involved.
+ *
+ * @param <T>
+ * @param array the array to wrap
+ * @return a list containing the array
+ */
+ public static <T> List<T> immutableListWrap(T... array)
+ {
+ return new ImmutableListCopy<T>(array);
+ }
+
+ /**
+ * Creates a new immutable list containing the union (combined entries) of both
lists.
+ *
+ * @param list1 contains the first elements of the new list
+ * @param list2 contains the successor elements of the new list
+ * @return a new immutable merged copy of list1 and list2
+ */
+ public static <T> List<T> immutableListMerge(List<? extends T>
list1, List<? extends T> list2)
+ {
+ return new ImmutableListCopy<T>(list1, list2);
+ }
+
+ /**
+ * Converts a Collections into an immutable Set by copying it.
+ *
+ * @param collection the collection to convert/copy
+ * @return a new immutable set containing the elements in collection
+ */
+ public static <T> Set<T> immutableSetConvert(Collection<? extends T>
collection)
+ {
+ return immutableSetWrap(new HashSet<T>(collection));
+ }
+
+ /**
+ * Wraps a set with an immutable set. There is no copying involved.
+ *
+ * @param set the set to wrap
+ * @return an immutable set wrapper that delegates to the original set
+ */
+ public static <T> Set<T> immutableSetWrap(Set<? extends T> set)
+ {
+ return new ImmutableSetWrapper<T>(set);
+ }
+
+ /**
+ * Creates an immutable copy of the specified set.
+ *
+ * @param set the set to copy from
+ * @return an immutable set copy
+ */
+ public static <T> Set<T> immutableSetCopy(Set<? extends T> set)
+ {
+ Set<? extends T> copy = attemptClone(set);
+ if (copy == null)
+ // Set uses Collection copy-ctor
+ copy = attemptCopyConstructor(set, Collection.class);
+
+ if (copy == null)
+ copy = new HashSet<T>(set);
+
+ return new ImmutableSetWrapper<T>(copy);
+ }
+
+
+ /**
+ * Wraps a map with an immutable map. There is no copying involved.
+ *
+ * @param map the map to wrap
+ * @return an immutable map wrapper that delegates to the original map
+ */
+ public static <K,V> Map<K,V> immutableMapWrap(Map<? extends K, ?
extends V> map)
+ {
+ return new ImmutableMapWrapper<K,V>(map);
+ }
+
+ /**
+ * Creates an immutable copy of the specified map.
+ *
+ * @param map the map to copy from
+ * @return an immutable map copy
+ */
+ public static <K,V> Map<K,V> immutableMapCopy(Map<? extends K, ?
extends V> map)
+ {
+ Map<? extends K, ? extends V> copy = attemptClone(map);
+ if (copy == null)
+ copy = attemptCopyConstructor(map, Map.class);
+ if (copy == null)
+ copy = new HashMap<K,V>(map);
+
+ return new ImmutableMapWrapper<K,V>(map);
+ }
+
+ /**
+ * Creates a new immutable copy of the specified Collection.
+ *
+ * @param collection the collection to copy
+ * @return an immutable copy
+ */
+ public static <T> Collection<T> immutableCollectionCopy(Collection<?
extends T> collection)
+ {
+ Collection<? extends T> copy = attemptClone(collection);
+ if (copy == null)
+ copy = attemptCopyConstructor(collection, Collection.class);
+ if (copy == null)
+ copy = new ArrayList<T>(collection);
+
+ return new ImmutableCollectionWrapper<T>(collection);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private static <T> T attemptClone(T source)
+ {
+ if (source instanceof Cloneable)
+ {
+ try
+ {
+ return (T) source.getClass().getMethod("clone").invoke(source);
+ }
+ catch (Exception e)
+ {
+ }
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T attemptCopyConstructor(T source, Class<? super T>
clazz)
+ {
+ try
+ {
+ return (T) source.getClass().getConstructor(clazz).newInstance(source);
+ }
+ catch (Exception e)
+ {
+ }
+
+ return null;
+ }
+
+
+ public interface Immutable
+ {
+ }
+
+ /*
+ * Immutable wrapper types.
+ *
+ * We have to re-implement Collections.unmodifiableXXX, since it is not
+ * simple to detect them (the class names are JDK dependent).
+ */
+
+ private static class ImmutableIteratorWrapper<E> implements Iterator<E>
+ {
+ private Iterator<? extends E> iterator;
+
+ public ImmutableIteratorWrapper(Iterator<? extends E> iterator)
+ {
+ this.iterator = iterator;
+ }
+
+ public boolean hasNext()
+ {
+ return iterator.hasNext();
+ }
+
+ public E next()
+ {
+ return iterator.next();
+ }
+
+ public void remove()
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private static class ImmutableCollectionWrapper<E> implements
Collection<E>, Serializable, Immutable
+ {
+ private static final long serialVersionUID = 6777564328198393535L;
+
+ Collection<? extends E> collection;
+
+ public ImmutableCollectionWrapper(Collection<? extends E> collection)
+ {
+ this.collection = collection;
+ }
+
+ public boolean add(E o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean addAll(Collection<? extends E> c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean contains(Object o)
+ {
+ return collection.contains(o);
+ }
+
+ public boolean containsAll(Collection<?> c)
+ {
+ return collection.containsAll(c);
+ }
+
+ public boolean equals(Object o)
+ {
+ return collection.equals(o);
+ }
+
+ public int hashCode()
+ {
+ return collection.hashCode();
+ }
+
+ public boolean isEmpty()
+ {
+ return collection.isEmpty();
+ }
+
+ public Iterator<E> iterator()
+ {
+ return new ImmutableIteratorWrapper<E>(collection.iterator());
+ }
+
+ public boolean remove(Object o)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean removeAll(Collection<?> c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean retainAll(Collection<?> c)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int size()
+ {
+ return collection.size();
+ }
+
+ public Object[] toArray()
+ {
+ return collection.toArray();
+ }
+
+ public <T> T[] toArray(T[] a)
+ {
+ return collection.toArray(a);
+ }
+
+ public String toString()
+ {
+ return collection.toString();
+ }
+ }
+
+
+
+ private static class ImmutableSetWrapper<E> extends
ImmutableCollectionWrapper<E> implements Set<E>, Serializable, Immutable
+ {
+ private static final long serialVersionUID = 7991492805176142615L;
+
+ public ImmutableSetWrapper(Set<? extends E> set)
+ {
+ super(set);
+ }
+ }
+
+
+ static class ImmutableEntry<K, V> implements Map.Entry<K, V>
+ {
+ private K key;
+ private V value;
+ private int hash;
+
+ ImmutableEntry(Map.Entry<? extends K, ? extends V> entry)
+ {
+ this.key = entry.getKey();
+ this.value = entry.getValue();
+ this.hash = entry.hashCode();
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+
+ public V getValue()
+ {
+ return value;
+ }
+
+ public V setValue(V value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ private static boolean eq(Object o1, Object o2)
+ {
+ return o1 == o2 || (o1 != null && o1.equals(o2));
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean equals(Object o)
+ {
+ if (! (o instanceof Map.Entry))
+ return false;
+
+ Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
+ return eq(entry.getKey(), key) && eq(entry.getValue(), value);
+ }
+
+ public int hashCode()
+ {
+ return hash;
+ }
+
+ public String toString()
+ {
+ return getKey() + "=" + getValue();
+ }
+ }
+
+ private static class ImmutableEntrySetWrapper<K,V> extends
ImmutableSetWrapper<Map.Entry<K, V>>
+ {
+ private static final long serialVersionUID = 6378667653889667692L;
+
+ @SuppressWarnings("unchecked")
+ public ImmutableEntrySetWrapper(Set<? extends Map.Entry<? extends K, ?
extends V>> set)
+ {
+ super((Set<Entry<K, V>>)set);
+ }
+
+ public Object[] toArray()
+ {
+ Object[] array = new Object[collection.size()];
+ int i = 0;
+ for (Map.Entry<K, V> entry : this)
+ array[i++] = entry;
+ return array;
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T[] toArray(T[] array)
+ {
+ int size = collection.size();
+ if (array.length < size)
+ array = (T[]) Array.newInstance(array.getClass().getComponentType(), size);
+
+ int i = 0;
+ Object[] result = array;
+ for (Map.Entry<K, V> entry : this)
+ result[i++] = entry;
+
+ return array;
+ }
+
+ public Iterator<Map.Entry<K,V>> iterator()
+ {
+ return new
ImmutableIteratorWrapper<Entry<K,V>>(collection.iterator()) {
+ public Entry<K, V> next()
+ {
+ return new ImmutableEntry<K,V>(super.next());
+ }
+ };
+ }
+ }
+
+ private static class ImmutableMapWrapper<K,V> implements Map<K,V>,
Serializable, Immutable
+ {
+ private static final long serialVersionUID = 708144227046742221L;
+
+ private Map<? extends K, ? extends V> map;
+
+ public ImmutableMapWrapper(Map<? extends K, ? extends V> map)
+ {
+ this.map = map;
+ }
+
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return map.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return map.containsValue(value);
+ }
+
+ public Set<Entry<K, V>> entrySet()
+ {
+ return new ImmutableEntrySetWrapper<K,V>(map.entrySet());
+ }
+
+ public boolean equals(Object o)
+ {
+ return map.equals(o);
+ }
+
+ public V get(Object key)
+ {
+ return map.get(key);
+ }
+
+ public int hashCode()
+ {
+ return map.hashCode();
+ }
+
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ public Set<K> keySet()
+ {
+ return new ImmutableSetWrapper<K>(map.keySet());
+ }
+
+ public V put(K key, V value)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public void putAll(Map<? extends K, ? extends V> t)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public V remove(Object key)
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ public int size()
+ {
+ return map.size();
+ }
+
+ public Collection<V> values()
+ {
+ return new ImmutableCollectionWrapper<V>(map.values());
+ }
+ }
+}
Modified: core/trunk/src/test/java/org/jboss/cache/util/ImmutableListCopyTest.java
===================================================================
--- core/trunk/src/test/java/org/jboss/cache/util/ImmutableListCopyTest.java 2008-08-06
16:17:53 UTC (rev 6535)
+++ core/trunk/src/test/java/org/jboss/cache/util/ImmutableListCopyTest.java 2008-08-07
04:21:36 UTC (rev 6536)
@@ -12,7 +12,7 @@
{
public void testImmutability()
{
- List<String> l = new
ImmutableListCopy<String>(Collections.singletonList("one"));
+ List<String> l =
Immutables.immutableListCopy(Collections.singletonList("one"));
try
{
l.add("two");
@@ -126,10 +126,8 @@
public void testListIterator()
{
- List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+ List<Integer> list = Immutables.immutableListWrap(1, 2, 3, 4, 5, 6, 7, 8, 9,
10);
- List<Integer> list = new ImmutableListCopy<Integer>(ints);
-
ListIterator<Integer> li = list.listIterator();
int number = 1;
@@ -145,7 +143,7 @@
public void testSubLists()
{
List<Integer> ints = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
- List<Integer> list = new ImmutableListCopy<Integer>(ints);
+ List<Integer> list = Immutables.immutableListCopy(ints);
assert ints.subList(2, 5).equals(list.subList(2, 5));
assert ints.subList(1, 9).equals(list.subList(1, 9));