Merge branch 'bidir-deadlock' into 'ibm-trunk'

Bidir deadlock

See merge request !49
diff --git a/yoko-core/src/test/java/test/rmi/ClientMain.java b/yoko-core/src/test/java/test/rmi/ClientMain.java
index 5f25e88..97e1f34 100755
--- a/yoko-core/src/test/java/test/rmi/ClientMain.java
+++ b/yoko-core/src/test/java/test/rmi/ClientMain.java
@@ -348,6 +348,20 @@
             assertSame(map2.get(3), map2.get(4));
             assertSame(map2.get(0), map2.get(1));
         }
+
+        public void testClass() throws RemoteException {
+            final Class<?> type = Object.class;
+            sample.setSerializable(type);
+            Serializable s = sample.getSerializable();
+            assertSame(s, type);
+        }
+
+        public void testClassArray() throws RemoteException {
+            final Class<?>[] types = { Object.class, Map.class, String.class, Map.class };
+            sample.setSerializable(types);
+            Object[] oa = (Object[])sample.getSerializable();
+            assertArrayEquals(types, oa);
+        }
     }
 
     public static void main(String[] args) throws Exception {
@@ -392,6 +406,8 @@
         test.testTimeUnit();
         test.testTimeUnitArray();
         test.testCmsfv2Data();
+        test.testClass();
+        test.testClassArray();
         //myORB.destroy();
         System.out.println("Testing complete");
     }
diff --git a/yoko-rmi-impl/pom.xml b/yoko-rmi-impl/pom.xml
index d87bb45..a436390 100755
--- a/yoko-rmi-impl/pom.xml
+++ b/yoko-rmi-impl/pom.xml
@@ -76,7 +76,6 @@
                             org.apache.yoko.rmi.util,
                             org.apache.yoko.rmi.util.corba,
                             org.apache.yoko.rmi.util.stub,
-                            org.apache.yoko.rmi.cmsf
                         </Export-Package>
                         <Import-Package>
                             !sun.*,
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ArrayDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ArrayDescriptor.java
index 6c2bf4c..b3ee101 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ArrayDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ArrayDescriptor.java
@@ -18,7 +18,9 @@
 
 package org.apache.yoko.rmi.impl;
 
+import java.io.Serializable;
 import java.lang.reflect.Array;
+import java.util.Map;
 import java.util.Vector;
 import java.util.logging.Logger;
 
@@ -28,6 +30,7 @@
 import org.omg.CORBA.ORB;
 import org.omg.CORBA.TypeCode;
 import org.omg.CORBA.ValueMember;
+import org.omg.CORBA.portable.InputStream;
 
 public abstract class ArrayDescriptor extends ValueDescriptor {
     protected int order;
@@ -49,7 +52,7 @@
         } else {
             TypeDescriptor desc = getTypeRepository()
                     .getDescriptor(elementType);
-            String elemRep = desc.getRepositoryIDForArray();
+            String elemRep = desc.getRepositoryID();
             String hash = elemRep.substring(elemRep.indexOf(':', 4));
             _repid = "RMI:" + getJavaClass().getName() + hash;
         }
@@ -71,7 +74,7 @@
         } else {
             TypeDescriptor desc = getTypeRepository()
                     .getDescriptor(elementType);
-            _elementRepid = desc.getRepositoryIDForArray();
+            _elementRepid = desc.getRepositoryID();
         }
 
         // System.out.println ("Element REPID "+getJavaClass()+" >> "+_elementRepid);
@@ -424,27 +427,21 @@
         }
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
-            Integer key) {
-        try {
-            ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);
+    public Serializable readValue(InputStream in, Map offsetMap, Integer key) {
+        final int length = in.read_long();
+        Object[] arr = (Object[]) Array.newInstance(elementType, length);
+        offsetMap.put(key, arr);
 
-            int length = reader.readInt();
-            Object[] arr = (Object[]) Array.newInstance(elementType, length);
-            offsetMap.put(key, arr);
-            // System.out.println ("ValueArrayDescriptor::readValue
-            // len="+length+"; type="+elementType);
-
-            for (int i = 0; i < length; i++) {
-                arr[i] = reader.readValueObject(elementType);
+        final org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
+        for (int i = 0; i < length; i++) {
+            try {
+                arr[i] = _in.read_value(elementType);
+            } catch (org.omg.CORBA.portable.IndirectionException ex) {
+                arr[i] = offsetMap.get(new Integer(ex.offset));
             }
-
-            return (java.io.Serializable) arr;
-        } catch (java.io.IOException ex) {
-            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
 
+        return arr;
     }
 
     Object copyObject(Object value, CopyState state) {
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassBaseDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassBaseDescriptor.java
new file mode 100644
index 0000000..debb1ec
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassBaseDescriptor.java
@@ -0,0 +1,41 @@
+package org.apache.yoko.rmi.impl;
+
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+import javax.rmi.CORBA.ClassDesc;
+
+import org.omg.CORBA.MARSHAL;
+
+abstract class ClassBaseDescriptor extends ValueDescriptor {
+
+    ClassBaseDescriptor(Class type, TypeRepository repository) {
+        super(type, repository);
+    }
+
+    @Override
+    public void init() {
+        super.init();
+
+        final Class<?> clz = ClassDesc.class;
+
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                try {
+                    final Field repid_field = clz.getDeclaredField("repid");
+                    repid_field.setAccessible(true);
+                    final Field codebase_field = clz.getDeclaredField("codebase");
+                    codebase_field.setAccessible(true);
+                    init(repid_field, codebase_field);
+                } catch (NoSuchFieldException ex) {
+                    throw (MARSHAL)new MARSHAL("no such field: " + ex).initCause(ex);
+                }
+                return null;
+            }
+        });
+    }
+
+    abstract void init(Field repid_field, Field codebase_field);
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescDescriptor.java
new file mode 100644
index 0000000..c2ff742
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescDescriptor.java
@@ -0,0 +1,70 @@
+package org.apache.yoko.rmi.impl;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.rmi.CORBA.ClassDesc;
+import javax.rmi.CORBA.Util;
+
+import org.omg.CORBA.MARSHAL;
+
+public class ClassDescDescriptor extends ClassBaseDescriptor {
+    private static final Logger logger = Logger.getLogger(ClassDescDescriptor.class.getName());
+
+    private Field repid_field;
+    private Field codebase_field;
+
+    ClassDescDescriptor(TypeRepository repository) {
+        super(ClassDesc.class, repository);
+    }
+
+    @Override
+    void init(Field repid_field, Field codebase_field) {
+        this.repid_field = repid_field;
+        this.codebase_field = codebase_field;
+    }
+
+    /** Read an instance of this value from a CDR stream */
+    @Override
+    public Serializable readResolve(final Serializable value) {
+        final ClassDesc desc = (ClassDesc) value;
+
+        Class<?> result = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+            public Class<?> run() {
+                String className = "<unknown>";
+                try {
+                    String repid = (String) repid_field.get(desc);
+                    String codebase = (String) codebase_field.get(desc);
+
+                    TypeDescriptor typeDesc = repository.getDescriptor(repid);
+                    if (null != typeDesc) {
+                        Class<?> type = typeDesc.getJavaClass();
+                        if (null != type) return type;
+                    }
+
+                    int beg = repid.indexOf(':');
+                    int end = repid.indexOf(':', beg + 1);
+
+                    className = repid.substring(beg + 1, end);
+                    ClassLoader loader = Thread.currentThread().getContextClassLoader();
+
+                    return Util.loadClass(className, codebase, loader);
+                } catch (ClassNotFoundException ex) {
+                    throw (MARSHAL)new MARSHAL("cannot load class " + className).initCause(ex);
+                } catch (IllegalAccessException ex) {
+                    throw (MARSHAL)new MARSHAL("no such field: " + ex).initCause(ex);
+                }
+            }
+        });
+
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("readResolve %s => %s", value, result));
+
+        return result;
+    }
+
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java
index 37d2202..fab9919 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java
@@ -18,115 +18,71 @@
 
 package org.apache.yoko.rmi.impl;
 
+import java.io.Serializable;
+import java.lang.reflect.Field;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
-public class ClassDescriptor extends ValueDescriptor {
-    static Logger logger = Logger.getLogger(ClassDescriptor.class.getName());
+import javax.rmi.CORBA.ClassDesc;
+import javax.rmi.CORBA.Util;
+import javax.rmi.CORBA.ValueHandler;
+
+import org.omg.CORBA.MARSHAL;
+
+public class ClassDescriptor extends ClassBaseDescriptor {
+    private static final Logger logger = Logger.getLogger(ClassDescriptor.class.getName());
+
+    private Field repid_field;
+    private Field codebase_field;
 
     ClassDescriptor(TypeRepository repository) {
-        super(javax.rmi.CORBA.ClassDesc.class, repository);
+        super(Class.class, repository);
     }
 
-    java.lang.reflect.Field repid_field;
-
-    java.lang.reflect.Field codebase_field;
-
-    String _repid_arr;
-
-    public void init() {
-        super.init();
-
-        Class clz = javax.rmi.CORBA.ClassDesc.class;
-        try {
-            repid_field = clz.getDeclaredField("repid");
-            repid_field.setAccessible(true);
-            codebase_field = clz.getDeclaredField("codebase");
-            codebase_field.setAccessible(true);
-        } catch (java.lang.NoSuchFieldException ex) {
-            throw new org.omg.CORBA.MARSHAL("no such field: " + ex);
-        }
-
-        ValueDescriptor class_desc = new ValueDescriptor(Class.class,
-                getTypeRepository());
-        class_desc.init();
-        _repid_arr = class_desc.getRepositoryID();
+    @Override
+    void init(Field repid_field, Field codebase_field) {
+        this.repid_field = repid_field;
+        this.codebase_field = codebase_field;
     }
 
-    public String getRepositoryIDForArray() {
-        return _repid_arr;
-    }
-
+    @Override
     Object copyObject(Object orig, CopyState state) {
         state.put(orig, orig);
         return orig;
     }
 
-    /** Read an instance of this value from a CDR stream */
-    public java.io.Serializable readResolve(final java.io.Serializable value) {
-        final javax.rmi.CORBA.ClassDesc desc = (javax.rmi.CORBA.ClassDesc) value;
-
-        java.io.Serializable result = (java.io.Serializable) AccessController
-                .doPrivileged(new PrivilegedAction() {
-                    public Object run() {
-                        String className = "<unknown>";
-                        try {
-                            String repid = (String) repid_field.get(desc);
-                            String codebase = (String) codebase_field.get(desc);
-
-                            int beg = repid.indexOf(':');
-                            int end = repid.indexOf(':', beg + 1);
-
-                            className = repid.substring(beg + 1, end);
-                            ClassLoader loader = Thread.currentThread()
-                                    .getContextClassLoader();
-
-                            return javax.rmi.CORBA.Util.loadClass(className,
-                                    codebase, loader);
-                        } catch (java.lang.ClassNotFoundException ex) {
-                            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(
-                                    "cannot load class " + className).initCause(ex);
-                        } catch (java.lang.IllegalAccessException ex) {
-                            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(
-                                    "no such field: " + ex).initCause(ex);
-                        }
-                    }
-                });
-
-        logger.fine("readResolve " + value + " => " + result);
-
-        return result;
-    }
-
     /** Write an instance of this value to a CDR stream */
-    public java.io.Serializable writeReplace(final java.io.Serializable value) {
-        final Class type = (Class) value;
+    @Override
+    public Serializable writeReplace(final Serializable value) {
+        final Class<?> type = (Class<?>) value;
 
-        final javax.rmi.CORBA.ClassDesc desc = new javax.rmi.CORBA.ClassDesc();
-
-        return (java.io.Serializable) AccessController
-                .doPrivileged(new PrivilegedAction() {
-                    public Object run() {
+        final ClassDesc result = AccessController
+                .doPrivileged(new PrivilegedAction<ClassDesc>() {
+                    public ClassDesc run() {
                         try {
+                            final ClassDesc desc = new ClassDesc();
 
-                            javax.rmi.CORBA.ValueHandler handler = javax.rmi.CORBA.Util
-                                    .createValueHandler();
+                            ValueHandler handler = Util.createValueHandler();
                             String repId = handler.getRMIRepositoryID(type);
                             repid_field.set(desc, repId);
 
-                            String codebase = javax.rmi.CORBA.Util
-                                    .getCodebase(type);
+                            String codebase = Util.getCodebase(type);
                             codebase_field.set(desc, codebase);
 
                             return desc;
 
-                        } catch (java.lang.IllegalAccessException ex) {
-                            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(
-                                    "no such field: " + ex).initCause(ex);
+                        } catch (IllegalAccessException ex) {
+                            throw (MARSHAL)new MARSHAL("no such field: " + ex).initCause(ex);
                         }
                     }
                 });
+
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("writeReplace %s => %s", value, result));
+
+        return result;
     }
 
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeDescriptor.java
index 43d6b0b..5b8b833 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeDescriptor.java
@@ -41,9 +41,9 @@
 
     @Override
     public String toString() {
-        return String.format("%s{class=\"%s\",repId=\"%s\",arrRepId=\"%s\"}",
+        return String.format("%s{class=\"%s\",repId=\"%s\"}",
                 this.getClass().getName(), getJavaClass(),
-                getRepositoryID(), getRepositoryIDForArray());
+                getRepositoryID());
     }
 
     protected TypeDescriptor(Class type, TypeRepository repository) {
@@ -65,10 +65,6 @@
         }
     }
 
-    public String getRepositoryIDForArray() {
-        return getRepositoryID();
-    }
-
     public String getRepositoryID() {
         if (_repid == null)
             _repid = "RMI:" + getJavaClass().getName() + ":0000000000000000";
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeRepository.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeRepository.java
index ddc5ca4..72d2d75 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeRepository.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/TypeRepository.java
@@ -69,7 +69,6 @@
             cleanStaleKeys();
             final WeakReference<TypeDescriptor> value = new WeakReference<>(typeDesc);
             map.putIfAbsent(new WeakKey<String>(typeDesc.getRepositoryID(), staleKeys), value);
-            map.putIfAbsent(new WeakKey<String>(typeDesc.getRepositoryIDForArray(), staleKeys), value);
         }
 
         private void cleanStaleKeys() {
@@ -100,7 +99,7 @@
                 } else if (type == Class.class) {
                     return new ClassDescriptor(repo);
                 } else if (type == ClassDesc.class) {
-                    return this.get(Class.class);
+                    return new ClassDescDescriptor(repo);
                 } else if (type == java.util.Date.class) {
                     return new DateValueDescriptor(repo);
                 } else if (staticAnyTypes.contains(type)) {
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueDescriptor.java
index 6d7eb3e..a4b869f 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueDescriptor.java
@@ -599,7 +599,11 @@
 
             readValue(reader, value);
 
-            return readResolve(value);
+            final Serializable resolved = readResolve(value);
+            if (value != resolved) {
+                offsetMap.put(offset, resolved);
+            }
+            return resolved;
 
         } catch (IOException ex) {
             throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);