Merge branch 'enum-fix' into 'ibm-trunk'

Enum fix

See merge request !63
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OBCORBA/ORB_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OBCORBA/ORB_impl.java
index 36e0044..4159e83 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OBCORBA/ORB_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OBCORBA/ORB_impl.java
@@ -296,7 +296,7 @@
             try {
                 piManager.addIORInterceptor(new YasfIORInterceptor(), true);
                 piManager.addClientRequestInterceptor(new YasfClientInterceptor());
-                piManager.addServerRequestInterceptor(new YasfServerInterceptor());
+                piManager.addServerRequestInterceptor(new YasfServerInterceptor(piManager.allocateSlotId()));
             } catch (org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName ex) {
                 org.apache.yoko.orb.OB.Assert._OB_assert(ex);
             }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ClientRequestInfo_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ClientRequestInfo_impl.java
index 53c938d..e2023e8 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ClientRequestInfo_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ClientRequestInfo_impl.java
@@ -19,6 +19,8 @@
 
 import org.apache.yoko.util.cmsf.CmsfThreadLocal;
 import org.apache.yoko.util.cmsf.CmsfThreadLocal.CmsfOverride;
+import org.apache.yoko.util.yasf.YasfThreadLocal;
+import org.apache.yoko.util.yasf.YasfThreadLocal.YasfOverride;
 
 final public class ClientRequestInfo_impl extends RequestInfo_impl implements
         org.omg.PortableInterceptor.ClientRequestInfo {
@@ -364,7 +366,8 @@
         argStrategy_.setArgsAvail(true);
         argStrategy_.setExceptAvail(true);
 
-        try (CmsfOverride cmsfo = CmsfThreadLocal.override()) {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             java.util.Enumeration e = interceptors.elements();
             while (e.hasMoreElements()) {
                 org.omg.PortableInterceptor.ClientRequestInterceptor interceptor = (org.omg.PortableInterceptor.ClientRequestInterceptor) e
@@ -398,7 +401,8 @@
             current_._OB_pushSlotData(currentSlots_);
         }
 
-        try (CmsfOverride cmsfo = CmsfThreadLocal.override()) {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             int curr = interceptors_.size() - 1;
             while (!interceptors_.isEmpty()) {
                 try {
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ServerRequestInfo_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ServerRequestInfo_impl.java
index fb484e4..70e6fc5 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ServerRequestInfo_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/PortableInterceptor/ServerRequestInfo_impl.java
@@ -19,6 +19,8 @@
 
 import org.apache.yoko.util.cmsf.CmsfThreadLocal;
 import org.apache.yoko.util.cmsf.CmsfThreadLocal.CmsfOverride;
+import org.apache.yoko.util.yasf.YasfThreadLocal;
+import org.apache.yoko.util.yasf.YasfThreadLocal.YasfOverride;
 
 final public class ServerRequestInfo_impl extends RequestInfo_impl implements
         ServerRequestInfoExt {
@@ -380,7 +382,8 @@
         argStrategy_.setArgsAvail(false);
         argStrategy_.setExceptAvail(false);
 
-        try (CmsfOverride cmsfo = CmsfThreadLocal.override()) {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             java.util.Enumeration e = interceptors.elements();
             while (e.hasMoreElements()) {
                 org.omg.PortableInterceptor.ServerRequestInterceptor i = (org.omg.PortableInterceptor.ServerRequestInterceptor) e
@@ -408,7 +411,8 @@
 
         status_ = NO_REPLY;
 
-        try (CmsfOverride cmsfo = CmsfThreadLocal.override()) {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             java.util.Enumeration e = interceptors_.elements();
             while (e.hasMoreElements()) {
                 ((org.omg.PortableInterceptor.ServerRequestInterceptor) (e
@@ -434,7 +438,8 @@
         //
         servant_ = null;
 
-        try (CmsfOverride cmsfo = CmsfThreadLocal.override()) {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             int curr = interceptors_.size() - 1;
             while (!interceptors_.isEmpty()) {
                 org.omg.PortableInterceptor.ServerRequestInterceptor i = (org.omg.PortableInterceptor.ServerRequestInterceptor) interceptors_
@@ -469,7 +474,8 @@
         //
         servant_ = null;
 
-        try (CmsfOverride cmsfo = CmsfThreadLocal.override()) {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             org.apache.yoko.orb.OB.Assert
                     ._OB_assert(status_ == org.omg.PortableInterceptor.SYSTEM_EXCEPTION.value
                             || status_ == org.omg.PortableInterceptor.USER_EXCEPTION.value);
@@ -511,7 +517,8 @@
         //
         servant_ = null;
 
-        try (CmsfOverride cmsfo = CmsfThreadLocal.override()) {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             org.apache.yoko.orb.OB.Assert
                     ._OB_assert(status_ == org.omg.PortableInterceptor.LOCATION_FORWARD.value
                             || status_ == org.omg.PortableInterceptor.TRANSPORT_RETRY.value);
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/Yasf.java b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/Yasf.java
deleted file mode 100644
index 98fdf34..0000000
--- a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/Yasf.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package org.apache.yoko.orb.yasf;
-
-import java.util.BitSet;
-
-import org.omg.IOP.ServiceContext;
-import org.omg.IOP.TaggedComponent;
-
-public enum Yasf {
-    ;
-
-    // TODO - Get ids from OMG assigned for these values
-    public static final int TAG_YOKO_AUXILLIARY_STREAM_FORMAT = 0xeeeeeeee;
-    public static final int YOKO_AUXIllIARY_STREAM_FORMAT_SC = 0xeeeeeeee;
-
-    public final int itemIndex;
-
-    private Yasf(int itemIndex) {
-        this.itemIndex = itemIndex;
-    }
-
-    public boolean isSet(BitSet items) {
-        return items.get(itemIndex);
-    }
-
-    public static Builder build() {
-        return new BuilderImpl();
-    }
-
-    public static BitSet readData(byte[] data) {
-        return BitSet.valueOf(data);
-    }
-
-    public interface Builder {
-        public Builder set(Yasf... items);
-        public Builder clear(Yasf... items);
-        public TaggedComponent tc();
-        public ServiceContext sc();
-    }
-
-    private static final class BuilderImpl implements Builder {
-        private final BitSet bits = new BitSet();
-
-        BuilderImpl() {}
-
-        @Override
-        public Builder set(Yasf... items) {
-            for (Yasf item: items) {
-                bits.set(item.itemIndex);
-            }
-            return this;
-        }
-
-        @Override
-        public Builder clear(Yasf... items) {
-            for (Yasf item: items) {
-                bits.clear(item.itemIndex);
-            }
-            return this;
-        }
-
-        @Override
-        public TaggedComponent tc() {
-            return new TaggedComponent(TAG_YOKO_AUXILLIARY_STREAM_FORMAT, bits.toByteArray());
-        }
-
-        @Override
-        public ServiceContext sc() {
-            return new ServiceContext(YOKO_AUXIllIARY_STREAM_FORMAT_SC, bits.toByteArray());
-        }
-    }
-}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfClientInterceptor.java b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfClientInterceptor.java
index 8a56c92..dc434a0 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfClientInterceptor.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfClientInterceptor.java
@@ -5,6 +5,8 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
+import org.apache.yoko.util.yasf.Yasf;
+import org.apache.yoko.util.yasf.YasfThreadLocal;
 import org.omg.CORBA.LocalObject;
 import org.omg.PortableInterceptor.ClientRequestInfo;
 import org.omg.PortableInterceptor.ClientRequestInterceptor;
@@ -15,7 +17,11 @@
 
     @Override
     public void send_request(ClientRequestInfo ri) throws ForwardRequest {
-        ri.add_request_service_context(Yasf.build().sc(), false);
+        byte[] yasfData = YasfHelper.readData(ri);
+
+        YasfThreadLocal.push(Yasf.toSet(yasfData));
+
+        YasfHelper.addSc(ri, Yasf.supported());
     }
 
     @Override
@@ -24,14 +30,17 @@
 
     @Override
     public void receive_reply(ClientRequestInfo ri) {
+        YasfThreadLocal.pop();
     }
 
     @Override
     public void receive_exception(ClientRequestInfo ri) throws ForwardRequest {
+        YasfThreadLocal.pop();
     }
 
     @Override
     public void receive_other(ClientRequestInfo ri) throws ForwardRequest {
+        YasfThreadLocal.pop();
     }
 
     @Override
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfHelper.java b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfHelper.java
new file mode 100644
index 0000000..d652a2e
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfHelper.java
@@ -0,0 +1,87 @@
+package org.apache.yoko.orb.yasf;
+
+import org.apache.yoko.util.yasf.Yasf;
+import org.omg.CORBA.Any;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.INTERNAL;
+import org.omg.CORBA.ORB;
+import org.omg.IOP.ServiceContext;
+import org.omg.IOP.TaggedComponent;
+import org.omg.PortableInterceptor.ClientRequestInfo;
+import org.omg.PortableInterceptor.IORInfo;
+import org.omg.PortableInterceptor.InvalidSlot;
+import org.omg.PortableInterceptor.ServerRequestInfo;
+
+import java.util.Set;
+
+import static org.apache.yoko.orb.OB.MinorCodes.MinorInvalidComponentId;
+import static org.apache.yoko.orb.OB.MinorCodes.MinorInvalidServiceContextId;
+
+/**
+ * Created by nrichard on 23/03/16.
+ */
+public enum YasfHelper {
+    ;
+
+    public static void addTc(IORInfo info, Set<Yasf> set) {
+        TaggedComponent tc = new TaggedComponent(Yasf.TAG_YOKO_AUXILLIARY_STREAM_FORMAT, Yasf.toData(set));
+        info.add_ior_component(tc);
+    }
+
+    private static ServiceContext sc(Set<Yasf> set) {
+        return new ServiceContext(Yasf.YOKO_AUXIllIARY_STREAM_FORMAT_SC, Yasf.toData(set));
+    }
+
+    public static void addSc(ClientRequestInfo ri, Set<Yasf> set) {
+        ServiceContext sc = sc(set);
+        ri.add_request_service_context(sc, false);
+    }
+
+    public static void addSc(ServerRequestInfo ri, Set<Yasf> set) {
+        ServiceContext sc = sc(set);
+        ri.add_reply_service_context(sc, false);
+    }
+
+    public static byte[] readData(ClientRequestInfo ri) {
+        try {
+            TaggedComponent tc = ri.get_effective_component(Yasf.TAG_YOKO_AUXILLIARY_STREAM_FORMAT);
+            return tc.component_data;
+        } catch (BAD_PARAM e) {
+            if (e.minor != MinorInvalidComponentId) {
+                throw e;
+            }
+        }
+        return null;
+    }
+
+    public static byte[] readData(ServerRequestInfo ri) {
+        try {
+            ServiceContext sc = ri.get_request_service_context(Yasf.YOKO_AUXIllIARY_STREAM_FORMAT_SC);
+            return sc.context_data;
+        } catch (BAD_PARAM e) {
+            if (e.minor != MinorInvalidServiceContextId) {
+                throw e;
+            }
+        }
+        return null;
+    }
+
+    public static void setSlot(int slotId, ServerRequestInfo ri, byte[] data) {
+        Any any = ORB.init().create_any();
+        any.insert_Value(data);
+        try {
+            ri.set_slot(slotId, any);
+        } catch (InvalidSlot e) {
+            throw (INTERNAL)(new INTERNAL(e.getMessage())).initCause(e);
+        }
+    }
+
+    public static byte[] getSlot(int slotId, ServerRequestInfo ri) {
+        try {
+            Any any = ri.get_slot(slotId);
+            return (byte[])any.extract_Value();
+        } catch (InvalidSlot e) {
+            throw (INTERNAL)(new INTERNAL(e.getMessage())).initCause(e);
+        }
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfIORInterceptor.java b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfIORInterceptor.java
index 68ef43e..ec3976a 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfIORInterceptor.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfIORInterceptor.java
@@ -5,6 +5,7 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
+import org.apache.yoko.util.yasf.Yasf;
 import org.omg.CORBA.LocalObject;
 import org.omg.PortableInterceptor.IORInfo;
 import org.omg.PortableInterceptor.IORInterceptor;
@@ -14,7 +15,7 @@
 
     @Override
     public void establish_components(IORInfo info) {
-        info.add_ior_component(Yasf.build().tc());
+        YasfHelper.addTc(info, Yasf.supported());
     }
 
     @Override
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfServerInterceptor.java b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfServerInterceptor.java
index f5d5bd1..352d70e 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfServerInterceptor.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfServerInterceptor.java
@@ -5,6 +5,8 @@
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 
+import org.apache.yoko.util.yasf.Yasf;
+import org.apache.yoko.util.yasf.YasfThreadLocal;
 import org.omg.CORBA.LocalObject;
 import org.omg.PortableInterceptor.ForwardRequest;
 import org.omg.PortableInterceptor.ServerRequestInfo;
@@ -13,8 +15,17 @@
 public class YasfServerInterceptor extends LocalObject implements ServerRequestInterceptor {
     private static final String NAME = YasfServerInterceptor.class.getName();
 
+    private final int slotId;
+
+    public YasfServerInterceptor(int slotId) {
+        this.slotId = slotId;
+    }
+
     @Override
     public void receive_request_service_contexts(ServerRequestInfo ri) throws ForwardRequest {
+        YasfThreadLocal.reset();
+        byte[] yasfData = YasfHelper.readData(ri);
+        YasfHelper.setSlot(slotId, ri, yasfData);
     }
 
     @Override
@@ -23,17 +34,23 @@
 
     @Override
     public void send_reply(ServerRequestInfo ri) {
-        ri.add_reply_service_context(Yasf.build().sc(), false);
+        YasfThreadLocal.push(Yasf.toSet(YasfHelper.getSlot(slotId, ri)));
+        // Adding for diagnostic purposes
+        YasfHelper.addSc(ri, Yasf.supported());
     }
 
     @Override
     public void send_exception(ServerRequestInfo ri) throws ForwardRequest {
-        ri.add_reply_service_context(Yasf.build().sc(), false);
+        YasfThreadLocal.push(Yasf.toSet(YasfHelper.getSlot(slotId, ri)));
+        // Adding for diagnostic purposes
+        YasfHelper.addSc(ri, Yasf.supported());
     }
 
     @Override
     public void send_other(ServerRequestInfo ri) throws ForwardRequest {
-        ri.add_reply_service_context(Yasf.build().sc(), false);
+        YasfThreadLocal.push(Yasf.toSet(YasfHelper.getSlot(slotId, ri)));
+        // Adding for diagnostic purposes
+        YasfHelper.addSc(ri, Yasf.supported());
     }
 
     @Override
diff --git a/yoko-core/src/test/java/test/rmi/ClientMain.java b/yoko-core/src/test/java/test/rmi/ClientMain.java
index 97e1f34..ff12805 100755
--- a/yoko-core/src/test/java/test/rmi/ClientMain.java
+++ b/yoko-core/src/test/java/test/rmi/ClientMain.java
@@ -218,6 +218,13 @@
             assertTrue(Arrays.deepEquals(sa, oa));
         }
 
+        public void testData() throws RemoteException {
+            SampleData sd = new SampleData();
+            sample.setSerializable(sd);
+            Serializable s = sample.getSerializable();
+            assertEquals(sd, s);
+        }
+
         public void testTimeUnit() throws RemoteException {
             TimeUnit tu = TimeUnit.NANOSECONDS;
             sample.setSerializable(tu);
@@ -403,6 +410,7 @@
         test.testHashMap();
         test.testEnum();
         test.testEnumArray();
+        test.testData();
         test.testTimeUnit();
         test.testTimeUnitArray();
         test.testCmsfv2Data();
diff --git a/yoko-core/src/test/java/test/rmi/SampleData.java b/yoko-core/src/test/java/test/rmi/SampleData.java
new file mode 100644
index 0000000..fe4c5a1
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/SampleData.java
@@ -0,0 +1,54 @@
+package test.rmi;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Objects;
+
+/**
+ * Created by nrichard on 11/03/16.
+ */
+public class SampleData implements Serializable {
+    private static class Data2 implements Serializable {
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (!(o instanceof Data2)) return false;
+            return true;
+        }
+    }
+
+    private static class MrBoom implements Serializable {
+        private void writeObject(ObjectOutputStream oos) throws IOException {
+            throw new IOException("*BOOM*!");
+        }
+    }
+
+    public static enum DataEnum {
+        E1(new Data2()), E2(new MrBoom());
+        public final Serializable s;
+
+        private DataEnum(Serializable s) {
+            this.s = s;
+        }
+    }
+
+    public final Serializable f1 = DataEnum.E1;
+    public final Serializable f2 = DataEnum.E2;
+    public final Serializable f3 = DataEnum.E1.s;
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!(o instanceof SampleData)) return false;
+        SampleData sd = (SampleData)o;
+        if (f1 != sd.f1) return false;
+        if (f2 != sd.f2) return false;
+        return f3.equals(sd.f3);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(f1, f2);
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AbstractObjectDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AbstractObjectDescriptor.java
index d1ffe66..8a64c50 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AbstractObjectDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AbstractObjectDescriptor.java
@@ -18,17 +18,14 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class AbstractObjectDescriptor extends ValueDescriptor {
+class AbstractObjectDescriptor extends ValueDescriptor {
     protected AbstractObjectDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
 
-    public String getRepositoryID() {
-        if (_repid == null)
-            _repid = "IDL:" + getJavaClass().getName().replace('.', '/')
-                    + ":1.0";
-
-        return _repid;
+    @Override
+    protected String genRepId() {
+        return String.format("IDL:%s:1.0", _java_class.getName().replace('.', '/'));
     }
 
     /** Read an instance of this value from a CDR stream */
@@ -60,7 +57,7 @@
         if (_type_code == null) {
             org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
             _type_code = orb.create_abstract_interface_tc(getRepositoryID(),
-                    getJavaClass().getName());
+                    _java_class.getName());
         }
 
         return _type_code;
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AnyDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AnyDescriptor.java
index 11c22c9..faabb00 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AnyDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/AnyDescriptor.java
@@ -18,17 +18,14 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class AnyDescriptor extends TypeDescriptor {
+class AnyDescriptor extends TypeDescriptor {
     AnyDescriptor(Class type, TypeRepository rep) {
         super(type, rep);
     }
 
-    public String getRepositoryID() {
-        if (_repid == null)
-            _repid = "IDL:" + getJavaClass().getName().replace('.', '/')
-                    + ":1.0";
-
-        return _repid;
+    @Override
+    protected String genRepId() {
+        return String.format("IDL:%s:1.0", _java_class.getName().replace('.', '/'));
     }
 
     /** Read an instance of this value from a CDR stream */
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 b3ee101..1a5f7cb 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
@@ -21,64 +21,44 @@
 import java.io.Serializable;
 import java.lang.reflect.Array;
 import java.util.Map;
-import java.util.Vector;
 import java.util.logging.Logger;
 
-import javax.rmi.CORBA.Util;
-
 import org.omg.CORBA.MARSHAL;
 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 {
+abstract class ArrayDescriptor extends ValueDescriptor {
     protected int order;
 
     protected Class basicType;
 
     protected Class elementType;
-    // repository ID for the array class
-    String _repid = null;
     // repository ID for the contained elements
-    String _elementRepid = null;
+    private volatile String _elementRepid = null;
 
-    public String getRepositoryID() {
-        if (_repid != null)
-            return _repid;
+    @Override
+    protected String genRepId() {
+        if (elementType.isPrimitive() || elementType == Object.class)
+            return String.format("RMI:%s:%016X", _java_class.getName(), 0);
 
-        if (elementType.isPrimitive() || elementType == Object.class) {
-            _repid = "RMI:" + getJavaClass().getName() + ":0000000000000000";
-        } else {
-            TypeDescriptor desc = getTypeRepository()
-                    .getDescriptor(elementType);
-            String elemRep = desc.getRepositoryID();
-            String hash = elemRep.substring(elemRep.indexOf(':', 4));
-            _repid = "RMI:" + getJavaClass().getName() + hash;
-        }
-
-        // System.out.println ("REPID "+getJavaClass()+" >> "+_repid);
-
-        return _repid;
+        TypeDescriptor desc = repo.getDescriptor(elementType);
+        String elemRep = desc.getRepositoryID();
+        String hash = elemRep.substring(elemRep.indexOf(':', 4));
+        return String.format("RMI:%s:%s", _java_class.getName(), hash);
     }
 
-
-    public String getElementRepositoryID() {
-        if (_elementRepid != null) {
-            return _elementRepid;
-        }
-
+    private final String genElemRepId() {
         if (elementType.isPrimitive() || elementType == Object.class) {
             // use the descriptor type past the array type marker
-            _elementRepid = "RMI:" + getJavaClass().getName().substring(1) + ":0000000000000000";
-        } else {
-            TypeDescriptor desc = getTypeRepository()
-                    .getDescriptor(elementType);
-            _elementRepid = desc.getRepositoryID();
+            return String.format("RMI:%s:%016X", _java_class.getName().substring(1), 0);
         }
+        return repo.getDescriptor(elementType).getRepositoryID();
+    }
 
-        // System.out.println ("Element REPID "+getJavaClass()+" >> "+_elementRepid);
-
+    public String getElementRepositoryID() {
+        if (_elementRepid == null) _elementRepid = genElemRepId();
         return _elementRepid;
     }
 
@@ -98,7 +78,7 @@
     public String getIDLName() {
         StringBuffer sb = new StringBuffer("org_omg_boxedRMI_");
 
-        TypeDescriptor desc = getTypeRepository().getDescriptor(basicType);
+        TypeDescriptor desc = repo.getDescriptor(basicType);
         
         // The logic that looks for the last "_" fails when this is a 
         // long_long primitive type.  The primitive types have a "" package 
@@ -183,17 +163,11 @@
      */
     public Object read(org.omg.CORBA.portable.InputStream in) {
         org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
-        logger.fine("Reading an array value with repository id " + getRepositoryID() + " java class is " + getJavaClass()); 
+        logger.fine("Reading an array value with repository id " + getRepositoryID() + " java class is " + _java_class);
         
         // if we have a resolved class, read using that, otherwise fall back on the 
         // repository id. 
-        Class clz = getJavaClass(); 
-        if (clz == null) {
-            return _in.read_value(getRepositoryID());
-        }
-        else { 
-            return _in.read_value(clz);
-        }
+        return ((null == _java_class) ? _in.read_value(getRepositoryID()) : _in.read_value(_java_class));
     }
 
     /** Write an instance of this value to a CDR stream */
@@ -209,8 +183,7 @@
 
             _value_members = new org.omg.CORBA.ValueMember[1];
 
-            TypeDescriptor elemDesc = getTypeRepository().getDescriptor(
-                    elementType);
+            TypeDescriptor elemDesc = repo.getDescriptor(elementType);
 
             String elemRepID = elemDesc.getRepositoryID();
 
@@ -228,7 +201,7 @@
     }
 
     void addDependencies(java.util.Set classes) {
-        getTypeRepository().getDescriptor(basicType).addDependencies(classes);
+        repo.getDescriptor(basicType).addDependencies(classes);
     }
 
 }
@@ -248,7 +221,7 @@
         Object[] arr = (Object[]) value;
         out.write_long(arr.length);
 
-        logger.finer("writing " + getJavaClass().getName() + " size="
+        logger.finer("writing " + _java_class.getName() + " size="
                 + arr.length);
 
         for (int i = 0; i < arr.length; i++) {
@@ -267,7 +240,7 @@
 
             offsetMap.put(key, arr);
 
-            logger.fine("reading " + getJavaClass().getName() + " size="
+            logger.fine("reading " + _java_class.getName() + " size="
                     + arr.length);
 
             for (int i = 0; i < length; i++) {
@@ -316,7 +289,7 @@
 
     void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         Object[] arr = (Object[]) val;
-        TypeDescriptor desc = getTypeRepository().getDescriptor(elementType);
+        TypeDescriptor desc = repo.getDescriptor(elementType);
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
             if (i != 0) {
@@ -397,7 +370,7 @@
 
     void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         Object[] arr = (Object[]) val;
-        TypeDescriptor desc = getTypeRepository().getDescriptor(elementType);
+        TypeDescriptor desc = repo.getDescriptor(elementType);
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
             if (i != 0) {
@@ -469,7 +442,7 @@
 
     void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         Object[] arr = (Object[]) val;
-        TypeDescriptor desc = getTypeRepository().getDescriptor(elementType);
+        TypeDescriptor desc = repo.getDescriptor(elementType);
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
             if (i != 0) {
@@ -550,7 +523,7 @@
 
     void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         Object[] arr = (Object[]) val;
-        TypeDescriptor desc = getTypeRepository().getDescriptor(elementType);
+        TypeDescriptor desc = repo.getDescriptor(elementType);
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
             if (i != 0) {
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/BooleanDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/BooleanDescriptor.java
index 2de50d2..24e22e6 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/BooleanDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/BooleanDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class BooleanDescriptor extends SimpleDescriptor {
+final class BooleanDescriptor extends SimpleDescriptor {
     BooleanDescriptor(TypeRepository repository) {
         super(Boolean.TYPE, repository, "boolean",
                 org.omg.CORBA.TCKind.tk_boolean);
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ByteDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ByteDescriptor.java
index b47b7d4..2c044cf 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ByteDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ByteDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class ByteDescriptor extends SimpleDescriptor {
+final class ByteDescriptor extends SimpleDescriptor {
     ByteDescriptor(TypeRepository repository) {
         super(Byte.TYPE, repository, "octet", org.omg.CORBA.TCKind.tk_octet);
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CharDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CharDescriptor.java
index 8334380..b8077b7 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CharDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CharDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class CharDescriptor extends SimpleDescriptor {
+final class CharDescriptor extends SimpleDescriptor {
     CharDescriptor(TypeRepository repository) {
         super(Character.TYPE, repository, "wchar",
                 org.omg.CORBA.TCKind.tk_wchar);
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
index eff9cb1..1a93939 100644
--- 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
@@ -13,7 +13,7 @@
 import org.apache.yoko.util.cmsf.RepIds;
 import org.omg.CORBA.MARSHAL;
 
-public class ClassDescDescriptor extends ClassBaseDescriptor {
+class ClassDescDescriptor extends ClassBaseDescriptor {
     private static final Logger logger = Logger.getLogger(ClassDescDescriptor.class.getName());
 
     private Field repid_field;
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 fab9919..d296aed 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
@@ -31,7 +31,7 @@
 
 import org.omg.CORBA.MARSHAL;
 
-public class ClassDescriptor extends ClassBaseDescriptor {
+class ClassDescriptor extends ClassBaseDescriptor {
     private static final Logger logger = Logger.getLogger(ClassDescriptor.class.getName());
 
     private Field repid_field;
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DateValueDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DateValueDescriptor.java
index bb718d1..bfc500c 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DateValueDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DateValueDescriptor.java
@@ -27,12 +27,11 @@
  * Window>Preferences>Java>Templates. To enable and disable the creation of type
  * comments go to Window>Preferences>Java>Code Generation.
  */
-public class DateValueDescriptor extends ValueDescriptor {
+class DateValueDescriptor extends ValueDescriptor {
 
     /**
      * Constructor for DateValueDescriptor.
-     * 
-     * @param type
+     *
      * @param repository
      */
     public DateValueDescriptor(TypeRepository repository) {
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DoubleDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DoubleDescriptor.java
index 2fd7ca6..8299776 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DoubleDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DoubleDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class DoubleDescriptor extends SimpleDescriptor {
+final class DoubleDescriptor extends SimpleDescriptor {
     DoubleDescriptor(TypeRepository repository) {
         super(Double.TYPE, repository, "double", org.omg.CORBA.TCKind.tk_double);
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumDescriptor.java
index 1e89d28..44e692c 100644
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumDescriptor.java
@@ -1,43 +1,68 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
 package org.apache.yoko.rmi.impl;
 
+import org.apache.yoko.util.yasf.Yasf;
+import org.apache.yoko.util.yasf.YasfThreadLocal;
+
+import java.io.IOException;
 import java.io.Serializable;
-import java.util.Map;
+import java.util.Set;
 
-import org.omg.CORBA.portable.IndirectionException;
-import org.omg.CORBA.portable.InputStream;
-
-public final class EnumDescriptor extends ValueDescriptor {
-    @SuppressWarnings("rawtypes")
-    private final Class enumType;
-
-    EnumDescriptor(Class<?> type, TypeRepository repository) {
-        super(type, repository);
-        enumType = getEnumType(type);
-    }
-
-    private static Class<?> getEnumType(Class<?> type) {
-        while (!!!type.isEnum()) {
-            type = type.getSuperclass();
-        }
-        return type;
+class EnumDescriptor extends ValueDescriptor {
+    public EnumDescriptor(Class<?> type, TypeRepository repo) {
+        super(type, repo);
     }
 
     @Override
-    long getSerialVersionUID() {
+    protected final long getSerialVersionUID() {
         return 0L;
     }
 
     @Override
-    public Serializable readValue(InputStream in, Map<Integer, Object> offsetMap, Integer offset) {
-        try {
-            in.read_long(); // read in and ignore Enum ordinal
-            final String name = (String) ((org.omg.CORBA_2_3.portable.InputStream) in).read_value(String.class);
-            @SuppressWarnings("unchecked")
-            final Enum<?> value = (Enum<?>) Enum.valueOf(enumType, name);
-            offsetMap.put(offset, value);
-            return value;
-        } catch (IndirectionException ex) {
-            return (Serializable) offsetMap.get(ex.offset);
+    protected final boolean isEnum() {
+        return true;
+    }
+
+    private FieldDescriptor nameField = null;
+    private FieldDescriptor ordinalField = null;
+
+    @Override
+    public final void init() {
+        super.init();
+        // Avoid doing anything that would cause the calculated classHash to change
+        for (FieldDescriptor f: _fields) {
+            if (f.java_name.equals("name")) {
+                nameField = f;
+            } else if (f.java_name.equals("ordinal")) {
+                ordinalField = f;
+            }
         }
     }
+
+    @Override
+    protected void defaultWriteValue(ObjectWriter writer, Serializable val) throws IOException {
+        checkInit();
+        if ((writer.yasfSet != null) && !!!writer.yasfSet.contains(Yasf.ENUM_FIXED)) {
+            // talking to an old yoko that expects an ordinal field to be written;
+            ordinalField.write(writer, val);
+        }
+        nameField.write(writer, val);
+    }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumSubclassDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumSubclassDescriptor.java
new file mode 100644
index 0000000..12c34c6
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumSubclassDescriptor.java
@@ -0,0 +1,105 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.yoko.rmi.impl;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Map;
+
+import org.apache.yoko.rmi.util.StringUtil;
+import org.omg.CORBA.portable.IndirectionException;
+import org.omg.CORBA.portable.InputStream;
+
+class EnumSubclassDescriptor extends ValueDescriptor {
+    @SuppressWarnings("rawtypes")
+    private final Class enumType;
+
+    EnumSubclassDescriptor(Class<?> type, TypeRepository repository) {
+        super(type, repository);
+        enumType = type;
+    }
+
+    static Class<?> getEnumType(Class<?> type) {
+        if (!!!Enum.class.isAssignableFrom(type)) throw new IllegalArgumentException(type.getName() + " is not an Enum");
+        while (!!!type.isEnum()) type = type.getSuperclass();
+        return type;
+    }
+
+    @Override
+    public final void init() {
+        super.init();
+        // Avoid doing anything that would cause the calculated classHash to change
+    }
+
+    @Override
+    protected final long getSerialVersionUID() {
+        return 0L;
+    }
+
+    @Override
+    protected final boolean isEnum() {
+        return true;
+    }
+
+    @Override
+    final public Serializable readValue(InputStream in, Map<Integer, Object> offsetMap, Integer offset) {
+        try {
+            // Shortcut to reading in just the 'name' field of java.lang.Enum
+            String name = null;
+            try {
+                name = (String) ((org.omg.CORBA_2_3.portable.InputStream) in).read_value(String.class);
+            } catch (org.omg.CORBA.MARSHAL e) {
+                // Problem probably due to ordinal field data being sent
+                // This should be resolved by the 'if (name == null) {' block below, so this
+                // exception can be safely discarded.
+            }
+            if (name == null) {
+                // ordinal field may have been sent, causing the read of the name field to fail
+                // If this is the case, the input stream cursor will now be at the start of where the
+                // name field is located (the 4 bytes of the ordinal having now been read in)
+                name = (String) ((org.omg.CORBA_2_3.portable.InputStream) in).read_value(String.class);
+            }
+
+            @SuppressWarnings("unchecked")
+            final Enum<?> value = (Enum<?>) Enum.valueOf(enumType, name);
+            offsetMap.put(offset, value);
+            return value;
+        } catch (IndirectionException ex) {
+            return (Serializable) offsetMap.get(ex.offset);
+        }
+    }
+
+    @Override
+    protected final void writeValue(ObjectWriter writer, Serializable val) throws IOException {
+        // Don't write out any fields in the Enum subclass
+        _super_descriptor.writeValue(writer, val);
+    }
+
+    @Override
+    public final boolean isChunked() {
+        // Always do chunking for subclasses of Enum - like it's custom marshalled
+        return true;
+    }
+
+    @Override
+    public final Serializable writeReplace(Serializable val) {
+        // Never allow the honoring of writeReplace on an Enum subclass
+        return val;
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ExceptionDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ExceptionDescriptor.java
index 0e2cd61..166a202 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ExceptionDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ExceptionDescriptor.java
@@ -18,25 +18,16 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class ExceptionDescriptor extends ValueDescriptor {
+class ExceptionDescriptor extends ValueDescriptor {
     ExceptionDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
 
-    String ex_repid = null;
+    private volatile String ex_repid = null;
 
-    public String getExceptionRepositoryID() {
-        if (ex_repid == null) {
-            init_repid();
-        }
-
-        return ex_repid;
-    }
-
-    void init_repid() {
-        Class type = getJavaClass();
-        String name = type.getName();
-        String encname = null;
+    private String genExceptionRepId() {
+        String name = _java_class.getName();
+        final String encname;
 
         if (name.endsWith("Exception")) {
             encname = name.substring(0, name.length() - 7);
@@ -44,7 +35,11 @@
             encname = name + "Ex";
         }
 
-        ex_repid = "IDL:" + encname.replace('.', '/') + ":1.0";
+        return String.format("IDL:%s:1.0", encname.replace('.', '/'));
     }
 
+    public final String getExceptionRepositoryID() {
+        if (ex_repid == null) ex_repid = genExceptionRepId();
+        return ex_repid;
+    }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDEnumDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDEnumDescriptor.java
new file mode 100644
index 0000000..9c7de4f
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDEnumDescriptor.java
@@ -0,0 +1,57 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.yoko.rmi.impl;
+
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.ValueDefPackage.FullValueDescription;
+
+class FVDEnumDescriptor extends EnumDescriptor {
+    private final FullValueDescription fvd;
+    private final String repid;
+
+    FVDEnumDescriptor(FullValueDescription fvd, Class clazz, TypeRepository rep, String repid, ValueDescriptor super_desc) {
+        super(clazz, rep);
+        this.fvd = fvd;
+        this.repid = repid;
+
+        init();
+
+        _super_descriptor = super_desc;
+    }
+
+    @Override
+    protected String genRepId() {
+        return repid;
+    }
+
+    @Override
+    FullValueDescription getFullValueDescription() {
+        return fvd;
+    }
+
+    @Override
+    TypeCode getTypeCode() {
+        return fvd.type;
+    }
+
+    @Override
+    public boolean isCustomMarshalled() {
+        return fvd.is_custom;
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDEnumSubclassDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDEnumSubclassDescriptor.java
new file mode 100644
index 0000000..9d8f2c3
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDEnumSubclassDescriptor.java
@@ -0,0 +1,59 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.yoko.rmi.impl;
+
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.ValueDefPackage.FullValueDescription;
+
+import java.util.Objects;
+
+class FVDEnumSubclassDescriptor extends EnumSubclassDescriptor {
+    private final FullValueDescription fvd;
+    private final String repid;
+
+    FVDEnumSubclassDescriptor(FullValueDescription fvd, Class clazz, TypeRepository rep, String repid, ValueDescriptor super_desc) {
+        super(EnumSubclassDescriptor.getEnumType(clazz), rep);
+        this.fvd = fvd;
+        this.repid = repid;
+
+        init();
+
+        _super_descriptor = super_desc;
+    }
+
+    @Override
+    protected String genRepId() {
+        return repid;
+    }
+
+    @Override
+    FullValueDescription getFullValueDescription() {
+        return fvd;
+    }
+
+    @Override
+    TypeCode getTypeCode() {
+        return fvd.type;
+    }
+
+    @Override
+    public boolean isCustomMarshalled() {
+        return fvd.is_custom;
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDValueDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDValueDescriptor.java
index 5c20871..ad379af 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDValueDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FVDValueDescriptor.java
@@ -24,7 +24,7 @@
 /**
  * @author krab
  */
-public class FVDValueDescriptor extends ValueDescriptor {
+class FVDValueDescriptor extends ValueDescriptor {
     FullValueDescription fvd;
 
     String repid;
@@ -64,8 +64,8 @@
     FieldDescriptor findField(ValueMember valueMember) {
         FieldDescriptor result = null;
 
-        for (Class c = getJavaClass(); c != null; c = c.getSuperclass()) {
-            TypeDescriptor td = getTypeRepository().getDescriptor(c);
+        for (Class c = _java_class; c != null; c = c.getSuperclass()) {
+            TypeDescriptor td = repo.getDescriptor(c);
             if (td instanceof ValueDescriptor) {
                 ValueDescriptor vd = (ValueDescriptor) td;
                 FieldDescriptor[] fds = vd._fields;
@@ -85,12 +85,8 @@
         return result;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.yoko.rmi.impl.TypeDescriptor#getRepositoryID()
-     */
-    public String getRepositoryID() {
+    @Override
+    protected String genRepId() {
         return repid;
     }
 
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FieldDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FieldDescriptor.java
index 87f37da..c4b1e89 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FieldDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FieldDescriptor.java
@@ -28,8 +28,7 @@
 
 import org.omg.CORBA.ValueMember;
 
-public abstract class FieldDescriptor extends ModelElement implements
-Comparable {
+abstract class FieldDescriptor extends ModelElement implements Comparable {
     static Logger logger = Logger.getLogger(FieldDescriptor.class.getName());
 
     org.apache.yoko.rmi.util.corba.Field field;
@@ -45,10 +44,10 @@
     boolean isPublic;
 
     protected FieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
+            java.lang.reflect.Field f, TypeRepository repo) {
+        super(repo, name);
         this.type = type;
-        setJavaName(name);
-        setIDLName(name);
+        init();
         declaringClass = owner;
 
         if (f != null) {
@@ -62,6 +61,11 @@
         }
     }
 
+    @Override
+    protected final String genIDLName() {
+        return java_name;
+    }
+
     ValueMember getValueMember(TypeRepository rep) {
         if (valuemember == null) {
             TypeDescriptor desc = rep.getDescriptor(type);
@@ -97,7 +101,7 @@
         //
         // fields of the same kind are ordered lexicographically
         //	
-        return getJavaName().compareTo(desc.getJavaName());
+        return java_name.compareTo(desc.java_name);
     }
 
     public boolean isPrimitive() {
@@ -118,11 +122,11 @@
 
     abstract void copyState(Object orig, Object copy, CopyState state);
 
-    static FieldDescriptor get(java.lang.reflect.Field f) {
-        return get(f.getDeclaringClass(), f.getType(), f.getName(), f);
+    static FieldDescriptor get(java.lang.reflect.Field f, TypeRepository repository) {
+        return get(f.getDeclaringClass(), f.getType(), f.getName(), f, repository);
     }
 
-    static FieldDescriptor get(Class declaringClass, ObjectStreamField field) {
+    static FieldDescriptor get(Class declaringClass, ObjectStreamField field, TypeRepository repository) {
         Field f = null;
         try {
             f = declaringClass.getDeclaredField(field.getName());
@@ -131,71 +135,77 @@
                     + "\" for class \"" + declaringClass.getName() + "\""
                     + "\n" + ex, ex);
         }
-        return get(declaringClass, field.getType(), field.getName(), f);
+        return get(declaringClass, field.getType(), field.getName(), f, repository);
     }
 
     static FieldDescriptor get(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
+                               java.lang.reflect.Field f, TypeRepository repository) {
+        FieldDescriptor desc = get0(owner, type, name, f, repository);
+        desc.init();
+        return desc;
+    }
+
+    private static FieldDescriptor get0(Class owner, Class type, String name,
+            java.lang.reflect.Field f, TypeRepository repository) {
 
         if (type.isPrimitive()) {
             if (type == Boolean.TYPE) {
-                return new BooleanFieldDescriptor(owner, type, name, f);
+                return new BooleanFieldDescriptor(owner, type, name, f, repository);
             } else if (type == Byte.TYPE) {
-                return new ByteFieldDescriptor(owner, type, name, f);
+                return new ByteFieldDescriptor(owner, type, name, f, repository);
             } else if (type == Short.TYPE) {
-                return new ShortFieldDescriptor(owner, type, name, f);
+                return new ShortFieldDescriptor(owner, type, name, f, repository);
             } else if (type == Character.TYPE) {
-                return new CharFieldDescriptor(owner, type, name, f);
+                return new CharFieldDescriptor(owner, type, name, f, repository);
             } else if (type == Integer.TYPE) {
-                return new IntFieldDescriptor(owner, type, name, f);
+                return new IntFieldDescriptor(owner, type, name, f, repository);
             } else if (type == Long.TYPE) {
-                return new LongFieldDescriptor(owner, type, name, f);
+                return new LongFieldDescriptor(owner, type, name, f, repository);
             } else if (type == Float.TYPE) {
-                return new FloatFieldDescriptor(owner, type, name, f);
+                return new FloatFieldDescriptor(owner, type, name, f, repository);
             } else if (type == Double.TYPE) {
-                return new DoubleFieldDescriptor(owner, type, name, f);
+                return new DoubleFieldDescriptor(owner, type, name, f, repository);
             } else {
                 throw new RuntimeException("unknown field type " + type);
             }
 
         } else {
             if(org.omg.CORBA.Object.class.isAssignableFrom(type)) {
-                return new CorbaObjectFieldDescriptor(owner, type, name, f);
+                return new CorbaObjectFieldDescriptor(owner, type, name, f, repository);
             }
             if (java.lang.Object.class.equals(type)
                     || java.io.Externalizable.class.equals(type)
                     || java.io.Serializable.class.equals(type)) {
-                return new AnyFieldDescriptor(owner, type, name, f);
+                return new AnyFieldDescriptor(owner, type, name, f,repository);
 
             } else if (java.rmi.Remote.class.isAssignableFrom(type) 
                     || java.rmi.Remote.class.equals(type))
             {
-                return new RemoteFieldDescriptor(owner, type, name, f);
+                return new RemoteFieldDescriptor(owner, type, name, f, repository);
 
             } else if (String.class.equals(type)) {
-                return new StringFieldDescriptor(owner, type, name, f);
+                return new StringFieldDescriptor(owner, type, name, f, repository);
 
             } else if (java.io.Serializable.class.isAssignableFrom(type)) {
-                return new ValueFieldDescriptor(owner, type, name, f);
+                return new ValueFieldDescriptor(owner, type, name, f, repository);
             } else if (type.isInterface() && type.getMethods().length > 0) {
                 // interface classes that define methods 
-                return new ValueFieldDescriptor(owner, type, name, f);
+                return new ValueFieldDescriptor(owner, type, name, f, repository);
             } else {
-                return new ObjectFieldDescriptor(owner, type, name, f);
+                return new ObjectFieldDescriptor(owner, type, name, f, repository);
             }
         }
     }
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
-        pw.print(getJavaName());
+        pw.print(java_name);
         pw.print("=");
         try {
             Object obj = field.get(val);
             if (obj == null) {
                 pw.print("null");
             } else {
-                TypeDescriptor desc = getTypeRepository().getDescriptor(
-                        obj.getClass());
+                TypeDescriptor desc = repo.getDescriptor(obj.getClass());
                 desc.print(pw, recurse, obj);
             }
         } catch (IllegalAccessException ex) {
@@ -212,8 +222,8 @@
     Class interfaceType;
 
     RemoteFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
 
         if (type.isInterface()) {
             interfaceType = type;
@@ -289,14 +299,14 @@
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         java.rmi.Remote value = (java.rmi.Remote) reader
                 .readRemoteObject(interfaceType);
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        java.rmi.Remote value = (java.rmi.Remote) map.get(getJavaName());
+        java.rmi.Remote value = (java.rmi.Remote) map.get(java_name);
         writer.writeRemoteObject(value);
     }
 
@@ -309,8 +319,8 @@
     boolean narrowValue;
 
     AnyFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
         narrowValue = java.rmi.Remote.class.isAssignableFrom(type);
     }
 
@@ -369,14 +379,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         org.omg.CORBA.Any value = (org.omg.CORBA.Any) reader.readAny();
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        org.omg.CORBA.Any value = (org.omg.CORBA.Any) map.get(getJavaName());
+        org.omg.CORBA.Any value = (org.omg.CORBA.Any) map.get(java_name);
         writer.writeAny(value);
     }
 
@@ -384,8 +394,8 @@
 
 class ValueFieldDescriptor extends FieldDescriptor {
     ValueFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -431,7 +441,7 @@
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         java.io.Serializable value = (java.io.Serializable) reader
                 .readValueObject();
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
@@ -439,7 +449,7 @@
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
         java.io.Serializable value = (java.io.Serializable) map
-                .get(getJavaName());
+                .get(java_name);
         writer.writeValueObject(value);
     }
 
@@ -447,8 +457,8 @@
 
 class StringFieldDescriptor extends FieldDescriptor {
     StringFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -483,14 +493,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         String value = (String) reader.readValueObject();
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        String value = (String) map.get(getJavaName());
+        String value = (String) map.get(java_name);
         writer.writeValueObject(value);
     }
 
@@ -498,8 +508,8 @@
 
 class ObjectFieldDescriptor extends FieldDescriptor {
     ObjectFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -545,14 +555,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Object value = (Object) reader.readAbstractObject();
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Object value = (Object) map.get(getJavaName());
+        Object value = (Object) map.get(java_name);
         writer.writeObject(value);
     }
 
@@ -560,8 +570,8 @@
 
 class BooleanFieldDescriptor extends FieldDescriptor {
     BooleanFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -601,7 +611,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             pw.print(field.getBoolean(val));
         } catch (IllegalAccessException ex) {
@@ -613,14 +623,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Boolean value = new Boolean(reader.readBoolean());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Boolean value = (Boolean) map.get(getJavaName());
+        Boolean value = (Boolean) map.get(java_name);
         if (value == null) {
             writer.writeBoolean(false);
         } else {
@@ -632,8 +642,8 @@
 
 class ByteFieldDescriptor extends FieldDescriptor {
     ByteFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -673,7 +683,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             pw.print(field.getByte(val));
         } catch (IllegalAccessException ex) {
@@ -685,14 +695,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Byte value = new Byte(reader.readByte());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Byte value = (Byte) map.get(getJavaName());
+        Byte value = (Byte) map.get(java_name);
         if (value == null) {
             writer.writeByte(0);
         } else {
@@ -704,8 +714,8 @@
 
 class ShortFieldDescriptor extends FieldDescriptor {
     ShortFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -745,7 +755,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             pw.print(field.getShort(val));
         } catch (IllegalAccessException ex) {
@@ -757,14 +767,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Short value = new Short(reader.readShort());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Short value = (Short) map.get(getJavaName());
+        Short value = (Short) map.get(java_name);
         if (value == null) {
             writer.writeShort(0);
         } else {
@@ -776,8 +786,8 @@
 
 class CharFieldDescriptor extends FieldDescriptor {
     CharFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -817,7 +827,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             char ch = field.getChar(val);
             pw.print(ch);
@@ -833,14 +843,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Character value = new Character(reader.readChar());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Character value = (Character) map.get(getJavaName());
+        Character value = (Character) map.get(java_name);
         if (value == null) {
             writer.writeChar(0);
         } else {
@@ -852,8 +862,8 @@
 
 class IntFieldDescriptor extends FieldDescriptor {
     IntFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -894,7 +904,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             pw.print(field.getInt(val));
         } catch (IllegalAccessException ex) {
@@ -906,14 +916,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Integer value = new Integer(reader.readInt());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Integer value = (Integer) map.get(getJavaName());
+        Integer value = (Integer) map.get(java_name);
         if (value == null) {
             writer.writeInt(0);
         } else {
@@ -925,8 +935,8 @@
 
 class LongFieldDescriptor extends FieldDescriptor {
     LongFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -967,7 +977,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             pw.print(field.getLong(val));
         } catch (IllegalAccessException ex) {
@@ -979,14 +989,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Long value = new Long(reader.readLong());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Long value = (Long) map.get(getJavaName());
+        Long value = (Long) map.get(java_name);
         if (value == null) {
             writer.writeLong(0);
         } else {
@@ -998,8 +1008,8 @@
 
 class FloatFieldDescriptor extends FieldDescriptor {
     FloatFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -1039,7 +1049,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             pw.print(field.getFloat(val));
         } catch (IllegalAccessException ex) {
@@ -1051,14 +1061,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Float value = new Float(reader.readFloat());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Float value = (Float) map.get(getJavaName());
+        Float value = (Float) map.get(java_name);
         if (value == null) {
             writer.writeFloat(0.0F);
         } else {
@@ -1070,8 +1080,8 @@
 
 class DoubleFieldDescriptor extends FieldDescriptor {
     DoubleFieldDescriptor(Class owner, Class type, String name,
-            java.lang.reflect.Field f) {
-        super(owner, type, name, f);
+            java.lang.reflect.Field f, TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     public void read(ObjectReader reader, Object obj)
@@ -1111,7 +1121,7 @@
 
     void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
         try {
-            pw.print(getJavaName());
+            pw.print(java_name);
             pw.print("=");
             pw.print(field.getDouble(val));
         } catch (IllegalAccessException ex) {
@@ -1123,14 +1133,14 @@
      */
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Double value = new Double(reader.readDouble());
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
     }
 
     /**
      * @see org.apache.yoko.rmi.impl.FieldDescriptor#writeField(ObjectWriter, Map)
      */
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        Double value = (Double) map.get(getJavaName());
+        Double value = (Double) map.get(java_name);
         if (value == null) {
             writer.writeDouble(0.0D);
         } else {
@@ -1142,8 +1152,8 @@
 
 class CorbaObjectFieldDescriptor extends FieldDescriptor {
 
-    protected CorbaObjectFieldDescriptor(Class owner, Class type, String name, Field f) {
-        super(owner, type, name, f);
+    protected CorbaObjectFieldDescriptor(Class owner, Class type, String name, Field f,TypeRepository repository) {
+        super(owner, type, name, f, repository);
     }
 
     void copyState(final Object orig, final Object copy, CopyState state) {
@@ -1175,7 +1185,7 @@
 
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
         Object value = reader.readCorbaObject(null);
-        map.put(getJavaName(), value);
+        map.put(java_name, value);
 
     }
 
@@ -1189,7 +1199,7 @@
     }
 
     void writeFieldFromMap(ObjectWriter writer, Map map) throws IOException {
-        org.omg.CORBA.Object value = (org.omg.CORBA.Object) map.get(getJavaName());
+        org.omg.CORBA.Object value = (org.omg.CORBA.Object) map.get(java_name);
         writer.writeCorbaObject(value);
 
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FloatDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FloatDescriptor.java
index 271d272..a28eea0 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FloatDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/FloatDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class FloatDescriptor extends SimpleDescriptor {
+final class FloatDescriptor extends SimpleDescriptor {
     FloatDescriptor(TypeRepository repository) {
         super(Float.TYPE, repository, "float", org.omg.CORBA.TCKind.tk_float);
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IDLEntityDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IDLEntityDescriptor.java
index 442f724..11dc546 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IDLEntityDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IDLEntityDescriptor.java
@@ -23,7 +23,7 @@
 
 import org.omg.CORBA.MARSHAL;
 
-public class IDLEntityDescriptor extends ValueDescriptor {
+class IDLEntityDescriptor extends ValueDescriptor {
     Method _read_method;
 
     Method _write_method;
@@ -51,7 +51,7 @@
         super.init();
 
         try {
-            final Class type = getJavaClass();
+            final Class type = _java_class;
             final String helperName = type.getName() + "Helper";
             final Class helperClass = javax.rmi.CORBA.Util.loadClass(
                     helperName, null, type.getClassLoader());
@@ -98,7 +98,7 @@
 
         } catch (ClassNotFoundException ex) {
             throw new RuntimeException("cannot load IDL Helper class for "
-                    + getJavaClass(), ex);
+                    + _java_class, ex);
         }
     }
     
@@ -119,7 +119,7 @@
         // the CORBA Object interface are actual corba objects, and must be handled that way. 
         // Other IDLEntity classes are just transmitted by value. 
         if (isCorba) {
-            return _in.read_Object(getJavaClass()); 
+            return _in.read_Object(_java_class);
         }
         else {
 
@@ -142,7 +142,7 @@
 
     public Object readValue(org.omg.CORBA.portable.InputStream in) {
         if (isAbstract) {
-            throw new MARSHAL("IDL Entity " + getJavaClass().getName()
+            throw new MARSHAL("IDL Entity " + _java_class.getName()
                     + " is abstract");
         }
 
@@ -177,7 +177,7 @@
 
     public void writeValue(org.omg.CORBA.portable.OutputStream out, java.io.Serializable val) {
         if (isAbstract) {
-            throw new MARSHAL("IDL Entity " + getJavaClass().getName()
+            throw new MARSHAL("IDL Entity " + _java_class.getName()
                     + " is abstract");
         }
 
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IntegerDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IntegerDescriptor.java
index ce67d33..1649929 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IntegerDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/IntegerDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class IntegerDescriptor extends SimpleDescriptor {
+final class IntegerDescriptor extends SimpleDescriptor {
     IntegerDescriptor(TypeRepository repository) {
         super(Integer.TYPE, repository, "long", org.omg.CORBA.TCKind.tk_long);
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/LongDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/LongDescriptor.java
index 39e3b71..7b6e417 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/LongDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/LongDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class LongDescriptor extends SimpleDescriptor {
+final class LongDescriptor extends SimpleDescriptor {
     LongDescriptor(TypeRepository repository) {
         super(Long.TYPE, repository, "long_long",
                 org.omg.CORBA.TCKind.tk_longlong);
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/MethodDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/MethodDescriptor.java
index dbde88c..16f1a51 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/MethodDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/MethodDescriptor.java
@@ -69,9 +69,8 @@
     }
 
     MethodDescriptor(java.lang.reflect.Method method, TypeRepository repository) {
+        super(repository, method.getName());
         reflected_method = method;
-        setTypeRepository(repository);
-        setJavaName(method.getName());
     }
 
     /** The number of arguments */
@@ -121,7 +120,7 @@
             }
 
         } else if (copyWithinState) {
-            CopyState state = new CopyState(getTypeRepository());
+            CopyState state = new CopyState(repo);
             for (int i = 0; i < args.length; i++) {
                 if (parameter_types[i].copyWithinState()) {
                     try {
@@ -167,7 +166,7 @@
             }
 
         } else if (copyWithinState) {
-            CopyState state = new CopyState(getTypeRepository());
+            CopyState state = new CopyState(repo);
             try {
                 return state.copy(result);
             } catch (CopyRecursionException e) {
@@ -227,7 +226,7 @@
     public org.omg.CORBA.portable.OutputStream writeException(
             org.omg.CORBA.portable.ResponseHandler response, Throwable ex) {
         for (int i = 0; i < exception_types.length; i++) {
-            if (exception_types[i].getJavaClass().isInstance(ex)) {
+            if (exception_types[i]._java_class.isInstance(ex)) {
                 org.omg.CORBA.portable.OutputStream out = response
                         .createExceptionReply();
                 org.omg.CORBA_2_3.portable.OutputStream out2 = (org.omg.CORBA_2_3.portable.OutputStream) out;
@@ -330,8 +329,7 @@
 
         for (int i = 0; i < param_types.length; i++) {
             try {
-                parameter_types[i] = getTypeRepository().getDescriptor(
-                        param_types[i]);
+                parameter_types[i] = repo.getDescriptor(param_types[i]);
                 copyWithinState |= parameter_types[i].copyWithinState();
 
             } catch (RuntimeException ex) {
@@ -340,20 +338,20 @@
         }
 
         Class result_type = reflected_method.getReturnType();
-        return_type = getTypeRepository().getDescriptor(result_type);
+        return_type = repo.getDescriptor(result_type);
 
         Class[] exc_types = reflected_method.getExceptionTypes();
         exception_types = new ExceptionDescriptor[exc_types.length];
         for (int i = 0; i < exc_types.length; i++) {
-            exception_types[i] = (ExceptionDescriptor) getTypeRepository()
-                    .getDescriptor(exc_types[i]);
+            exception_types[i] = (ExceptionDescriptor) repo.getDescriptor(exc_types[i]);
         }
 
         parameter_count = param_types.length;
-        generateIDLName();
+        super.init();
     }
 
-    void generateIDLName() {
+    @Override
+    protected String genIDLName() {
         String idl_name = null;
 
         if (isSetterMethod()) {
@@ -361,7 +359,7 @@
         } else if (isGetterMethod()) {
             idl_name = "_get_" + transformIdentifier(attributeName());
         } else {
-            idl_name = transformIdentifier(getJavaName());
+            idl_name = transformIdentifier(java_name);
         }
 
         if (isCaseSensitive) {
@@ -371,12 +369,11 @@
         if (isOverloaded) {
             idl_name = transformOverloading(idl_name);
         }
-
-        setIDLName(idl_name);
+        return idl_name;
     }
 
     private String attributeName() {
-        String methodName = getJavaName();
+        String methodName = java_name;
         StringBuffer buf = new StringBuffer();
 
         int pfxLen;
@@ -542,7 +539,7 @@
         writeJavaType(pw, reflected_method.getReturnType());
 
         pw.print(' ');
-        pw.print(getJavaName());
+        pw.print(java_name);
 
         pw.print(" (");
         Class[] args = reflected_method.getParameterTypes();
@@ -597,7 +594,7 @@
 
         Class[] args = reflected_method.getParameterTypes();
         for (int i = 0; i < args.length; i++) {
-            TypeDescriptor desc = getTypeRepository().getDescriptor(args[i]);
+            TypeDescriptor desc = repo.getDescriptor(args[i]);
             pw.print("\t\t\t");
             desc.writeMarshalValue(pw, "out", "arg" + i);
             pw.println(";");
@@ -613,7 +610,7 @@
             writeJavaType(pw, rtype);
             pw.print(")");
 
-            TypeDescriptor desc = getTypeRepository().getDescriptor(rtype);
+            TypeDescriptor desc = repo.getDescriptor(rtype);
             desc.writeUnmarshalValue(pw, "in");
             pw.println(";");
         }
@@ -631,8 +628,7 @@
                 continue;
             }
 
-            ExceptionDescriptor exd = (ExceptionDescriptor) getTypeRepository()
-                    .getDescriptor(ex[i]);
+            ExceptionDescriptor exd = (ExceptionDescriptor) repo.getDescriptor(ex[i]);
 
             pw.println("\t\t\tif (exname.equals(\""
                     + exd.getExceptionRepositoryID() + "\"))");
@@ -676,7 +672,7 @@
         // copy arguments
         Class[] args = reflected_method.getParameterTypes();
         if (args.length == 1) {
-            if (getTypeRepository().getDescriptor(args[0]).copyInStub()) {
+            if (repo.getDescriptor(args[0]).copyInStub()) {
                 pw.print("\t\t\t\targ0 = (");
                 writeJavaType(pw, args[0]);
                 pw.println(")" + UTIL + ".copyObject(arg0, _orb());");
@@ -686,7 +682,7 @@
             int copyCount = 0;
 
             for (int i = 0; i < args.length; i++) {
-                TypeDescriptor td = getTypeRepository().getDescriptor(args[i]);
+                TypeDescriptor td = repo.getDescriptor(args[i]);
                 copy[i] = td.copyInStub();
                 if (copy[i]) {
                     copyCount += 1;
@@ -727,7 +723,7 @@
         pw.print("((");
         writeJavaType(pw, thisClass);
         pw.print(")so.servant).");
-        pw.print(getJavaName());
+        pw.print(java_name);
         pw.print("(");
 
         for (int i = 0; i < args.length; i++) {
@@ -741,7 +737,7 @@
 
         pw.print("\t\t\t\treturn ");
         if (out != Void.TYPE) {
-            TypeDescriptor td = getTypeRepository().getDescriptor(out);
+            TypeDescriptor td = repo.getDescriptor(out);
             if (td.copyInStub()) {
                 pw.print('(');
                 writeJavaType(pw, out);
@@ -761,22 +757,21 @@
     }
 
     void addDependencies(java.util.Set classes) {
-        TypeRepository rep = getTypeRepository();
 
         TypeDescriptor desc = null;
 
-        desc = rep.getDescriptor(reflected_method.getReturnType());
+        desc = repo.getDescriptor(reflected_method.getReturnType());
         desc.addDependencies(classes);
 
         Class[] param = reflected_method.getParameterTypes();
         for (int i = 0; i < param.length; i++) {
-            desc = rep.getDescriptor(param[i]);
+            desc = repo.getDescriptor(param[i]);
             desc.addDependencies(classes);
         }
 
         Class[] ex = reflected_method.getExceptionTypes();
         for (int i = 0; i < ex.length; i++) {
-            desc = rep.getDescriptor(ex[i]);
+            desc = repo.getDescriptor(ex[i]);
             desc.addDependencies(classes);
         }
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ModelElement.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ModelElement.java
index 703d6b5..a3fd62e 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ModelElement.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ModelElement.java
@@ -18,51 +18,29 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class ModelElement {
-    protected String idl_name;        // fully resolved package name
-    protected String type_name = "";       // the simple type name (minus package, if any)
-    protected String package_name = "";    // the package name qualifier (if any)
-    protected String java_name;       // the java name of the type 
+abstract class ModelElement {
+    final TypeRepository repo;
+    final String java_name;    // the java name of the type
+    private String idl_name;   // fully resolved package name
+    private volatile boolean notInit = true;
 
-    protected void setIDLName(String name) {
-        idl_name = name;
+    protected ModelElement(TypeRepository repo, String java_name) {
+        this.repo = repo;
+        this.java_name = java_name;
     }
-    
+
+    protected void init() {
+        idl_name = genIDLName();
+        notInit = false;
+    }
+
+    protected abstract String genIDLName();
+
+    final void checkInit() {
+        if (notInit) throw new IllegalStateException("Not initialized: " + java_name);
+    }
     public String getIDLName() {
+        checkInit();
         return idl_name;
     }
-
-    protected void setTypeName(String name) {
-        type_name = name;
-    }
-    
-    public String getTypeName() {
-        return type_name;
-    }
-
-    protected void setPackageName(String name) {
-        package_name = name;
-    }
-    
-    public String getPackageName() {
-        return package_name;
-    }
-
-    protected void setJavaName(String name) {
-        java_name = name;
-    }
-
-    public String getJavaName() {
-        return java_name;
-    }
-
-    protected TypeRepository repository;
-
-    protected void setTypeRepository(TypeRepository repository) {
-        this.repository = repository;
-    }
-
-    public TypeRepository getTypeRepository() {
-        return repository;
-    }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectWriter.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectWriter.java
index 6a14da2..9d9a5f5 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectWriter.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectWriter.java
@@ -28,8 +28,11 @@
 import java.lang.reflect.Method;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.yoko.util.cmsf.CmsfThreadLocal;
+import org.apache.yoko.util.yasf.Yasf;
+import org.apache.yoko.util.yasf.YasfThreadLocal;
 
 abstract class ObjectWriter extends ObjectOutputStream {
     protected final Serializable object;
@@ -40,7 +43,8 @@
 
     private WriteObjectState state = WriteObjectState.NOT_IN_WRITE_OBJECT;
 
-    private byte streamFormatVersion = 1;
+    final byte cmsf;
+    final Set<Yasf> yasfSet;
 
     private enum WriteObjectState {
         NOT_IN_WRITE_OBJECT {
@@ -58,7 +62,7 @@
                 // If we're in stream format version 2, we must
                 // put the "null" marker to say that there isn't
                 // any optional data
-                if (writer.getStreamFormatVersion() == 2) {
+                if (writer.cmsf == 2) {
                     writer._nullValue();
                 }
             }
@@ -74,7 +78,7 @@
                 // writeDefaultObject was not invoked
                 writer.writeBoolean(false);
 
-                if (writer.getStreamFormatVersion() == 2) {
+                if (writer.cmsf == 2) {
                     writer._startValue(writer._desc.getCustomRepositoryID());
                 }
             }
@@ -92,7 +96,7 @@
 
                 // write a null-marker to identify that there is no custom
                 // state being marshalled...
-                if (writer.getStreamFormatVersion() == 2) {
+                if (writer.cmsf == 2) {
                     writer._nullValue();
                 }
             }
@@ -102,14 +106,14 @@
                 // been emitted in IN_WRITE_OBJECT.beforeWriteDefaultObject
                 writer.state = WROTE_CUSTOM_DATA;
 
-                if (writer.getStreamFormatVersion() == 2) {
+                if (writer.cmsf == 2) {
                     writer._startValue(writer._desc.getCustomRepositoryID());
                 }
             }
         },
         WROTE_CUSTOM_DATA {
             void afterWriteObject(ObjectWriter writer) throws IOException {
-                if (writer.getStreamFormatVersion() == 2) {
+                if (writer.cmsf == 2) {
                     writer._endValue();
                 }
 
@@ -144,11 +148,8 @@
 
     ObjectWriter(Serializable obj) throws IOException {
         object = obj;
-        streamFormatVersion = CmsfThreadLocal.get();
-    }
-
-    private byte getStreamFormatVersion() {
-        return streamFormatVersion;
+        cmsf = CmsfThreadLocal.get();
+        yasfSet = YasfThreadLocal.get();
     }
 
     abstract ObjectReader getObjectReader(Object newObject);
@@ -282,7 +283,7 @@
         state = WriteObjectState.NOT_IN_WRITE_OBJECT;
         try {
             setCurrentValueDescriptor(descriptor);
-            writeByte(getStreamFormatVersion());
+            writeByte(cmsf);
             state.beforeWriteObject(this);
             _write_object_method.invoke(val, this);
             state.afterWriteObject(this);
@@ -299,7 +300,7 @@
     protected abstract void _nullValue() throws IOException;
 
     void invokeWriteExternal(Externalizable externalizable) throws IOException {
-        writeByte(getStreamFormatVersion());
+        writeByte(cmsf);
         externalizable.writeExternal(this);
     }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIServant.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIServant.java
index 28d773b..e70afe6 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIServant.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIServant.java
@@ -39,7 +39,7 @@
     byte[] _id;
 
     Class getJavaClass() {
-        return _descriptor.getJavaClass();
+        return _descriptor._java_class;
     }
 
     RMIState getRMIState() {
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubDescriptor.java
index 09332cd..4cd36cc 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubDescriptor.java
@@ -18,42 +18,22 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class RMIStubDescriptor extends ValueDescriptor {
+class RMIStubDescriptor extends ValueDescriptor {
     RMIStubDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
 
-    String stub_repid = null;
-
-    public String getRepositoryID() {
-        if (stub_repid == null) {
-            init_repid();
-        }
-
-        return stub_repid;
-    }
-
-    void init_repid() {
-        Class type = getJavaClass();
-
-        Class[] ifaces = type.getInterfaces();
-
+    @Override
+    protected String genRepId() {
+        final Class[] ifaces = _java_class.getInterfaces();
         if (ifaces.length != 2 || ifaces[1] != org.apache.yoko.rmi.util.stub.Stub.class) {
             throw new RuntimeException("Unexpected RMIStub structure");
         }
 
-        String ifname = ifaces[0].getName();
-        String stubClassName = null;
-
-        int idx = ifname.lastIndexOf('.');
-        if (idx == -1) {
-            stubClassName = "_" + ifname + "_Stub";
-        } else {
-            stubClassName = ifname.substring(0, idx + 1) + "_"
-                    + ifname.substring(idx + 1) + "_Stub";
-        }
-
-        stub_repid = "RMI:" + stubClassName + ":0";
+        final String ifname = ifaces[0].getName();
+        final int idx = ifname.lastIndexOf('.');
+        return ((idx < 0) ? String.format("RMI:_%s_Stub:0", ifname) :
+                String.format("RMI:%s_%s_Stub:0", ifname.substring(0, idx + 1), ifname.substring(idx + 1)));
     }
 
     //
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubHandler.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubHandler.java
index 74f4c06..d0855be 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubHandler.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStubHandler.java
@@ -42,7 +42,7 @@
     static final RMIStubHandler instance = new RMIStubHandler();
 
     public Object stubWriteReplace(RMIStub stub) {
-    Class type = stub._descriptor.getJavaClass();
+        Class type = stub._descriptor._java_class;
     return new org.apache.yoko.rmi.impl.RMIPersistentStub(stub, type);
     }
     
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteClassDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteClassDescriptor.java
index 4d86d50..c660417 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteClassDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteClassDescriptor.java
@@ -18,17 +18,14 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class RemoteClassDescriptor extends RemoteDescriptor {
+class RemoteClassDescriptor extends RemoteDescriptor {
 
-    public String getRepositoryID() {
-        return "IDL:" + getJavaClass().getName().replace('.', '/') + ":1.0";
+    @Override
+    protected String genRepId() {
+        return String.format("IDL:%s:1.0", _java_class.getName().replace('.', '/'));
     }
 
     RemoteClassDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
-
-    public void init() {
-        super.init();
-    }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteDescriptor.java
index fd44426..5e91b4b 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteDescriptor.java
@@ -34,7 +34,7 @@
 
 import javax.rmi.PortableRemoteObject;
 
-public abstract class RemoteDescriptor extends TypeDescriptor {
+abstract class RemoteDescriptor extends TypeDescriptor {
     private java.util.Map method_map;
 
     private java.util.Map refl_method_map;
@@ -54,15 +54,14 @@
         if (this instanceof RemoteInterfaceDescriptor) {
             result = (RemoteInterfaceDescriptor) this;
         } else {
-            Class[] remotes = collect_remote_interfaces(getJavaClass());
+            Class[] remotes = collect_remote_interfaces(_java_class);
             if (remotes.length == 0) {
-                throw new RuntimeException(getJavaClass().getName()
+                throw new RuntimeException(_java_class.getName()
                         + " has no remote interfaces");
             }
             Class most_specific_interface = remotes[0];
 
-            result = (RemoteInterfaceDescriptor) repository
-                    .getDescriptor(most_specific_interface);
+            result = (RemoteInterfaceDescriptor)repo.getDescriptor(most_specific_interface);
         }
 
         setRemoteInterface(result);
@@ -80,11 +79,11 @@
 
     public String[] all_interfaces() {
         if (_ids == null) {
-            Class[] ifaces = collect_remote_interfaces(getJavaClass());
+            Class[] ifaces = collect_remote_interfaces(_java_class);
             int len = ifaces.length;
             String[] ids = new String[len];
             for (int i = 0; i < len; i++) {
-                TypeDescriptor desc = repository.getDescriptor(ifaces[i]);
+                TypeDescriptor desc = repo.getDescriptor(ifaces[i]);
                 ids[i] = desc.getRepositoryID();
             }
 
@@ -111,7 +110,7 @@
 
     void debugMethodMap() {
         if (logger.isLoggable(Level.FINER)) {
-            logger.finer("METHOD MAP FOR " + getJavaClass().getName());
+            logger.finer("METHOD MAP FOR " + _java_class.getName());
 
             Iterator it = method_map.keySet().iterator();
             while (it.hasNext()) {
@@ -141,9 +140,6 @@
         super(type, repository);
     }
 
-    public void init() {
-    }
-
     public MethodDescriptor[] getMethods() {
         if (operations == null) {
             init_methods();
@@ -169,7 +165,7 @@
         ArrayList method_list = new ArrayList();
 
         // first step is to build the helpers for any super classes
-        Class[] supers = getJavaClass().getInterfaces();
+        Class[] supers = _java_class.getInterfaces();
         super_descriptors = new ArrayList();
 
         Map all_methods = new HashMap();
@@ -180,8 +176,7 @@
             if (!REMOTE_CLASS.equals(iface) && !OBJECT_CLASS.equals(iface)
                     && REMOTE_CLASS.isAssignableFrom(iface)
                     && iface.isInterface()) {
-                RemoteDescriptor superHelper = (RemoteDescriptor) repository
-                        .getDescriptor(iface);
+                RemoteDescriptor superHelper = (RemoteDescriptor)repo.getDescriptor(iface);
 
                 super_descriptors.add(superHelper);
 
@@ -217,9 +212,9 @@
         }
 
         for (int i = 0; i < methods.length; i++) {
-            MethodDescriptor op = new MethodDescriptor(methods[i], repository);
+            MethodDescriptor op = new MethodDescriptor(methods[i], repo);
 
-            String mname = op.getJavaName();
+            String mname = op.java_name;
 
             // is there another method that differs only in case?
             Set same_case_names = (Set) lower_case_names.get(mname.toLowerCase());
@@ -242,7 +237,7 @@
         method_map = new java.util.HashMap();
         for (int i = 0; i < method_list.size(); i++) {
             MethodDescriptor desc = (MethodDescriptor) method_list.get(i);
-            logger.finer("Adding method " + desc.getJavaName() + " to method map under " + desc.getIDLName()); 
+            logger.finer("Adding method " + desc.java_name + " to method map under " + desc.getIDLName());
             method_map.put(desc.getIDLName(), desc);
         }
 
@@ -271,7 +266,7 @@
     Method[] getLocalMethods() {
         ArrayList result = new ArrayList();
 
-        addNonRemoteInterfaceMethods(getJavaClass(), result);
+        addNonRemoteInterfaceMethods(_java_class, result);
 
         Method[] out = new Method[result.size()];
         result.toArray(out);
@@ -398,7 +393,7 @@
     /** Read an instance of this value from a CDR stream */
     public Object read(org.omg.CORBA.portable.InputStream in) {
         return javax.rmi.PortableRemoteObject.narrow(in.read_Object(),
-                getJavaClass());
+                _java_class);
     }
 
     /** Write an instance of this value to a CDR stream */
@@ -409,7 +404,7 @@
     org.omg.CORBA.TypeCode getTypeCode() {
         if (_type_code == null) {
             org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
-            return orb.create_interface_tc(getRepositoryID(), getJavaClass()
+            return orb.create_interface_tc(getRepositoryID(), _java_class
                     .getName());
         }
 
@@ -427,14 +422,14 @@
 
     void writeUnmarshalValue(java.io.PrintWriter pw, String inName) {
         pw.print('(');
-        pw.print(getJavaClass().getName());
+        pw.print(_java_class.getName());
         pw.print(')');
         pw.print(PortableRemoteObject.class.getName());
         pw.print(".narrow(");
         pw.print(inName);
         pw.print('.');
         pw.print("read_Object(),");
-        pw.print(getJavaClass().getName());
+        pw.print(_java_class.getName());
         pw.print(".class)");
     }
 
@@ -475,7 +470,7 @@
 
     void writeStubClass(java.io.PrintWriter pw) {
 
-        Class c = getJavaClass();
+        Class c = _java_class;
         String cname = c.getName();
         String fullname = stubClassName(c);
         //String stubname = fullname.substring(fullname.lastIndexOf('.') + 1);
@@ -520,7 +515,7 @@
     }
 
     String getStubClassName() {
-        Class c = getJavaClass();
+        Class c = _java_class;
         String cname = c.getName();
 
         String pkgname = null;
@@ -537,7 +532,7 @@
     }
 
     void addDependencies(Set classes) {
-        Class c = getJavaClass();
+        Class c = _java_class;
 
         if (c == java.rmi.Remote.class || classes.contains(c))
             return;
@@ -545,14 +540,13 @@
         classes.add(c);
 
         if (c.getSuperclass() != null) {
-            TypeDescriptor desc = getTypeRepository().getDescriptor(
-                    c.getSuperclass());
+            TypeDescriptor desc = repo.getDescriptor(c.getSuperclass());
             desc.addDependencies(classes);
         }
 
         Class[] ifaces = c.getInterfaces();
         for (int i = 0; i < ifaces.length; i++) {
-            TypeDescriptor desc = getTypeRepository().getDescriptor(ifaces[i]);
+            TypeDescriptor desc = repo.getDescriptor(ifaces[i]);
             desc.addDependencies(classes);
         }
 
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteInterfaceDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteInterfaceDescriptor.java
index 072fcee..72f8e91 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteInterfaceDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RemoteInterfaceDescriptor.java
@@ -18,13 +18,8 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class RemoteInterfaceDescriptor extends RemoteDescriptor {
+class RemoteInterfaceDescriptor extends RemoteDescriptor {
     RemoteInterfaceDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
-
-    public void init() {
-        super.init();
-    }
-
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ShortDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ShortDescriptor.java
index 6a3ce74..eb95f93 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ShortDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ShortDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class ShortDescriptor extends SimpleDescriptor {
+final class ShortDescriptor extends SimpleDescriptor {
     ShortDescriptor(TypeRepository repository) {
         super(Short.TYPE, repository, "short", org.omg.CORBA.TCKind.tk_short);
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/SimpleDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/SimpleDescriptor.java
index ada58a7..a30e822 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/SimpleDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/SimpleDescriptor.java
@@ -18,21 +18,32 @@
 
 package org.apache.yoko.rmi.impl;
 
-public abstract class SimpleDescriptor extends TypeDescriptor {
+abstract class SimpleDescriptor extends TypeDescriptor {
+    private final String idl_name;
     SimpleDescriptor(Class type, TypeRepository repository, String idl_name,
             org.omg.CORBA.TCKind tc) {
         super(type, repository);
-        setJavaName(type.getName());
-        setIDLName(idl_name);
-        // the simple type name is the same as the IDL name.  The 
-        // package name is null 
-        setTypeName(idl_name); 
-        setPackageName("");
+        this.idl_name = idl_name;
 
         org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
         _type_code = orb.get_primitive_tc(tc);
     }
 
+    @Override
+    protected String genIDLName() {
+        return idl_name;
+    }
+
+    @Override
+    protected String genPackageName() {
+        return "";
+    }
+
+    @Override
+    protected String genTypeName() {
+        return idl_name;
+    }
+
     org.omg.CORBA.TypeCode getTypeCode() {
         return _type_code;
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StringDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StringDescriptor.java
index 2ee1f00..9d5c38b 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StringDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StringDescriptor.java
@@ -18,20 +18,23 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class StringDescriptor extends ValueDescriptor {
+class StringDescriptor extends ValueDescriptor {
     public String getIDLName() {
         return "CORBA_WStringValue";
     }
     
     StringDescriptor(TypeRepository repository) {
         super(String.class, repository);
-        // strings have a special type and package name other than the java class name. 
-        setTypeName("WStringValue"); 
-        setPackageName("CORBA"); 
     }
 
-    public void init() {
-        super.init();
+    @Override
+    protected String genPackageName() {
+        return "CORBA";
+    }
+
+    @Override
+    protected String genTypeName() {
+        return "WStringValue";
     }
 
     /** Read an instance of this value from a CDR stream */
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 78303c9..33730f3 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
@@ -27,24 +27,32 @@
 
 import org.omg.CORBA.portable.InputStream;
 
-public abstract class TypeDescriptor extends ModelElement {
+abstract class TypeDescriptor extends ModelElement {
     static Logger logger = Logger.getLogger(TypeDescriptor.class.getName());
 
-    protected final Class _java_class;
+    final Class _java_class;
 
-    protected String _repid;
+    private volatile String _repid;
 
     protected RemoteInterfaceDescriptor remoteDescriptor;
 
     private FullKey _key;
 
-    public Class getJavaClass() {
-        return _java_class;
+    private String package_name;    // the package name qualifier (if any)
+    public String getPackageName() {
+        checkInit();
+        return package_name;
+    }
+
+    private String type_name;       // the simple type name (minus package, if any)
+    public String getTypeName() {
+        checkInit();
+        return type_name;
     }
 
     public final FullKey getKey() {
         if (null == _key) {
-            _key = new FullKey(getRepositoryID(), getJavaClass());
+            _key = new FullKey(getRepositoryID(), _java_class);
         }
         return _key;
     }
@@ -101,33 +109,43 @@
     @Override
     public String toString() {
         return String.format("%s{class=\"%s\",repId=\"%s\"}",
-                this.getClass().getName(), getJavaClass(),
+                this.getClass().getName(), _java_class,
                 getRepositoryID());
     }
 
     protected TypeDescriptor(Class type, TypeRepository repository) {
+        super(repository, type.getName());
         _java_class = type;
-        String typeName = type.getName(); 
-        setTypeRepository(repository);
-        setIDLName(typeName.replace('.', '_'));
-        // break up the simple type and package
-        int idx = typeName.lastIndexOf('.');
-        // if we have a package, split it into the component parts
-        if (idx >= 0) {
-            setPackageName(typeName.substring(0, idx));
-            setTypeName(typeName.substring(idx + 1));
-        }
-        else {
-            // no package...the type is the simple name
-            setPackageName(""); 
-            setTypeName(typeName); 
-        }
     }
 
-    public String getRepositoryID() {
-        if (_repid == null)
-            _repid = "RMI:" + getJavaClass().getName() + ":0000000000000000";
+    @Override
+    protected void init() {
+        package_name = genPackageName();
+        type_name = genTypeName();
+        super.init();
+    }
 
+    protected String genPackageName() {
+        int idx = java_name.lastIndexOf('.');
+        return ((idx < 0) ? "" : java_name.substring(0, idx));
+    }
+
+    protected String genTypeName() {
+        int idx = java_name.lastIndexOf('.');
+        return ((idx < 0) ? java_name : java_name.substring(idx + 1));
+    }
+
+    @Override
+    protected String genIDLName() {
+        return java_name.replace('.', '_');
+    }
+
+    protected String genRepId() {
+        return String.format("RMI:%s:%016X", _java_class.getName(), 0);
+    }
+
+    public final String getRepositoryID() {
+        if (_repid == null) _repid = genRepId();
         return _repid;
     }
 
@@ -146,9 +164,6 @@
     public abstract void write(org.omg.CORBA.portable.OutputStream out,
             Object val);
 
-    public void init() {
-    }
-
     public boolean isCustomMarshalled() {
         return false;
     }
@@ -273,7 +288,7 @@
             pw.print("^" + old);
         } else {
             Integer key = new Integer(System.identityHashCode(val));
-            pw.println(getJavaClass().getName() + "@"
+            pw.println(_java_class.getName() + "@"
                     + Integer.toHexString(key.intValue()));
         }
     }
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 ea1afce..6ad6894 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
@@ -118,8 +118,11 @@
                     return new IDLEntityDescriptor(type, repo);
                 } else if (Throwable.class.isAssignableFrom(type)) {
                     return new ExceptionDescriptor(type, repo);
-                } else if (Enum.class.isAssignableFrom(type) && (Enum.class != type)) {
+                } else if (Enum.class == type) {
                     return new EnumDescriptor(type, repo);
+                } else if (Enum.class.isAssignableFrom(type)) {
+                    Class<?> enumType = EnumSubclassDescriptor.getEnumType(type);
+                    return ((enumType == type) ? new EnumSubclassDescriptor(type, repo) : get(enumType));
                 } else if (type.isArray()) {
                     return ArrayDescriptor.get(type, repo);
                 } else if (!type.isInterface()
@@ -363,7 +366,14 @@
                     codebase);
         }
 
-        ValueDescriptor newDesc = new FVDValueDescriptor(fvd, clz, this, repid, super_desc);
+        final ValueDescriptor newDesc;
+        if ((super_desc != null) && super_desc.isEnum()) {
+            newDesc = new FVDEnumSubclassDescriptor(fvd, clz, this, repid, super_desc);
+        } else if (fvd.id.startsWith("RMI:java.lang.Enum:")) {
+            newDesc = new FVDEnumDescriptor(fvd, clz, this, repid, super_desc);
+        } else {
+            newDesc = new FVDValueDescriptor(fvd, clz, this, repid, super_desc);
+        }
         ConcurrentMap<String, ValueDescriptor> remoteDescMap = (clz == null) ? noTypeDescMap : fvdDescMaps.get(clz);
         clzdesc = remoteDescMap.putIfAbsent(newDesc.getRepositoryID(), newDesc);
         if (clzdesc == null) {
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/UtilImpl.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/UtilImpl.java
index 2131bb7..6343381 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/UtilImpl.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/UtilImpl.java
@@ -715,7 +715,7 @@
     static Object copyRMIStub(RMIStub stub) throws RemoteException {
         ClassLoader loader = getContextClassLoader();
 
-        if (getClassLoader(stub._descriptor.getJavaClass()) == loader) {
+        if (getClassLoader(stub._descriptor._java_class) == loader) {
             return stub;
         }
 
@@ -724,7 +724,7 @@
         Class<?> targetClass;
 
         try {
-            targetClass = Util.loadClass(desc.getJavaClass().getName(), stub
+            targetClass = Util.loadClass(desc._java_class.getName(), stub
                     ._get_codebase(), loader);
         } catch (ClassNotFoundException ex) {
             logger.log(Level.FINER, "copyRMIStub exception (current loader is: " + loader
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 636ee91..65e6465 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
@@ -70,11 +70,9 @@
 
 import sun.reflect.ReflectionFactory;
 
-public class ValueDescriptor extends TypeDescriptor {
+class ValueDescriptor extends TypeDescriptor {
     static final Logger logger = Logger.getLogger(ValueDescriptor.class.getName());
 
-    private boolean _is_enum;
-
     private boolean _is_externalizable;
 
     private boolean _is_serializable;
@@ -112,40 +110,24 @@
         super(type, repository);
     }
 
-    public String getRepositoryID() {
-        if (_repid == null) {
-            StringBuilder buf = new StringBuilder("RMI:");
-            buf.append(StringUtil.convertToValidIDLNames(getJavaClass().getName()));
-            buf.append(":");
+    protected boolean isEnum() { return false; }
 
-            String hashCode = Long.toHexString(_hash_code).toUpperCase();
-            for (int i = 0; (i + hashCode.length()) != 16; i++)
-                buf.append('0');
-            buf.append(hashCode);
-
-            long serialVersionUID = getSerialVersionUID();
-
-            buf.append(":");
-            String serialID = Long.toHexString(serialVersionUID).toUpperCase();
-            for (int i = 0; (i + serialID.length()) != 16; i++)
-                buf.append('0');
-            buf.append(serialID);
-
-            _repid = buf.toString();
-        }
-
-        return _repid;
+    @Override
+    protected String genRepId() {
+        return String.format("RMI:%s:%016X:%016X", StringUtil.convertToValidIDLNames(_java_class.getName()),
+                _hash_code, getSerialVersionUID());
     }
 
-    public String getCustomRepositoryID() {
-        if (_custom_repid == null) {
-            _custom_repid = "RMI:org.omg.custom." + getRepositoryID().substring(4);
-        }
+    private String genCustomRepId() {
+        return String.format("RMI:org.omg.custom.%s", getRepositoryID().substring(4));
+    }
+
+    public final String getCustomRepositoryID() {
+        if (_custom_repid == null) _custom_repid = genCustomRepId();
         return _custom_repid;
     }
 
-    long getSerialVersionUID() {
-        if (_is_enum) return 0L;
+    protected long getSerialVersionUID() {
         if (_serial_version_uid_field != null) {
 
             try {
@@ -154,7 +136,7 @@
                 // skip //
             }
         }
-        ObjectStreamClass serialForm = ObjectStreamClass.lookup(getJavaClass());
+        ObjectStreamClass serialForm = ObjectStreamClass.lookup(_java_class);
 
         return (serialForm != null) ? serialForm.getSerialVersionUID() : 0L;
     }
@@ -162,6 +144,7 @@
     public void init() {
         try {
             init0();
+            super.init();
 
             if (_fields == null) {
                 throw new RuntimeException("fields==null after init!");
@@ -173,10 +156,9 @@
     }
 
     private void init0() {
-        final Class<?> type = getJavaClass();
+        final Class<?> type = _java_class;
         final Class<?> superClass = type.getSuperclass();
 
-        _is_enum = Enum.class.isAssignableFrom(type);
         _is_rmi_stub = RMIStub.class.isAssignableFrom(type);
         _is_externalizable = Externalizable.class.isAssignableFrom(type);
         _is_serializable = Serializable.class.isAssignableFrom(type);
@@ -184,7 +166,7 @@
         _is_immutable_value = _immutable_value_classes.contains(type);
 
         if ((superClass != null) && (superClass != Object.class)) {
-            TypeDescriptor superDesc = getTypeRepository().getDescriptor(superClass);
+            TypeDescriptor superDesc = repo.getDescriptor(superClass);
 
             if (superDesc instanceof ValueDescriptor) {
                 _super_descriptor = (ValueDescriptor) superDesc;
@@ -240,7 +222,7 @@
                 // validate readObject
                 //
                 if ((_write_object_method == null) || !Modifier.isPrivate(_write_object_method.getModifiers())
-                        || Modifier.isStatic(_write_object_method.getModifiers()) || (_write_object_method.getDeclaringClass() != getJavaClass())) {
+                        || Modifier.isStatic(_write_object_method.getModifiers()) || (_write_object_method.getDeclaringClass() != _java_class)) {
 
                     _write_object_method = null;
 
@@ -322,7 +304,7 @@
                             _constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(type, init_cons);
 
                             if (_constructor == null) {
-                                logger.warning("Unable to get constructor for serialization for class " + getJavaName());
+                                logger.warning("Unable to get constructor for serialization for class " + java_name);
                             } else {
                                 _constructor.setAccessible(true);
                             }
@@ -355,8 +337,7 @@
                             }
 
                             f.setAccessible(true);
-                            FieldDescriptor fd = FieldDescriptor.get(f);
-                            fd.setTypeRepository(getTypeRepository());
+                            FieldDescriptor fd = FieldDescriptor.get(f, repo);
                             flist.add(fd);
                         }
 
@@ -382,16 +363,14 @@
                             rf.setAccessible(true);
 
                             if (rf.getType() == f.getType()) {
-                                fd = FieldDescriptor.get(rf);
+                                fd = FieldDescriptor.get(rf,repo);
                             }
                         } catch (SecurityException | NoSuchFieldException ex) {
                         }
 
                         if (fd == null) {
-                            fd = FieldDescriptor.get(type, f);
+                            fd = FieldDescriptor.get(type, f, repo);
                         }
-
-                        fd.setTypeRepository(getTypeRepository());
                         _fields[i] = fd;
                     }
 
@@ -513,7 +492,7 @@
     }
 
     protected void defaultWriteValue(ObjectWriter writer, Serializable val) throws IOException {
-        logger.finer("writing fields for " + getJavaClass());
+        logger.finer("writing fields for " + _java_class);
         FieldDescriptor[] fields = _fields;
 
         if (fields == null) {
@@ -521,7 +500,7 @@
         }
 
         for (int i = 0; i < fields.length; i++) {
-            logger.finer("writing field " + _fields[i].getJavaName());
+            logger.finer("writing field " + _fields[i].java_name);
 
             fields[i].write(writer, val);
         }
@@ -570,7 +549,7 @@
                 throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
 
             } catch (NullPointerException ex) {
-                logger.log(Level.WARNING, "unable to create instance of " + getJavaClass().getName(), ex);
+                logger.log(Level.WARNING, "unable to create instance of " + _java_class.getName(), ex);
                 logger.warning("constructor => " + _constructor);
 
                 throw ex;
@@ -623,7 +602,7 @@
             int key = System.identityHashCode(val);
             recurse.put(val, key);
 
-            pw.println(getJavaClass().getName() + "@" + Integer.toHexString(key) + "[");
+            pw.println(_java_class.getName() + "@" + Integer.toHexString(key) + "[");
 
             printFields(pw, recurse, val);
 
@@ -659,11 +638,11 @@
             return;
         }
 
-        logger.fine("reading fields for " + getJavaClass().getName());
+        logger.fine("reading fields for " + _java_class.getName());
 
         for (FieldDescriptor _field : _fields) {
 
-            logger.fine("reading field " + _field.getJavaName() + " of type " + _field.getType().getName() + " using " + _field.getClass().getName());
+            logger.fine("reading field " + _field.java_name + " of type " + _field.getType().getName() + " using " + _field.getClass().getName());
 
             try {
                 _field.read(reader, value);
@@ -671,7 +650,7 @@
                 if (ex.getMessage() != null)
                     throw ex;
 
-                String msg = String.format("%s, while reading %s.%s", ex, getJavaName(), _field.getJavaName());
+                String msg = String.format("%s, while reading %s.%s", ex, java_name, _field.java_name);
                 throw (MARSHAL) new MARSHAL(msg, ex.minor, ex.completed).initCause(ex);
             }
         }
@@ -682,13 +661,13 @@
             return Collections.EMPTY_MAP;
         }
 
-        logger.finer("reading fields for " + getJavaClass().getName());
+        logger.finer("reading fields for " + _java_class.getName());
 
         Map map = new HashMap();
 
         for (FieldDescriptor _field : _fields) {
 
-            logger.finer("reading field " + _field.getJavaName());
+            logger.finer("reading field " + _field.java_name);
 
             _field.readFieldIntoMap(reader, map);
         }
@@ -701,11 +680,11 @@
             return;
         }
 
-        logger.finer("writing fields for " + getJavaClass().getName());
+        logger.finer("writing fields for " + _java_class.getName());
 
         for (FieldDescriptor _field : _fields) {
 
-            logger.finer("writing field " + _field.getJavaName());
+            logger.finer("writing field " + _field.java_name);
 
             _field.writeFieldFromMap(writer, fieldMap);
         }
@@ -769,7 +748,7 @@
     }
 
     protected long computeHashCode() {
-        Class type = getJavaClass();
+        Class type = _java_class;
 
         if (_is_externalizable) {
             return 1L;
@@ -788,7 +767,7 @@
 
             Class superType = type.getSuperclass();
             if (superType != null) {
-                TypeDescriptor desc = getTypeRepository().getDescriptor(superType);
+                TypeDescriptor desc = repo.getDescriptor(superType);
                 out.writeLong(desc.getHashCode());
             }
 
@@ -804,7 +783,7 @@
                 Arrays.sort(fds, compareByName);
 
             for (FieldDescriptor f : fds) {
-                out.writeUTF(f.getJavaName());
+                out.writeUTF(f.java_name);
                 out.writeUTF(makeSignature(f.getType()));
             }
 
@@ -833,8 +812,8 @@
 
     private static final Comparator compareByName = new Comparator() {
         public int compare(Object f1, Object f2) {
-            String n1 = ((FieldDescriptor) f1).getJavaName();
-            String n2 = ((FieldDescriptor) f2).getJavaName();
+            String n1 = ((FieldDescriptor) f1).java_name;
+            String n2 = ((FieldDescriptor) f2).java_name;
             return n1.compareTo(n2);
         }
     };
@@ -851,7 +830,7 @@
         if (_value_members == null) {
             _value_members = new ValueMember[_fields.length];
             for (int i = 0; i < _fields.length; i++) {
-                _value_members[i] = _fields[i].getValueMember(getTypeRepository());
+                _value_members[i] = _fields[i].getValueMember(repo);
             }
         }
 
@@ -867,9 +846,9 @@
 
         TypeCode _base = ((_super_descriptor == null) ? null : _super_descriptor.getTypeCode());
 
-        Class javaClass = getJavaClass();
+        Class javaClass = _java_class;
         if (javaClass.isArray()) {
-            TypeDescriptor desc = getTypeRepository().getDescriptor(javaClass.getComponentType());
+            TypeDescriptor desc = repo.getDescriptor(javaClass.getComponentType());
             _type_code = desc.getTypeCode();
             _type_code = orb.create_sequence_tc(0, _type_code);
             _type_code = orb.create_value_box_tc(getRepositoryID(), "Sequence", _type_code);
@@ -887,7 +866,7 @@
     
     FullValueDescription getFullValueDescription() {
         FullValueDescription fvd = new FullValueDescription();
-        fvd.name = getJavaClass().getName();
+        fvd.name = _java_class.getName();
         fvd.id = getRepositoryID();
         fvd.is_abstract = false;
         fvd.is_custom = isCustomMarshalled();
@@ -923,17 +902,17 @@
         }
 
         ObjectDeserializer(FullValueDescription desc, RunTime runtime) throws IOException {
-            Class myClass = ValueDescriptor.this.getJavaClass();
+            Class myClass = _java_class;
             ValueMember[] members = desc.members;
             fields = new FieldDescriptor[members.length];
             for (int i = 0; i < members.length; i++) {
                 Class type = getClassFromTypeCode(members[i].type);
-                fields[i] = FieldDescriptor.get(myClass, type, members[i].name, null);
+                fields[i] = FieldDescriptor.get(myClass, type, members[i].name, null, repo);
             }
 
             if (!"".equals(desc.base_value)) {
                 Class clz = ValueHandlerImpl.getClassFromRepositoryID(desc.base_value);
-                TypeDescriptor tdesc = getTypeRepository().getDescriptor(clz);
+                TypeDescriptor tdesc = repo.getDescriptor(clz);
 
                 if ((tdesc instanceof ValueDescriptor)) {
                     super_descriptor = ((ValueDescriptor) tdesc).getObjectDeserializer(desc.base_value, runtime);
@@ -981,9 +960,9 @@
         if (oorig == orig) {
             wdesc = this;
         } else {
-            wdesc = (ValueDescriptor) getTypeRepository().getDescriptor(oorig.getClass());
+            wdesc = (ValueDescriptor) repo.getDescriptor(oorig.getClass());
 
-            logger.finer("writeReplace -> " + getJavaClass().getName());
+            logger.finer("writeReplace -> " + _java_class.getName());
         }
 
         return wdesc.copyObject2(oorig, state);
@@ -1012,7 +991,7 @@
             writeValue(writer, oorig);
             return writer;
         } catch (IOException ex) {
-            String msg = String.format("%s writing %s", ex, getJavaClass().getName());
+            String msg = String.format("%s writing %s", ex, _java_class.getName());
             throw (MARSHAL) new MARSHAL(msg).initCause(ex);
         }
     }
@@ -1023,7 +1002,7 @@
             readValue(reader, copy);
             return readResolve(copy);
         } catch (IOException ex) {
-            String msg = String.format("%s reading instance of %s", ex, getJavaClass().getName());
+            String msg = String.format("%s reading instance of %s", ex, _java_class.getName());
             throw (MARSHAL) new MARSHAL(msg).initCause(ex);
         }
     }
@@ -1042,7 +1021,7 @@
 
         pw.print(paramName);
         pw.print(',');
-        MethodDescriptor.writeJavaType(pw, getJavaClass());
+        MethodDescriptor.writeJavaType(pw, _java_class);
         pw.print(".class)");
     }
 
@@ -1051,12 +1030,12 @@
         pw.print('.');
         pw.print("read_value");
         pw.print('(');
-        MethodDescriptor.writeJavaType(pw, getJavaClass());
+        MethodDescriptor.writeJavaType(pw, _java_class);
         pw.print(".class)");
     }
 
     void addDependencies(Set<Class<?>> classes) {
-        Class c = getJavaClass();
+        Class c = _java_class;
 
         if ((c == Object.class) || classes.contains(c))
             return;
@@ -1064,13 +1043,13 @@
         classes.add(c);
 
         if (c.getSuperclass() != null) {
-            TypeDescriptor desc = getTypeRepository().getDescriptor(c.getSuperclass());
+            TypeDescriptor desc = repo.getDescriptor(c.getSuperclass());
             desc.addDependencies(classes);
         }
 
         Class[] ifaces = c.getInterfaces();
         for (Class iface : ifaces) {
-            TypeDescriptor desc = getTypeRepository().getDescriptor(iface);
+            TypeDescriptor desc = repo.getDescriptor(iface);
             desc.addDependencies(classes);
         }
 
@@ -1079,7 +1058,7 @@
                 if (_field.isPrimitive())
                     continue;
 
-                TypeDescriptor desc = getTypeRepository().getDescriptor(_field.type);
+                TypeDescriptor desc = repo.getDescriptor(_field.type);
                 desc.addDependencies(classes);
             }
         }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueHandlerImpl.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueHandlerImpl.java
index 7d898c6..7004c25 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueHandlerImpl.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ValueHandlerImpl.java
@@ -26,7 +26,6 @@
 
 import org.omg.CORBA.CompletionStatus;
 import org.omg.CORBA.MARSHAL;
-import org.omg.CORBA.OBJECT_NOT_EXIST;
 import org.omg.CORBA.ValueDefPackage.FullValueDescription;
 import org.omg.SendingContext.RunTime;
 
@@ -173,7 +172,7 @@
         if (val instanceof RMIStub) {
 
             RMIStub stub = (RMIStub) val;
-            Class type = stub._descriptor.getJavaClass();
+            Class type = stub._descriptor._java_class;
 
             RMIState state = RMIState.current();
             Stub result = state.getStaticStub(stub._get_codebase(), type);
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/VoidDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/VoidDescriptor.java
index 0ec6385..3c9ecfe 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/VoidDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/VoidDescriptor.java
@@ -18,7 +18,7 @@
 
 package org.apache.yoko.rmi.impl;
 
-class VoidDescriptor extends SimpleDescriptor {
+final class VoidDescriptor extends SimpleDescriptor {
     VoidDescriptor(TypeRepository repository) {
         super(Void.TYPE, repository, "void", org.omg.CORBA.TCKind.tk_void);
     }
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/yasf/Yasf.java b/yoko-util/src/main/java/org/apache/yoko/util/yasf/Yasf.java
new file mode 100644
index 0000000..616e27e
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/yasf/Yasf.java
@@ -0,0 +1,43 @@
+package org.apache.yoko.util.yasf;
+
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Set;
+
+public enum Yasf {
+    ENUM_FIXED(0);
+
+    // TODO - Get ids from OMG assigned for these values
+    public static final int TAG_YOKO_AUXILLIARY_STREAM_FORMAT = 0xeeeeeeee;
+    public static final int YOKO_AUXIllIARY_STREAM_FORMAT_SC = 0xeeeeeeee;
+
+    public final int itemIndex;
+
+    private Yasf(int itemIndex) {
+        this.itemIndex = itemIndex;
+    }
+
+    public static Set<Yasf> supported() {
+        return Collections.unmodifiableSet(EnumSet.of(ENUM_FIXED));
+    }
+
+    public static Set<Yasf> toSet(byte[] data) {
+        if (data == null) return null;
+        final EnumSet<Yasf> set = EnumSet.noneOf(Yasf.class);
+        BitSet items = BitSet.valueOf(data);
+        for (Yasf yasf : values()) {
+            if (items.get(yasf.itemIndex)) set.add(yasf);
+        }
+        return Collections.unmodifiableSet(set);
+    }
+
+    public static byte[] toData(Set<Yasf> yasfSet) {
+        if (null == yasfSet) return null;
+        final BitSet bits = new BitSet();
+        for (Yasf yasf : yasfSet) {
+            bits.set(yasf.itemIndex);
+        }
+        return bits.toByteArray();
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/yasf/YasfThreadLocal.java b/yoko-util/src/main/java/org/apache/yoko/util/yasf/YasfThreadLocal.java
new file mode 100644
index 0000000..6cb897b
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/yasf/YasfThreadLocal.java
@@ -0,0 +1,87 @@
+package org.apache.yoko.util.yasf;
+
+import java.util.BitSet;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public final class YasfThreadLocal {
+    private static final Logger LOGGER = Logger.getLogger(YasfThreadLocal.class.getName());
+    private static final ThreadLocal<YasfInfo> yasfInfo = new ThreadLocal<YasfInfo>() {
+        @Override protected YasfInfo initialValue() {
+            return new YasfInfo();
+        }
+    };
+
+    private YasfThreadLocal() {}
+
+    private static final class YasfInfo {
+        public Frame head = Frame.DEFAULT;
+        public boolean override = false;
+    }
+
+    private static final class Frame {
+        static final Frame DEFAULT = new Frame();
+        public final Set<Yasf> value;
+        public final Frame prev;
+
+        private Frame() {
+            this.value = null;
+            this.prev = this;
+        }
+
+        Frame(Set<Yasf> value, Frame prev) {
+            this.value = value;
+            this.prev = prev;
+        }
+    }
+
+    public static final class YasfOverride implements AutoCloseable {
+        private final YasfInfo info;
+
+        YasfOverride(YasfInfo info) {
+            this.info = info;
+            info.override = true;
+        }
+
+        @Override
+        public void close() {
+            info.override = false;
+        }
+    }
+
+    public static YasfOverride override() {
+        return new YasfOverride(yasfInfo.get());
+    }
+
+    public static void push(Set<Yasf> items) {
+        final YasfInfo info = yasfInfo.get();
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer(String.format("YASF thread local version pushed onto stack: %s", items));
+        info.head = new Frame(items, info.head);
+    }
+
+    public static Set<Yasf> get() {
+        final YasfInfo info = yasfInfo.get();
+        final boolean override = info.override;
+        final Set<Yasf> items = (override) ? null : info.head.value;
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer(String.format("YASF thread local version retrieved: %s, override is %b", items, override));
+        return items;
+    }
+
+    public static Set<Yasf> pop() {
+        final YasfInfo info = yasfInfo.get();
+        final Set<Yasf> items = info.head.value;
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer(String.format("YASF thread local version popped from stack: %s", items));
+        info.head = info.head.prev;
+        return items;
+    }
+
+    public static void reset() {
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer("YASF thread local stack reset");
+        yasfInfo.remove();
+    }
+}