[jbosscache-commits] JBoss Cache SVN: r6946 - in core/branches/flat/src/main/java/org/jboss/starobrno: transaction and 3 other directories.

jbosscache-commits at lists.jboss.org jbosscache-commits at lists.jboss.org
Tue Oct 14 13:50:04 EDT 2008


Author: mircea.markus
Date: 2008-10-14 13:50:03 -0400 (Tue, 14 Oct 2008)
New Revision: 6946

Added:
   core/branches/flat/src/main/java/org/jboss/starobrno/RPCManager.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/
   core/branches/flat/src/main/java/org/jboss/starobrno/util/FastCopyHashMap.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/Immutables.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/ReflectionUtil.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/
   core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/
Modified:
   core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java
   core/branches/flat/src/main/java/org/jboss/starobrno/CacheException.java
   core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java
   core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/LockContainer.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/OwnableReentrantLock.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/OwnableReentrantLockContainer.java
   core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/ReentrantLockContainer.java
Log:
enabling replication 

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java	2008-10-14 17:49:31 UTC (rev 6945)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/CacheDelegate.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -26,7 +26,7 @@
 import org.jboss.cache.buddyreplication.GravitateResult;
 import org.jboss.cache.loader.CacheLoaderManager;
 import org.jboss.cache.marshall.Marshaller;
-import org.jboss.cache.statetransfer.StateTransferManager;
+import org.jboss.starobrno.statetransfer.StateTransferManager;
 import org.jboss.starobrno.batch.BatchContainer;
 import org.jboss.starobrno.commands.CommandsFactory;
 import org.jboss.starobrno.commands.read.GetKeyValueCommand;
@@ -47,7 +47,6 @@
 import org.jboss.starobrno.interceptors.base.CommandInterceptor;
 import org.jboss.starobrno.invocation.InvocationContextContainer;
 import org.jboss.starobrno.notifications.Notifier;
-import org.jboss.starobrno.remoting.RPCManager;
 import org.jboss.starobrno.transaction.GlobalTransaction;
 import org.jboss.starobrno.transaction.TransactionTable;
 

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/CacheException.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/CacheException.java	2008-10-14 17:49:31 UTC (rev 6945)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/CacheException.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -24,7 +24,7 @@
 /**
  * Thrown when operations on {@link Cache} or {@link org.jboss.cache.Node} fail unexpectedly.
  * <p/>
- * Specific subclasses such as {@link org.jboss.cache.lock.TimeoutException}, {@link org.jboss.cache.config.ConfigurationException} and {@link org.jboss.cache.lock.LockingException}
+ * Specific subclasses such as {@link org.jboss.starobrno.lock.TimeoutException}, {@link org.jboss.cache.config.ConfigurationException} and {@link org.jboss.cache.lock.LockingException}
  * have more specific uses.
  *
  * @author <a href="mailto:bela at jboss.org">Bela Ban</a>

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java	2008-10-14 17:49:31 UTC (rev 6945)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/CacheSPI.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -26,12 +26,11 @@
 import org.jboss.cache.buddyreplication.GravitateResult;
 import org.jboss.cache.loader.CacheLoaderManager;
 import org.jboss.cache.marshall.Marshaller;
-import org.jboss.cache.statetransfer.StateTransferManager;
+import org.jboss.starobrno.statetransfer.StateTransferManager;
 import org.jboss.starobrno.context.InvocationContext;
 import org.jboss.starobrno.factories.ComponentRegistry;
 import org.jboss.starobrno.interceptors.base.CommandInterceptor;
 import org.jboss.starobrno.notifications.Notifier;
-import org.jboss.starobrno.remoting.RPCManager;
 import org.jboss.starobrno.transaction.GlobalTransaction;
 import org.jboss.starobrno.transaction.TransactionTable;
 
@@ -176,7 +175,7 @@
     * From 2.1.0, Interceptor authors should obtain this by injection rather than this method.  See the
     * {@link org.jboss.cache.factories.annotations.Inject} annotation.
     *
-    * @return the current {@link org.jboss.cache.statetransfer.StateTransferManager}
+    * @return the current {@link org.jboss.starobrno.statetransfer.StateTransferManager}
     */
    StateTransferManager getStateTransferManager();
 

Added: core/branches/flat/src/main/java/org/jboss/starobrno/RPCManager.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/RPCManager.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/RPCManager.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -0,0 +1,135 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.starobrno;
+
+import org.jboss.starobrno.commands.ReplicableCommand;
+import org.jgroups.Address;
+import org.jgroups.Channel;
+import org.jgroups.blocks.RspFilter;
+
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * Provides a mechanism for communicating with other caches in the cluster.  For now this is based on JGroups as an underlying
+ * transport, and in future more transport options may become available.
+ * <p/>
+ * Implementations have a simple lifecycle:
+ * <ul>
+ * <li>start() - starts the underlying channel based on configuration options injected, and connects the channel</li>
+ * <li>disconnect() - disconnects the channel</li>
+ * <li>stop() - stops the dispatcher and releases resources</li>
+ * </ul>
+ *
+ * @author Manik Surtani
+ * @since 2.1.0
+ */
+public interface RPCManager
+{
+   /**
+    * Disconnects and closes the underlying JGroups channel.
+    */
+   void disconnect();
+
+   /**
+    * Stops the RPCDispatcher and frees resources.  Closes and disconnects the underlying JGroups channel if this is
+    * still open/connected.
+    */
+   void stop();
+
+   /**
+    * Starts the RPCManager by connecting the underlying JGroups channel (if configured for replication).  Connecting
+    * the channel may also involve state transfer (if configured) so the interceptor chain should be started and
+    * available before this method is called.
+    */
+   void start();
+
+   /**
+    * Invokes an RPC call on other caches in the cluster.
+    *
+    * @param recipients          a list of Addresses to invoke the call on.  If this is null, the call is broadcast to the entire cluster.
+    * @param cacheCommand        the cache command to invoke
+    * @param mode                the group request mode to use.  See {@link org.jgroups.blocks.GroupRequest}.
+    * @param timeout             a timeout after which to throw a replication exception.
+    * @param responseFilter      a response filter with which to filter out failed/unwanted/invalid responses.
+    * @param useOutOfBandMessage if true, the message is put on JGroups' OOB queue.  See JGroups docs for more info.
+    * @return a list of responses from each member contacted.
+    * @throws Exception in the event of problems.
+    */
+   List<Object> callRemoteMethods(Vector<Address> recipients, ReplicableCommand cacheCommand, int mode, long timeout, RspFilter responseFilter, boolean useOutOfBandMessage) throws Exception;
+
+   /**
+    * Invokes an RPC call on other caches in the cluster.
+    *
+    * @param recipients          a list of Addresses to invoke the call on.  If this is null, the call is broadcast to the entire cluster.
+    * @param cacheCommand        the cache command to invoke
+    * @param mode                the group request mode to use.  See {@link org.jgroups.blocks.GroupRequest}.
+    * @param timeout             a timeout after which to throw a replication exception.
+    * @param useOutOfBandMessage if true, the message is put on JGroups' OOB queue.  See JGroups docs for more info.
+    * @return a list of responses from each member contacted.
+    * @throws Exception in the event of problems.
+    */
+   List<Object> callRemoteMethods(Vector<Address> recipients, ReplicableCommand cacheCommand, int mode, long timeout, boolean useOutOfBandMessage) throws Exception;
+
+   /**
+    * Invokes an RPC call on other caches in the cluster.
+    *
+    * @param recipients          a list of Addresses to invoke the call on.  If this is null, the call is broadcast to the entire cluster.
+    * @param cacheCommand        the cache command to invoke
+    * @param synchronous         if true, sets group request mode to {@link org.jgroups.blocks.GroupRequest#GET_ALL}, and if false sets it to {@link org.jgroups.blocks.GroupRequest#GET_NONE}.
+    * @param timeout             a timeout after which to throw a replication exception.
+    * @param useOutOfBandMessage if true, the message is put on JGroups' OOB queue.  See JGroups docs for more info.
+    * @return a list of responses from each member contacted.
+    * @throws Exception in the event of problems.
+    */
+   List<Object> callRemoteMethods(Vector<Address> recipients, ReplicableCommand cacheCommand, boolean synchronous, long timeout, boolean useOutOfBandMessage) throws Exception;
+
+   /**
+    * @return true if the current Channel is the coordinator of the cluster.
+    */
+   boolean isCoordinator();
+
+   /**
+    * @return the Address of the current coordinator.
+    */
+   Address getCoordinator();
+
+   /**
+    * Retrieves the local JGroups channel's address
+    *
+    * @return an Address
+    */
+   Address getLocalAddress();
+
+   /**
+    * Returns a defensively copied list of  members in the current cluster view.
+    */
+   List<Address> getMembers();
+
+
+   /**
+    * Retrieves the Channel
+    *
+    * @return a channel
+    */
+   Channel getChannel();
+}
\ No newline at end of file

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java	2008-10-14 17:49:31 UTC (rev 6945)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/transaction/TransactionTable.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -24,12 +24,12 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.jboss.starobrno.CacheException;
+import org.jboss.starobrno.RPCManager;
 import org.jboss.starobrno.context.InvocationContext;
 import org.jboss.starobrno.context.TransactionContext;
 import org.jboss.starobrno.factories.annotations.Inject;
 import org.jboss.starobrno.factories.annotations.NonVolatile;
 import org.jboss.starobrno.factories.context.ContextFactory;
-import org.jboss.starobrno.remoting.RPCManager;
 import org.jgroups.Address;
 
 import javax.transaction.Status;

Copied: core/branches/flat/src/main/java/org/jboss/starobrno/util/FastCopyHashMap.java (from rev 6897, core/branches/flat/src/main/java/org/jboss/cache/util/FastCopyHashMap.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/util/FastCopyHashMap.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/util/FastCopyHashMap.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -0,0 +1,836 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.starobrno.util;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.AbstractCollection;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+
+/**
+ * A HashMap that is optimized for fast shallow copies.
+ *
+ * @author Jason T. Greene
+ */
+public class FastCopyHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Cloneable, Serializable
+{
+   /**
+    * Marks null keys.
+    */
+   private static final Object NULL = new Object();
+
+   /**
+    * Serialization ID
+    */
+   private static final long serialVersionUID = 10929568968762L;
+
+   /**
+    * Same default as HashMap, must be a power of 2
+    */
+   private static final int DEFAULT_CAPACITY = 8;
+
+   /**
+    * MAX_INT - 1
+    */
+   private static final int MAXIMUM_CAPACITY = 1 << 30;
+
+   /**
+    * 67%, just like IdentityHashMap
+    */
+   private static final float DEFAULT_LOAD_FACTOR = 0.67f;
+
+   /**
+    * The open-addressed table
+    */
+   private transient Entry<K, V>[] table;
+
+   /**
+    * The current number of key-value pairs
+    */
+   private transient int size;
+
+   /**
+    * The next resize
+    */
+   private transient int threshold;
+
+   /**
+    * The user defined load factor which defines when to resize
+    */
+   private final float loadFactor;
+
+   /**
+    * Counter used to detect changes made outside of an iterator
+    */
+   private transient int modCount;
+
+   // Cached views
+   private transient KeySet keySet;
+   private transient Values values;
+   private transient EntrySet entrySet;
+
+   public FastCopyHashMap(int initialCapacity, float loadFactor)
+   {
+      if (initialCapacity < 0)
+         throw new IllegalArgumentException("Can not have a negative size table!");
+
+      if (initialCapacity > MAXIMUM_CAPACITY)
+         initialCapacity = MAXIMUM_CAPACITY;
+
+      if (!(loadFactor > 0F && loadFactor <= 1F))
+         throw new IllegalArgumentException("Load factor must be greater than 0 and less than or equal to 1");
+
+      this.loadFactor = loadFactor;
+      init(initialCapacity, loadFactor);
+   }
+
+   @SuppressWarnings("unchecked")
+   public FastCopyHashMap(Map<? extends K, ? extends V> map)
+   {
+      if (map instanceof FastCopyHashMap)
+      {
+         FastCopyHashMap<? extends K, ? extends V> fast = (FastCopyHashMap<? extends K, ? extends V>) map;
+         this.table = (Entry<K, V>[]) fast.table.clone();
+         this.loadFactor = fast.loadFactor;
+         this.size = fast.size;
+         this.threshold = fast.threshold;
+      }
+      else
+      {
+         this.loadFactor = DEFAULT_LOAD_FACTOR;
+         init(map.size(), this.loadFactor);
+         putAll(map);
+      }
+   }
+
+   @SuppressWarnings("unchecked")
+   private void init(int initialCapacity, float loadFactor)
+   {
+      int c = 1;
+      for (; c < initialCapacity; c <<= 1) ;
+
+      this.table = (Entry<K, V>[]) new Entry[c];
+
+      threshold = (int) (c * loadFactor);
+   }
+
+   public FastCopyHashMap(int initialCapacity)
+   {
+      this(initialCapacity, DEFAULT_LOAD_FACTOR);
+   }
+
+   public FastCopyHashMap()
+   {
+      this(DEFAULT_CAPACITY);
+   }
+
+   // The normal bit spreader...
+   private static final int hash(Object key)
+   {
+      int h = key.hashCode();
+      h ^= (h >>> 20) ^ (h >>> 12);
+      return h ^ (h >>> 7) ^ (h >>> 4);
+   }
+
+   @SuppressWarnings("unchecked")
+   private static final <K> K maskNull(K key)
+   {
+      return key == null ? (K) NULL : key;
+   }
+
+   private static final <K> K unmaskNull(K key)
+   {
+      return key == NULL ? null : key;
+   }
+
+   private int nextIndex(int index, int length)
+   {
+      index = (index >= length - 1) ? 0 : index + 1;
+      return index;
+   }
+
+   private static final boolean eq(Object o1, Object o2)
+   {
+      return o1 == o2 || (o1 != null && o1.equals(o2));
+   }
+
+   private static final int index(int hashCode, int length)
+   {
+      return hashCode & (length - 1);
+   }
+
+   public int size()
+   {
+      return size;
+   }
+
+   public boolean isEmpty()
+   {
+      return size == 0;
+   }
+
+   public V get(Object key)
+   {
+      key = maskNull(key);
+
+      int hash = hash(key);
+      int length = table.length;
+      int index = index(hash, length);
+
+      for (; ;)
+      {
+         Entry<K, V> e = table[index];
+         if (e == null)
+            return null;
+
+         if (e.hash == hash && eq(key, e.key))
+            return e.value;
+
+         index = nextIndex(index, length);
+      }
+   }
+
+   public boolean containsKey(Object key)
+   {
+      key = maskNull(key);
+
+      int hash = hash(key);
+      int length = table.length;
+      int index = index(hash, length);
+
+      for (; ;)
+      {
+         Entry<K, V> e = table[index];
+         if (e == null)
+            return false;
+
+         if (e.hash == hash && eq(key, e.key))
+            return true;
+
+         index = nextIndex(index, length);
+      }
+   }
+
+   public boolean containsValue(Object value)
+   {
+      for (Entry<K, V> e : table)
+         if (e != null && eq(value, e.value))
+            return true;
+
+      return false;
+   }
+
+   public V put(K key, V value)
+   {
+      key = maskNull(key);
+
+      Entry<K, V>[] table = this.table;
+      int hash = hash(key);
+      int length = table.length;
+      int start = index(hash, length);
+      int index = start;
+
+
+      for (; ;)
+      {
+         Entry<K, V> e = table[index];
+         if (e == null)
+            break;
+
+         if (e.hash == hash && eq(key, e.key))
+         {
+            table[index] = new Entry<K, V>(e.key, e.hash, value);
+            return e.value;
+         }
+
+         index = nextIndex(index, length);
+         if (index == start)
+            throw new IllegalStateException("Table is full!");
+      }
+
+      modCount++;
+      table[index] = new Entry<K, V>(key, hash, value);
+      if (++size >= threshold)
+         resize(length);
+
+      return null;
+   }
+
+
+   @SuppressWarnings("unchecked")
+   private void resize(int from)
+   {
+      int newLength = from << 1;
+
+      // Can't get any bigger
+      if (newLength > MAXIMUM_CAPACITY || newLength <= from)
+         return;
+
+      Entry<K, V>[] newTable = new Entry[newLength];
+      Entry<K, V>[] old = table;
+
+      for (Entry<K, V> e : old)
+      {
+         if (e == null)
+            continue;
+
+         int index = index(e.hash, newLength);
+         while (newTable[index] != null)
+            index = nextIndex(index, newLength);
+
+         newTable[index] = e;
+      }
+
+      threshold = (int) (loadFactor * newLength);
+      table = newTable;
+   }
+
+   public void putAll(Map<? extends K, ? extends V> map)
+   {
+      int size = map.size();
+      if (size == 0)
+         return;
+
+      if (size > threshold)
+      {
+         if (size > MAXIMUM_CAPACITY)
+            size = MAXIMUM_CAPACITY;
+
+         int length = table.length;
+         for (; length < size; length <<= 1) ;
+
+         resize(length);
+      }
+
+      for (Map.Entry<? extends K, ? extends V> e : map.entrySet())
+         put(e.getKey(), e.getValue());
+   }
+
+   public V remove(Object key)
+   {
+      key = maskNull(key);
+
+      Entry<K, V>[] table = this.table;
+      int length = table.length;
+      int hash = hash(key);
+      int start = index(hash, length);
+
+      for (int index = start; ;)
+      {
+         Entry<K, V> e = table[index];
+         if (e == null)
+            return null;
+
+         if (e.hash == hash && eq(key, e.key))
+         {
+            table[index] = null;
+            relocate(index);
+            modCount++;
+            size--;
+            return e.value;
+         }
+
+         index = nextIndex(index, length);
+         if (index == start)
+            return null;
+      }
+
+
+   }
+
+   private void relocate(int start)
+   {
+      Entry<K, V>[] table = this.table;
+      int length = table.length;
+      int current = nextIndex(start, length);
+
+      for (; ;)
+      {
+         Entry<K, V> e = table[current];
+         if (e == null)
+            return;
+
+         // A Doug Lea variant of Knuth's Section 6.4 Algorithm R.
+         // This provides a non-recursive method of relocating
+         // entries to their optimal positions once a gap is created.
+         int prefer = index(e.hash, length);
+         if ((current < prefer && (prefer <= start || start <= current))
+               || (prefer <= start && start <= current))
+         {
+            table[start] = e;
+            table[current] = null;
+            start = current;
+         }
+
+         current = nextIndex(current, length);
+      }
+   }
+
+   public void clear()
+   {
+      modCount++;
+      Entry<K, V>[] table = this.table;
+      for (int i = 0; i < table.length; i++)
+         table[i] = null;
+
+      size = 0;
+   }
+
+   @SuppressWarnings("unchecked")
+   public Object clone()
+   {
+      try
+      {
+         FastCopyHashMap<K, V> clone = (FastCopyHashMap<K, V>) super.clone();
+         clone.table = table.clone();
+         clone.entrySet = null;
+         clone.values = null;
+         clone.keySet = null;
+         return clone;
+      }
+      catch (CloneNotSupportedException e)
+      {
+         // should never happen
+         throw new IllegalStateException(e);
+      }
+   }
+
+   public void printDebugStats()
+   {
+      int optimal = 0;
+      int total = 0;
+      int totalSkew = 0;
+      int maxSkew = 0;
+      for (int i = 0; i < table.length; i++)
+      {
+         Entry<K, V> e = table[i];
+         if (e != null)
+         {
+
+            total++;
+            int target = index(e.hash, table.length);
+            if (i == target)
+               optimal++;
+            else
+            {
+               int skew = Math.abs(i - target);
+               if (skew > maxSkew) maxSkew = skew;
+               totalSkew += skew;
+            }
+
+         }
+      }
+
+      System.out.println(" Size:            " + size);
+      System.out.println(" Real Size:       " + total);
+      System.out.println(" Optimal:         " + optimal + " (" + (float) optimal * 100 / total + "%)");
+      System.out.println(" Average Distnce: " + ((float) totalSkew / (total - optimal)));
+      System.out.println(" Max Distance:    " + maxSkew);
+   }
+
+   public Set<Map.Entry<K, V>> entrySet()
+   {
+      if (entrySet == null)
+         entrySet = new EntrySet();
+
+      return entrySet;
+   }
+
+   public Set<K> keySet()
+   {
+      if (keySet == null)
+         keySet = new KeySet();
+
+      return keySet;
+   }
+
+   public Collection<V> values()
+   {
+      if (values == null)
+         values = new Values();
+
+      return values;
+   }
+
+   @SuppressWarnings("unchecked")
+   private void readObject(java.io.ObjectInputStream s) throws IOException, ClassNotFoundException
+   {
+      s.defaultReadObject();
+
+      int size = s.readInt();
+
+      init(size, loadFactor);
+
+      for (int i = 0; i < size; i++)
+      {
+         K key = (K) s.readObject();
+         V value = (V) s.readObject();
+         putForCreate(key, value);
+      }
+   }
+
+   @SuppressWarnings("unchecked")
+   private void putForCreate(K key, V value)
+   {
+      key = maskNull(key);
+
+      Entry<K, V>[] table = this.table;
+      int hash = hash(key);
+      int length = table.length;
+      int index = index(hash, length);
+
+      Entry<K, V> e = table[index];
+      while (e != null)
+      {
+         index = nextIndex(index, length);
+         e = table[index];
+      }
+
+      table[index] = new Entry<K, V>(key, hash, value);
+   }
+
+   private void writeObject(java.io.ObjectOutputStream s) throws IOException
+   {
+      s.defaultWriteObject();
+      s.writeInt(size);
+
+      for (Entry<K, V> e : table)
+      {
+         if (e != null)
+         {
+            s.writeObject(unmaskNull(e.key));
+            s.writeObject(e.value);
+         }
+      }
+   }
+
+   private static final class Entry<K, V>
+   {
+      final K key;
+      final int hash;
+      final V value;
+
+      Entry(K key, int hash, V value)
+      {
+         this.key = key;
+         this.hash = hash;
+         this.value = value;
+      }
+   }
+
+   private abstract class FasyCopyHashMapIterator<E> implements Iterator<E>
+   {
+      private int next = 0;
+      private int expectedCount = modCount;
+      private int current = -1;
+      private boolean hasNext;
+      Entry<K, V> table[] = FastCopyHashMap.this.table;
+
+      public boolean hasNext()
+      {
+         if (hasNext == true)
+            return true;
+
+         Entry<K, V> table[] = this.table;
+         for (int i = next; i < table.length; i++)
+         {
+            if (table[i] != null)
+            {
+               next = i;
+               return hasNext = true;
+            }
+         }
+
+         next = table.length;
+         return false;
+      }
+
+      protected Entry<K, V> nextEntry()
+      {
+         if (modCount != expectedCount)
+            throw new ConcurrentModificationException();
+
+         if (!hasNext && !hasNext())
+            throw new NoSuchElementException();
+
+         current = next++;
+         hasNext = false;
+
+         return table[current];
+      }
+
+      @SuppressWarnings("unchecked")
+      public void remove()
+      {
+         if (modCount != expectedCount)
+            throw new ConcurrentModificationException();
+
+         int current = this.current;
+         int delete = current;
+
+         if (current == -1)
+            throw new IllegalStateException();
+
+         // Invalidate current (prevents multiple remove)
+         this.current = -1;
+
+         // Start were we relocate
+         next = delete;
+
+         Entry<K, V>[] table = this.table;
+         if (table != FastCopyHashMap.this.table)
+         {
+            FastCopyHashMap.this.remove(table[delete].key);
+            table[delete] = null;
+            expectedCount = modCount;
+            return;
+         }
+
+
+         int length = table.length;
+         int i = delete;
+
+         table[delete] = null;
+         size--;
+
+         for (; ;)
+         {
+            i = nextIndex(i, length);
+            Entry<K, V> e = table[i];
+            if (e == null)
+               break;
+
+            int prefer = index(e.hash, length);
+            if ((i < prefer && (prefer <= delete || delete <= i))
+                  || (prefer <= delete && delete <= i))
+            {
+               // Snapshot the unseen portion of the table if we have
+               // to relocate an entry that was already seen by this iterator
+               if (i < current && current <= delete && table == FastCopyHashMap.this.table)
+               {
+                  int remaining = length - current;
+                  Entry<K, V>[] newTable = (Entry<K, V>[]) new Entry[remaining];
+                  System.arraycopy(table, current, newTable, 0, remaining);
+
+                  // Replace iterator's table.
+                  // Leave table local var pointing to the real table
+                  this.table = newTable;
+                  next = 0;
+               }
+
+               // Do the swap on the real table
+               table[delete] = e;
+               table[i] = null;
+               delete = i;
+            }
+         }
+      }
+   }
+
+
+   private class KeyIterator extends FasyCopyHashMapIterator<K>
+   {
+      public K next()
+      {
+         return unmaskNull(nextEntry().key);
+      }
+   }
+
+   private class ValueIterator extends FasyCopyHashMapIterator<V>
+   {
+      public V next()
+      {
+         return nextEntry().value;
+      }
+   }
+
+   private class EntryIterator extends FasyCopyHashMapIterator<Map.Entry<K, V>>
+   {
+      private class WriteThroughEntry extends SimpleEntry<K, V>
+      {
+         WriteThroughEntry(K key, V value)
+         {
+            super(key, value);
+         }
+
+         public V setValue(V value)
+         {
+            if (table != FastCopyHashMap.this.table)
+               FastCopyHashMap.this.put(getKey(), value);
+
+            return super.setValue(value);
+         }
+      }
+
+      public Map.Entry<K, V> next()
+      {
+         Entry<K, V> e = nextEntry();
+         return new WriteThroughEntry(unmaskNull(e.key), e.value);
+      }
+
+   }
+
+   private class KeySet extends AbstractSet<K>
+   {
+      public Iterator<K> iterator()
+      {
+         return new KeyIterator();
+      }
+
+      public void clear()
+      {
+         FastCopyHashMap.this.clear();
+      }
+
+      public boolean contains(Object o)
+      {
+         return containsKey(o);
+      }
+
+      public boolean remove(Object o)
+      {
+         int size = size();
+         FastCopyHashMap.this.remove(o);
+         return size() < size;
+      }
+
+      public int size()
+      {
+         return FastCopyHashMap.this.size();
+      }
+   }
+
+   private class Values extends AbstractCollection<V>
+   {
+      public Iterator<V> iterator()
+      {
+         return new ValueIterator();
+      }
+
+      public void clear()
+      {
+         FastCopyHashMap.this.clear();
+      }
+
+      public int size()
+      {
+         return FastCopyHashMap.this.size();
+      }
+   }
+
+   private class EntrySet extends AbstractSet<Map.Entry<K, V>>
+   {
+      public Iterator<Map.Entry<K, V>> iterator()
+      {
+         return new EntryIterator();
+      }
+
+      public boolean contains(Object o)
+      {
+         if (!(o instanceof Map.Entry))
+            return false;
+
+         Map.Entry<?, ?> entry = (Map.Entry<?, ?>) o;
+         Object value = get(entry.getKey());
+         return eq(entry.getValue(), value);
+      }
+
+      public void clear()
+      {
+         FastCopyHashMap.this.clear();
+      }
+
+      public boolean isEmpty()
+      {
+         return FastCopyHashMap.this.isEmpty();
+      }
+
+      public int size()
+      {
+         return FastCopyHashMap.this.size();
+      }
+   }
+
+   protected static class SimpleEntry<K, V> implements Map.Entry<K, V>
+   {
+      private K key;
+      private V value;
+
+      SimpleEntry(K key, V value)
+      {
+         this.key = key;
+         this.value = value;
+      }
+
+      SimpleEntry(Map.Entry<K, V> entry)
+      {
+         this.key = entry.getKey();
+         this.value = entry.getValue();
+      }
+
+      public K getKey()
+      {
+         return key;
+      }
+
+      public V getValue()
+      {
+         return value;
+      }
+
+      public V setValue(V value)
+      {
+         V old = this.value;
+         this.value = value;
+         return old;
+      }
+
+      public boolean equals(Object o)
+      {
+         if (this == o)
+            return true;
+
+         if (!(o instanceof Map.Entry))
+            return false;
+         Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
+         return eq(key, e.getKey()) && eq(value, e.getValue());
+      }
+
+      public int hashCode()
+      {
+         return hash(key) ^
+               (value == null ? 0 : hash(value));
+      }
+
+      public String toString()
+      {
+         return getKey() + "=" + getValue();
+      }
+   }
+}

Copied: core/branches/flat/src/main/java/org/jboss/starobrno/util/Immutables.java (from rev 6897, core/branches/flat/src/main/java/org/jboss/cache/util/Immutables.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/util/Immutables.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/util/Immutables.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -0,0 +1,586 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.starobrno.util;
+
+import org.jboss.starobrno.util.FastCopyHashMap;
+import org.jboss.cache.util.ImmutableListCopy;
+
+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.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+/**
+ * Factory for generating immutable type wrappers.
+ *
+ * @author Jason T. Greene
+ */
+public class Immutables
+{
+   /**
+    * Whether or not this collection type is immutable
+    *
+    * @param o 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 = attemptKnownSetCopy(set);
+      if (copy == null)
+         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 = attemptKnownMapCopy(map);
+
+      if (copy == null)
+         attemptClone(map);
+      if (copy == null)
+         copy = attemptCopyConstructor(map, Map.class);
+      if (copy == null)
+         copy = new HashMap<K, V>(map);
+
+      return new ImmutableMapWrapper<K, V>(copy);
+   }
+
+   /**
+    * 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 = attemptKnownSetCopy(collection);
+      if (copy == null)
+         copy = attemptClone(collection);
+      if (copy == null)
+         copy = attemptCopyConstructor(collection, Collection.class);
+      if (copy == null)
+         copy = new ArrayList<T>(collection);
+
+      return new ImmutableCollectionWrapper<T>(copy);
+   }
+
+   @SuppressWarnings("unchecked")
+   private static <T extends Map> T attemptKnownMapCopy(T map)
+   {
+      if (map instanceof FastCopyHashMap)
+         return (T) ((FastCopyHashMap) map).clone();
+      if (map instanceof HashMap)
+         return (T) ((HashMap) map).clone();
+      if (map instanceof LinkedHashMap)
+         return (T) ((LinkedHashMap) map).clone();
+      if (map instanceof TreeMap)
+         return (T) ((TreeMap) map).clone();
+
+      return null;
+   }
+
+   @SuppressWarnings("unchecked")
+   private static <T extends Collection> T attemptKnownSetCopy(T set)
+   {
+      if (set instanceof HashSet)
+         return (T) ((HashSet) set).clone();
+      if (set instanceof LinkedHashSet)
+         return (T) ((LinkedHashSet) set).clone();
+      if (set instanceof TreeSet)
+         return (T) ((TreeSet) set).clone();
+
+      return null;
+   }
+
+   @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 Entry<K, V>
+   {
+      private K key;
+      private V value;
+      private int hash;
+
+      ImmutableEntry(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 Entry))
+            return false;
+
+         Entry<K, V> entry = (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<Entry<K, V>>
+   {
+      private static final long serialVersionUID = 6378667653889667692L;
+
+      @SuppressWarnings("unchecked")
+      public ImmutableEntrySetWrapper(Set<? extends 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 (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 (Entry<K, V> entry : this)
+            result[i++] = entry;
+
+         return array;
+      }
+
+      public Iterator<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());
+      }
+
+      public String toString()
+      {
+         return map.toString();
+      }
+   }
+}
\ No newline at end of file

Copied: core/branches/flat/src/main/java/org/jboss/starobrno/util/ReflectionUtil.java (from rev 6897, core/branches/flat/src/main/java/org/jboss/cache/util/reflect/ReflectionUtil.java)
===================================================================
--- core/branches/flat/src/main/java/org/jboss/starobrno/util/ReflectionUtil.java	                        (rev 0)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/util/ReflectionUtil.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -0,0 +1,153 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2000 - 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file 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.starobrno.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.jboss.starobrno.CacheException;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Basic reflection utilities to enhance what the JDK provides.
+ *
+ * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
+ * @since 2.1.0
+ */
+public class ReflectionUtil
+{
+   private static final Log log = LogFactory.getLog(ReflectionUtil.class);
+
+   /**
+    * Returns a set of Methods that contain the given method annotation.  This includes all public, protected, package and private
+    * methods, as well as those of superclasses.  Note that this does *not* include overridden methods.
+    *
+    * @param c              class to inspect
+    * @param annotationType the type of annotation to look for
+    * @return List of Method objects that require injection.
+    */
+   public static List<Method> getAllMethods(Class c, Class<? extends Annotation> annotationType)
+   {
+      List<Method> annotated = new LinkedList<Method>();
+      inspectRecursively(c, annotated, annotationType);
+      return annotated;
+   }
+
+   /**
+    * Inspects a class and its superclasses (all the way to {@link Object} for method instances that contain a given annotation.
+    * This even identifies private, package and protected methods, not just public ones.
+    *
+    * @param c
+    * @param s
+    * @param annotationType
+    */
+   private static void inspectRecursively(Class c, List<Method> s, Class<? extends Annotation> annotationType)
+   {
+      // Superclass first
+      if (!c.equals(Object.class)) inspectRecursively(c.getSuperclass(), s, annotationType);
+
+      for (Method m : c.getDeclaredMethods())
+      {
+         // don't bother if this method has already been overridden by a subclass
+         if (!alreadyFound(m, s) && m.isAnnotationPresent(annotationType))
+         {
+            s.add(m);
+         }
+      }
+   }
+
+   /**
+    * Tests whether a method has already been found, i.e., overridden.
+    *
+    * @param m method to inspect
+    * @param s collection of methods found
+    * @return true a method with the same signature already exists.
+    */
+   private static boolean alreadyFound(Method m, Collection<Method> s)
+   {
+      for (Method found : s)
+      {
+         if (m.getName().equals(found.getName()) &&
+               Arrays.equals(m.getParameterTypes(), found.getParameterTypes()))
+            return true;
+      }
+      return false;
+   }
+
+   public static void setValue(Object instance, String fieldName, Object value)
+   {
+      try
+      {
+         Field f = findFieldRecursively(instance.getClass(), fieldName);
+         if (f == null)
+            throw new NoSuchMethodException("Cannot find field " + fieldName + " on " + instance.getClass() + " or superclasses");
+         f.setAccessible(true);
+         f.set(instance, value);
+      }
+      catch (Exception e)
+      {
+         log.error("Unable to set value!", e);
+      }
+   }
+
+   private static Field findFieldRecursively(Class c, String fieldName)
+   {
+      Field f = null;
+      try
+      {
+         f = c.getDeclaredField(fieldName);
+      }
+      catch (NoSuchFieldException e)
+      {
+         if (!c.equals(Object.class)) f = findFieldRecursively(c.getSuperclass(), fieldName);
+      }
+      return f;
+   }
+
+   /**
+    * Invokes a method using reflection, in an accessible manner (by using {@link Method#setAccessible(boolean)}
+    *
+    * @param instance   instance on which to execute the method
+    * @param method     method to execute
+    * @param parameters parameters
+    */
+   public static void invokeAccessibly(Object instance, Method method, Object[] parameters)
+   {
+      try
+      {
+         method.setAccessible(true);
+         method.invoke(instance, parameters);
+      }
+      catch (Exception e)
+      {
+         throw new CacheException("Unable to invoke method " + method + " on object " + //instance +
+               (parameters != null ? " with parameters " + Arrays.asList(parameters) : ""), e);
+      }
+   }
+
+}

Copied: core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks (from rev 6897, core/branches/flat/src/main/java/org/jboss/cache/util/concurrent/locks)

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/LockContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/cache/util/concurrent/locks/LockContainer.java	2008-10-09 13:22:09 UTC (rev 6897)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/LockContainer.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -19,7 +19,7 @@
  * 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.concurrent.locks;
+package org.jboss.starobrno.util.concurrent.locks;
 
 import net.jcip.annotations.ThreadSafe;
 

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/OwnableReentrantLock.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLock.java	2008-10-09 13:22:09 UTC (rev 6897)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/OwnableReentrantLock.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -19,7 +19,7 @@
  * 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.concurrent.locks;
+package org.jboss.starobrno.util.concurrent.locks;
 
 import net.jcip.annotations.ThreadSafe;
 import org.jboss.starobrno.invocation.InvocationContextContainer;

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/OwnableReentrantLockContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/cache/util/concurrent/locks/OwnableReentrantLockContainer.java	2008-10-09 13:22:09 UTC (rev 6897)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/OwnableReentrantLockContainer.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -19,7 +19,7 @@
  * 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.concurrent.locks;
+package org.jboss.starobrno.util.concurrent.locks;
 
 import net.jcip.annotations.ThreadSafe;
 import org.jboss.starobrno.invocation.InvocationContextContainer;
@@ -27,11 +27,11 @@
 import java.util.Arrays;
 
 /**
- * A LockContainer that holds {@link org.jboss.cache.util.concurrent.locks.OwnableReentrantLock}s.
+ * A LockContainer that holds {@link org.jboss.starobrno.util.concurrent.locks.OwnableReentrantLock}s.
  *
  * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
- * @see org.jboss.cache.util.concurrent.locks.ReentrantLockContainer
- * @see org.jboss.cache.util.concurrent.locks.OwnableReentrantLock
+ * @see org.jboss.starobrno.util.concurrent.locks.ReentrantLockContainer
+ * @see org.jboss.starobrno.util.concurrent.locks.OwnableReentrantLock
  * @since 3.0
  */
 @ThreadSafe

Modified: core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/ReentrantLockContainer.java
===================================================================
--- core/branches/flat/src/main/java/org/jboss/cache/util/concurrent/locks/ReentrantLockContainer.java	2008-10-09 13:22:09 UTC (rev 6897)
+++ core/branches/flat/src/main/java/org/jboss/starobrno/util/concurrent/locks/ReentrantLockContainer.java	2008-10-14 17:50:03 UTC (rev 6946)
@@ -19,7 +19,7 @@
  * 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.concurrent.locks;
+package org.jboss.starobrno.util.concurrent.locks;
 
 import net.jcip.annotations.ThreadSafe;
 
@@ -30,7 +30,7 @@
  * A LockContainer that holds ReentrantLocks
  *
  * @author Manik Surtani (<a href="mailto:manik at jboss.org">manik at jboss.org</a>)
- * @see org.jboss.cache.util.concurrent.locks.OwnableReentrantLockContainer
+ * @see org.jboss.starobrno.util.concurrent.locks.OwnableReentrantLockContainer
  * @since 3.0
  */
 @ThreadSafe




More information about the jbosscache-commits mailing list