[jboss-svn-commits] JBoss Common SVN: r4164 - in invokablecontainer/trunk: api/src/main/java/org/jboss and 1 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Wed Mar 10 21:57:03 EST 2010


Author: david.lloyd at jboss.com
Date: 2010-03-10 21:57:03 -0500 (Wed, 10 Mar 2010)
New Revision: 4164

Added:
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationContext.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationException.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationPermission.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java
   invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java
Removed:
   invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/
   invokablecontainer/trunk/core/
   invokablecontainer/trunk/spi/
Modified:
   invokablecontainer/trunk/pom.xml
Log:
Mutilate ALR's nice Invocation API, see if he gets mad

Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/FastCopyHashMap.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,855 @@
+/*
+ * 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.invokable;
+
+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. If the copy-ctor is
+ * passed another FastCopyHashMap, or clone is called on this map, the shallow
+ * copy can be performed using little more than a single array copy. In order to
+ * accomplish this, immutable objects must be used internally, so update
+ * operations result in slightly more object churn than <code>HashMap</code>.
+ *
+ * Note: It is very important to use a smaller load factor than you normally
+ * would for HashMap, since the implementation is open-addressed with linear
+ * probing. With a 50% load-factor a get is expected to return in only 2 probes.
+ * However, a 90% load-factor is expected to return in around 50 probes.
+ *
+ * @author Jason T. Greene
+ */
+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) ;
+      threshold = (int) (c * loadFactor);
+
+      // Include the load factor when sizing the table for the first time
+      if (initialCapacity > threshold && c < MAXIMUM_CAPACITY)
+      {
+         c <<= 1;
+         threshold = (int) (c * loadFactor);
+      }
+
+      this.table = (Entry<K, V>[]) new Entry[c];
+   }
+
+   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 (int start = index; ;)
+      {
+         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);
+         if (index == start) // Full table
+            return null;
+      }
+   }
+
+   public boolean containsKey(Object key)
+   {
+      key = maskNull(key);
+
+      int hash = hash(key);
+      int length = table.length;
+      int index = index(hash, length);
+
+      for (int start = index; ;)
+      {
+         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);
+         if (index == start) // Full table
+            return false;
+      }
+   }
+
+   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 index = index(hash, length);
+
+      for (int start = index; ;)
+      {
+         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 FastCopyHashMap<K, V> 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);
+      }
+
+      this.size = size;
+   }
+
+   @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 (key == null ? 0 : hash(key)) ^
+                (value == null ? 0 : hash(value));
+      }
+
+      public String toString()
+      {
+         return getKey() + "=" + getValue();
+      }
+   }
+}

Copied: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java (from rev 4153, invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/Invocation.java)
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/Invocation.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,220 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.invokable;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Arrays;
+
+/**
+ * A unified view of a {@link Method} invocation.  Composes the target method, arguments, and mapped context into a single
+ * entity.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ * @version $Revision: $
+ */
+public final class Invocation implements Serializable {
+
+    private static final long serialVersionUID = 2691631710015102611L;
+    private static final Field targetMethodField;
+
+    private final Object[] args;
+
+    @SuppressWarnings({ "InstanceVariableMayNotBeInitializedByReadObject" })
+    private transient final Method targetMethod;
+    private volatile InvocationContext context;
+
+    /**
+     * Construct a new instance.
+     *
+     * @param context
+     * @param targetMethod
+     * @param args
+     */
+    public Invocation(final InvocationContext context, final Method targetMethod, final Object... args) {
+        if (targetMethod == null) {
+            throw new IllegalArgumentException("targetMethod is null");
+        }
+        if (args == null) {
+            throw new IllegalArgumentException("args is null");
+        }
+        if (context == null) {
+            throw new IllegalArgumentException("context is null");
+        }
+        this.targetMethod = targetMethod;
+        this.args = args;
+        this.context = context;
+    }
+
+    public Invocation(final Method method, final Object... args) {
+        this(InvocationContext.EMPTY, method, args);
+    }
+
+    static {
+        targetMethodField = AccessController.doPrivileged(new PrivilegedAction<Field>() {
+            public Field run() {
+                try {
+                    final Field field = Invocation.class.getDeclaredField("targetMethod");
+                    field.setAccessible(true);
+                    return field;
+                } catch (NoSuchFieldException e) {
+                    throw new IllegalStateException(e);
+                }
+            }
+        });
+    }
+
+    //-------------------------------------------------------------------------------------||
+    // Contracts --------------------------------------------------------------------------||
+    //-------------------------------------------------------------------------------------||
+
+    /**
+     * Obtains the target method requested of the invocation.
+     *
+     * @return the target method
+     */
+    public Method getTargetMethod() {
+        return targetMethod;
+    }
+
+    /**
+     * Returns the arguments to be passed along to this method invocation
+     *
+     * @return the method call arguments
+     */
+    public Object[] getArgs() {
+        return args;
+    }
+
+    /**
+     * Get the invocation context, which may be used to get information about this invocation.  It may also be used
+     * to create a new, derived invocation context by way of the {@link InvocationContext#builder()} method.
+     *
+     * @return the current invocation context
+     */
+    public InvocationContext getContext() {
+        return context;
+    }
+
+    /**
+     * Replace this invocation's {@code InvocationContext}.
+     *
+     * @param context the new invocation context
+     */
+    public void setContext(final InvocationContext context) {
+        this.context = context;
+    }
+
+    //-------------------------------------------------------------------------------------||
+    // Serialization ----------------------------------------------------------------------||
+    //-------------------------------------------------------------------------------------||
+
+    /**
+     * Serializes the invocation with a custom form
+     *
+     * @serialData After all non-transient fields are written, we pipe out the target method's declaring class, method
+     * name, and array of parameter types.  These are used to reconstitute the target Method, which is not itself
+     * Serializable
+     */
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        // Default write of non-transient fields
+        out.defaultWriteObject();
+        // Write out the target method by decomposing it into Serializable parts
+        final Method targetMethod = this.targetMethod;
+        final Class<?> declaringClass = targetMethod.getDeclaringClass();
+        final String name = targetMethod.getName();
+        final Class<?>[] paramTypes = targetMethod.getParameterTypes();
+        out.writeObject(declaringClass);
+        out.writeObject(name);
+        out.writeObject(paramTypes);
+        // See if the invocation context is empty
+        final InvocationContext contextToWrite = context;
+        if (context.isEmpty()) {
+            // Null out; we don't need to send empty properties.  On deserialization
+            // we'll just re-instantiate.
+            out.writeObject(null);
+        } else {
+            // Write invocation context
+            out.writeObject(contextToWrite);
+        }
+    }
+
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        // Get default form
+        in.defaultReadObject();
+        // Assert invariants
+        if (getArgs() == null) {
+            throw new IllegalArgumentException("Deserialization resulted in null arguments to the target method");
+        }
+        // Reconstruct the Method by getting the declaring class, method name, and signature
+        final Class<?> declaringClass = (Class<?>) in.readObject();
+        final String methodName = (String) in.readObject();
+        final Class<?>[] paramTypes = (Class<?>[]) in.readObject();
+        // Some more assertions
+        if (declaringClass == null) {
+            throw new InvalidObjectException("Declaring class was not read in during deserialization");
+        }
+        if (methodName == null) {
+            throw new InvalidObjectException("Target method name was not read in during deserialization");
+        }
+        if (paramTypes == null) {
+            throw new InvalidObjectException(
+                    "Parameter types of the target method were not read in during deserialization");
+        }
+        // Obtain the target method
+        final Method targetMethod;
+        try {
+            targetMethod = declaringClass.getMethod(methodName, paramTypes);
+        } catch (final NoSuchMethodException nsme) {
+            throw new InvalidObjectException("Could not deserialize; no target method \"" + methodName + "\" found in "
+                    + declaringClass.getName() + " with param types " + Arrays.asList(paramTypes));
+        }
+        // Set the target method
+        setTargetMethod(targetMethod);
+        // Set the InvocationContext
+        final InvocationContext context = (InvocationContext) in.readObject();
+        // If no context is provided
+        if (context == null) {
+            // Replace with a new instance; this signals empty properties were present when the instance
+            // was serialized
+            this.context = InvocationContext.EMPTY;
+        } else {
+            this.context = context;
+        }
+    }
+
+    private void setTargetMethod(Method method) {
+        try {
+            targetMethodField.set(this, method);
+        } catch (IllegalAccessException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+}

Copied: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationContext.java (from rev 4153, invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/InvocationContext.java)
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationContext.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationContext.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,226 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.invokable;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * An immutable collection of contextual properties which may be associated with an {@link Invocation}.  To construct
+ * instances, use the {@link Builder} interface by way of the {@link InvocationContext#builder()} method.  An empty
+ * context instance is available at {@link InvocationContext#EMPTY}.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @author <a href="mailto:david.lloyd at redhat.com">David M. Lloyd</a>
+ * @version $Revision: $
+ */
+public final class InvocationContext implements Serializable {
+
+    private static final long serialVersionUID = -8786118177256759054L;
+
+    private transient final Map<Object, Object> backingMap;
+
+    private InvocationContext(final Map<Object, Object> backingMap) {
+        this.backingMap = backingMap;
+    }
+
+    //-------------------------------------------------------------------------------------||
+    // Contracts --------------------------------------------------------------------------||
+    //-------------------------------------------------------------------------------------||
+
+    /**
+     * Obtains the context property associated with the specified key, or null if not found
+     *
+     * @param key
+     *
+     * @return The value under the specified key, or null if not found
+     *
+     * @throws IllegalArgumentException If the key is not specified
+     */
+    public Object getProperty(Object key) throws IllegalArgumentException {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null");
+        }
+        return backingMap.get(key);
+    }
+
+    /**
+     * Obtains the context property associated with the specified key, or null if not found
+     *
+     * @param <T> Type of the object to be returned
+     * @param key
+     * @param expectedType Expected type of the object to be returned
+     *
+     * @return The value under the specified key, or null if not found
+     *
+     * @throws IllegalArgumentException If the key is not specified
+     * @throws ClassCastException If the expected type is not the correct type for the object under the specified key
+     */
+    public <T> T getProperty(Object key, Class<T> expectedType) throws IllegalArgumentException, ClassCastException {
+        if (key == null) {
+            throw new IllegalArgumentException("key is null");
+        }
+        if (expectedType == null) {
+            throw new IllegalArgumentException("expectedType is null");
+        }
+        return expectedType.cast(backingMap.get(key));
+    }
+
+    /**
+     * Determines whether the context properties are empty (ie. none exist)
+     *
+     * @return {@code true} if the map is empty, {@code false} otherwise
+     */
+    public boolean isEmpty() {
+        return backingMap.isEmpty();
+    }
+
+    /**
+     * Get a builder which is prepopulated with the values from this context.
+     *
+     * @return a new builder
+     */
+    public Builder builder() {
+        return new BuilderImpl(backingMap);
+    }
+
+    /**
+     * Replace this instance with a serializable proxy.
+     *
+     * @return the replacement
+     */
+    protected Object writeReplace() {
+        return new Serialized(backingMap);
+    }
+
+    /**
+     * An empty invocation context.
+     */
+    public static final InvocationContext EMPTY = new InvocationContext(Collections.emptyMap());
+
+    /**
+     * A builder for invocation contexts.
+     */
+    public interface Builder {
+
+        /**
+         * Add or replace a property.
+         *
+         * @param key the property key
+         * @param value the new value
+         * @throws IllegalArgumentException if either the key or the value is {@code null}
+         */
+        void setProperty(Object key, Object value) throws IllegalArgumentException;
+
+        /**
+         * Remove a property, if it is present.
+         *
+         * @param key the property to remove
+         */
+        void removeProperty(Object key);
+
+        /**
+         * Create an invocation context from the current state of this builder.
+         *
+         * @return a new invocation context
+         */
+        InvocationContext create();
+    }
+
+    static final class BuilderImpl implements Builder {
+        private final FastCopyHashMap<Object, Object> map;
+
+        BuilderImpl(final Map<Object, Object> map) {
+            this.map = new FastCopyHashMap<Object, Object>(map);
+        }
+
+        public void setProperty(final Object key, final Object value) throws IllegalArgumentException {
+            if (key == null) {
+                throw new IllegalArgumentException("key is null");
+            }
+            if (value == null) {
+                throw new IllegalArgumentException("value is null");
+            }
+            map.put(key, value);
+        }
+
+        public void removeProperty(final Object key) {
+            if (key != null) map.remove(key);
+        }
+
+        public InvocationContext create() {
+            final FastCopyHashMap<Object, Object> map = this.map;
+            switch (map.size()) {
+                case 0: return EMPTY;
+                case 1: {
+                    final Object key = map.keySet().iterator().next();
+                    return new InvocationContext(Collections.singletonMap(key, map.get(key)));
+                }
+                default: {
+                    return new InvocationContext(map.clone());
+                }
+            }
+        }
+    }
+
+    static final class Serialized implements Serializable {
+
+        private static final long serialVersionUID = -2451954101448516318L;
+
+        private transient Map<Object, Object> values;
+
+        Serialized(final Map<Object, Object> values) {
+            this.values = values;
+        }
+
+        private void writeObject(ObjectOutputStream oos) throws IOException {
+            oos.defaultWriteObject();
+            oos.writeInt(values.size());
+            for (Map.Entry<Object, Object> entry : values.entrySet()) {
+                oos.writeObject(entry.getKey());
+                oos.writeObject(entry.getValue());
+            }
+        }
+
+        private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+            ois.defaultReadObject();
+            final int len = ois.readInt();
+            switch (len) {
+                case 0: values = Collections.emptyMap(); return;
+                case 1: values = Collections.singletonMap(ois.readObject(), ois.readObject()); return;
+            }
+            values = new FastCopyHashMap<Object, Object>(len);
+            for (int i = 0; i < len; i++) {
+                values.put(ois.readObject(), ois.readObject());
+            }
+        }
+
+        protected Object readResolve() {
+            if (values.isEmpty()) return EMPTY;
+            return new InvocationContext(values);
+        }
+    }
+}

Copied: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java (from rev 4153, invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/InvokableContainer.java)
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationDispatcher.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,47 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.invokable;
+
+/**
+ * Invokable
+ * <p/>
+ * Contract of an endpoint servicing incoming invocations.  For instance, implementations may either handle directly, or
+ * delegate to an underlying bean instance.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public interface InvocationDispatcher {
+
+    /**
+     * Carries out the specified invocation, returning the result
+     *
+     * @param invocation
+     *
+     * @return
+     *
+     * @throws InvocationException If the underlying invocation resulted in some Exception; the true context may be
+     * obtained via {@link InvocationException#getCause()}
+     * @throws IllegalArgumentException If the invocation is not specified
+     */
+    Object dispatch(Invocation invocation) throws InvocationException;
+}

Copied: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationException.java (from rev 4153, invokablecontainer/trunk/api/src/main/java/org/jboss/ejb3/container/api/InvocationException.java)
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationException.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationException.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,87 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2009, 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.invokable;
+
+/**
+ * InvocationException
+ * <p/>
+ * Represents some exceptional circumstance has occurred while carrying out an invocation.  The underlying problem is
+ * represented in the wrapped cause, which is required at construction.
+ *
+ * @author <a href="mailto:andrew.rubinger at jboss.org">ALR</a>
+ * @version $Revision: $
+ */
+public class InvocationException extends Exception {
+    //-------------------------------------------------------------------------------------||
+    // Class Members ----------------------------------------------------------------------||
+    //-------------------------------------------------------------------------------------||
+
+    /**
+     * serialVersionUID
+     */
+    private static final long serialVersionUID = 1L;
+    //-------------------------------------------------------------------------------------||
+    // Constructors -----------------------------------------------------------------------||
+    //-------------------------------------------------------------------------------------||
+
+    /**
+     * Constructs a new {@link InvocationException}
+     *
+     * @param message
+     * @param cause
+     *
+     * @throws IllegalArgumentException If no cause has been specified
+     */
+    public InvocationException(final String message, final Throwable cause) {
+        super(message, cause);
+        // Assert invariants
+        this.assertCauseSpecified();
+    }
+
+    /**
+     * Constructs a new {@link InvocationException}
+     *
+     * @param cause
+     *
+     * @throws IllegalArgumentException If no cause has been specified
+     */
+    public InvocationException(final Throwable cause) {
+        super(cause);
+        // Assert invariants
+        this.assertCauseSpecified();
+    }
+    //-------------------------------------------------------------------------------------||
+    // Internal Helper Methods ------------------------------------------------------------||
+    //-------------------------------------------------------------------------------------||
+
+    /**
+     * Ensures that the cause of this Exception has been specified; typically called from construction
+     *
+     * @throws IllegalArgumentException If no cause exists
+     */
+    private void assertCauseSpecified() {
+        // Assert invariants
+        if (this.getCause() == null) {
+            throw new IllegalArgumentException("Cause must be specified");
+        }
+    }
+}

Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationPermission.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationPermission.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/InvocationPermission.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,44 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.invokable;
+
+import java.security.BasicPermission;
+
+public final class InvocationPermission extends BasicPermission {
+
+    private static final long serialVersionUID = 1974507481892267240L;
+
+    public InvocationPermission(String name) {
+        super(name);
+    }
+
+    public static final InvocationPermission INVOKE = new InvocationPermission("invoke");
+
+    protected Object readResolve() {
+        if ("invoke".equals(getName())) {
+            return INVOKE;
+        } else {
+            return this;
+        }
+    }
+}

Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ObjectInvocationDispatcher.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.invokable;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+
+public final class ObjectInvocationDispatcher implements Serializable, InvocationDispatcher {
+
+    private static final long serialVersionUID = 149324822317622879L;
+
+    private final Object target;
+
+    public ObjectInvocationDispatcher(final Object target) {
+        this.target = target;
+    }
+
+    public Object dispatch(final Invocation invocation) throws InvocationException {
+        try {
+            return invocation.getTargetMethod().invoke(target, invocation.getArgs());
+        } catch (IllegalAccessException e) {
+            throw new InvocationException(new IllegalAccessError(e.getMessage()));
+        } catch (InvocationTargetException e) {
+            throw new InvocationException(e.getCause());
+        }
+    }
+
+    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+        ois.defaultReadObject();
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (! target.getClass().getProtectionDomain().implies(InvocationPermission.INVOKE)) {
+                throw new InvalidObjectException("Target object does not have invoke permission");
+            }
+        }
+    }
+}

Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProcessingInvocationDispatcher.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.invokable;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+
+public final class ProcessingInvocationDispatcher implements InvocationDispatcher, Serializable {
+
+    private static final long serialVersionUID = -132466317660532342L;
+
+    private final InvocationDispatcher dispatcher;
+
+    public ProcessingInvocationDispatcher(final InvocationDispatcher dispatcher) {
+        this.dispatcher = dispatcher;
+    }
+
+    public Object dispatch(final Invocation invocation) throws InvocationException {
+        return dispatcher.dispatch(invocation);
+    }
+
+    private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
+        ois.defaultReadObject();
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (! dispatcher.getClass().getProtectionDomain().implies(InvocationPermission.INVOKE)) {
+                throw new InvalidObjectException("Dispatcher does not have invoke permission");
+            }
+        }
+    }
+}

Added: invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java
===================================================================
--- invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java	                        (rev 0)
+++ invokablecontainer/trunk/api/src/main/java/org/jboss/invokable/ProxyInvocationHandler.java	2010-03-11 02:57:03 UTC (rev 4164)
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.invokable;
+
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.Serializable;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public final class ProxyInvocationHandler implements InvocationHandler, Serializable {
+
+    private static final long serialVersionUID = -7550306900997519378L;
+
+    private final InvocationDispatcher dispatcher;
+
+    public ProxyInvocationHandler(final InvocationDispatcher dispatcher) {
+        this.dispatcher = dispatcher;
+    }
+
+    public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable {
+        return dispatcher.dispatch(new Invocation(method, args));
+    }
+
+    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+        ois.defaultReadObject();
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            if (! dispatcher.getClass().getProtectionDomain().implies(InvocationPermission.INVOKE)) {
+                throw new InvalidObjectException("Dispatcher does not have invoke permission");
+            }
+        }
+    }
+}

Modified: invokablecontainer/trunk/pom.xml
===================================================================
--- invokablecontainer/trunk/pom.xml	2010-03-10 21:54:13 UTC (rev 4163)
+++ invokablecontainer/trunk/pom.xml	2010-03-11 02:57:03 UTC (rev 4164)
@@ -26,8 +26,6 @@
   <modules>
     <module>api</module>
     <module>build</module>
-    <module>core</module>
-    <module>spi</module>
   </modules>
 
 </project>



More information about the jboss-svn-commits mailing list