Merge IBM development contributiions. As it does not appear possible to alter the git log messages to include jira issue numbers, the git commit hashes will be added to the jira issues.
diff --git a/.gitignore b/.gitignore
index 1f29ad1..7660622 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
 *.i??
 .project
+.metadata
+.idea
 .classpath
 .settings
 target
diff --git a/pom.xml b/pom.xml
index dd14cac..9eaf6ae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,7 +44,7 @@
         <antrun.version>1.1</antrun.version>
         <!--<antlr.version>2.7.5</antlr.version>-->
         <bcel.version>5.2</bcel.version>
-        <junit.version>4.5</junit.version>
+        <junit.version>4.12</junit.version>
         <compile.flags>-Xlint:unchecked,deprecation,fallthrough,finally</compile.flags>
         <java.endorsed.dirs>${basedir}/target/classes</java.endorsed.dirs>
         <compile.forked>false</compile.forked>
@@ -71,11 +71,12 @@
     <packaging>pom</packaging>
 
     <modules>
-        <module>yoko-core</module>
+        <module>yoko-osgi</module>
         <module>yoko-spec-corba</module>
         <module>yoko-rmi-spec</module>
+        <module>yoko-util</module>
         <module>yoko-rmi-impl</module>
-        <module>yoko-osgi</module>
+        <module>yoko-core</module>
     </modules>
 
     <dependencyManagement>
@@ -83,7 +84,7 @@
             <!--  Yoko modules -->
             <dependency>
                 <groupId>org.apache.yoko</groupId>
-                <artifactId>yoko-core</artifactId>
+                <artifactId>yoko-osgi</artifactId>
                 <version>${project.version}</version>
             </dependency>
             <dependency>
@@ -93,19 +94,24 @@
             </dependency>
             <dependency>
                 <groupId>org.apache.yoko</groupId>
-                <artifactId>yoko-osgi</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.yoko</groupId>
                 <artifactId>yoko-rmi-spec</artifactId>
                 <version>${project.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.apache.yoko</groupId>
+                <artifactId>yoko-util</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.apache.yoko</groupId>
                 <artifactId>yoko-rmi-impl</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.apache.yoko</groupId>
+                <artifactId>yoko-core</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <!--  External dependencies -->
             <dependency>
                 <groupId>junit</groupId>
@@ -117,16 +123,6 @@
                 <artifactId>org.apache.servicemix.bundles.bcel</artifactId>
                 <version>5.2_2</version>
             </dependency>
-            <!--<dependency>-->
-                <!--<groupId>org.apache.maven</groupId>-->
-                <!--<artifactId>maven-plugin-api</artifactId>-->
-                <!--<version>${maven.version}</version>-->
-            <!--</dependency>-->
-            <!--<dependency>-->
-                <!--<groupId>org.apache.maven</groupId>-->
-                <!--<artifactId>maven-project</artifactId>-->
-                <!--<version>${maven.version}</version>-->
-            <!--</dependency>-->
             <dependency>
                 <groupId>ant</groupId>
                 <artifactId>ant</artifactId>
@@ -197,7 +193,18 @@
                 <groupId>org.apache.felix</groupId>
                 <artifactId>maven-bundle-plugin</artifactId>
             </plugin>
-
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                    <compilerArguments>
+                        <endorseddirs>${project.build.directory}/endorsed</endorseddirs>
+                    </compilerArguments>
+                </configuration>
+            </plugin>
         </plugins>
 
         <pluginManagement>
@@ -214,24 +221,6 @@
                         </dependency>
                     </dependencies>
                 </plugin>
-                <!--<plugin>-->
-                    <!--<groupId>org.apache.maven.plugins</groupId>-->
-                    <!--<artifactId>maven-surefire-plugin</artifactId>-->
-                    <!--<configuration>-->
-                        <!--<includes>-->
-                            <!--<include>**/*Test.java</include>-->
-                            <!--<include>**/*TestCase.java</include>-->
-                        <!--</includes>-->
-                        <!--<excludes>-->
-                            <!--<exclude>**/*$*</exclude>-->
-                        <!--</excludes>-->
-                        <!--<reportFormat>brief</reportFormat>-->
-                        <!--<useFile>false</useFile>-->
-                        <!--<forkMode>once</forkMode>-->
-                        <!--<childDelegation>false</childDelegation>-->
-                        <!--<argLine>-ea</argLine>-->
-                    <!--</configuration>-->
-                <!--</plugin>-->
                 <plugin>
                     <groupId>org.apache.felix</groupId>
                     <artifactId>maven-bundle-plugin</artifactId>
@@ -260,9 +249,6 @@
                 <artifactId>maven-clover-plugin</artifactId>
                 <version>2.4</version>
             </plugin>
-            <!--plugin>
-              <artifactId>maven-pmd-plugin</artifactId>
-            </plugin!-->
             <plugin>
                 <artifactId>maven-project-info-reports-plugin</artifactId>
             </plugin>
@@ -275,4 +261,11 @@
         <url>http://svn.apache.org/viewvc/geronimo/yoko/trunk</url>
     </scm>
 
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.servicemix.bundles</groupId>
+        <artifactId>org.apache.servicemix.bundles.bcel</artifactId>
+        <version>5.2_2</version>
+      </dependency>
+    </dependencies>
 </project>
diff --git a/yoko-core/pom.xml b/yoko-core/pom.xml
index 31493c9..dfe3cf7 100644
--- a/yoko-core/pom.xml
+++ b/yoko-core/pom.xml
@@ -33,7 +33,12 @@
         <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
-            <version>4.3.0</version>
+            <version>5.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.yoko</groupId>
+            <artifactId>yoko-osgi</artifactId>
             <scope>provided</scope>
         </dependency>
         <dependency>
@@ -48,24 +53,33 @@
         </dependency>
         <dependency>
             <groupId>org.apache.yoko</groupId>
-            <artifactId>yoko-rmi-impl</artifactId>
-            <scope>test</scope>
+            <artifactId>yoko-util</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.yoko</groupId>
-            <artifactId>yoko-osgi</artifactId>
+            <artifactId>yoko-rmi-impl</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
-
     </dependencies>
 
     <build>
         <plugins>
             <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-Activator>org.apache.yoko.orb.activator.Activator</Bundle-Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-dependency-plugin</artifactId>
                 <executions>
@@ -90,6 +104,13 @@
                                     <overWrite>true</overWrite>
                                     <outputDirectory>${project.build.directory}/endorsed</outputDirectory>
                                 </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.apache.yoko</groupId>
+                                    <artifactId>yoko-osgi</artifactId>
+                                    <type>jar</type>
+                                    <overWrite>true</overWrite>
+                                    <outputDirectory>${project.build.directory}/endorsed</outputDirectory>
+                                </artifactItem>
                             </artifactItems>
                         </configuration>
                     </execution>
@@ -110,15 +131,10 @@
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
                 <configuration>
+                    <argLine>-Xmx128m -Djava.endorsed.dirs=${project.build.directory}/endorsed</argLine>
                     <includes>
                         <include>**/org/apache/yoko/*Test.java</include>
                     </includes>
-                    <systemProperties>
-                        <property>
-                            <name>java.endorsed.dirs</name>
-                            <value>${basedir}/target/endorsed</value>
-                        </property>
-                    </systemProperties>
                 </configuration>
             </plugin>
 
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/Delegate.java b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/Delegate.java
index db5868f..acc5015 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/Delegate.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/Delegate.java
@@ -1057,11 +1057,4 @@
         return downcallStub_;
     }
 
-    public synchronized void _OB_closeConnection(boolean terminate) {
-        if (downcallStub_ == null) {
-            return;
-        }
-        downcallStub_._OB_closeConnection(terminate);
-        downcallStub_ = null;
-    }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/InputStream.java b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/InputStream.java
index 906f6aa..a7f4184 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/InputStream.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/InputStream.java
@@ -1,10 +1,10 @@
 /*
  *  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
+ *  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
  *
@@ -17,23 +17,38 @@
 
 package org.apache.yoko.orb.CORBA;
 
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.rmi.Remote;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.rmi.CORBA.Util;
 
+import org.apache.yoko.orb.OB.Assert;
+import org.apache.yoko.orb.OB.MinorCodes;
+import org.apache.yoko.orb.OB.OB_Extras;
+import org.apache.yoko.orb.OCI.GiopVersion;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.portable.IDLEntity;
+import org.omg.CORBA.portable.ObjectImpl;
+import org.omg.CORBA.portable.ValueInputStream;
 import org.omg.SendingContext.CodeBase;
 
-final public class InputStream extends org.omg.CORBA_2_3.portable.InputStream {
+final public class InputStream extends org.omg.CORBA_2_3.portable.InputStream implements ValueInputStream {
     static final Logger logger = Logger.getLogger(InputStream.class.getName());
-    
+
     org.apache.yoko.orb.OB.ORBInstance orbInstance_;
 
     public org.apache.yoko.orb.OCI.Buffer buf_;
 
     boolean swap_;
 
-    private int GIOPVersion_ = org.apache.yoko.orb.OB.OB_Extras.DEFAULT_GIOP_VERSION;
+    private GiopVersion giopVersion_ = org.apache.yoko.orb.OB.OB_Extras.DEFAULT_GIOP_VERSION;
 
     private int origPos_;
 
@@ -59,9 +74,9 @@
 
     private boolean wCharConversionRequired_;
 
-	private CodeBase sendingContextRuntime_;
+    private CodeBase sendingContextRuntime_;
 
-	private String codebase_;
+    private String codebase_;
 
     // ------------------------------------------------------------------
     // Private and protected members
@@ -80,11 +95,11 @@
         return tc;
     }
 
-    private org.omg.CORBA.TypeCode readTypeCodeImpl(
-            java.util.Hashtable history, boolean isTopLevel) {
+    private org.omg.CORBA.TypeCode readTypeCodeImpl(java.util.Hashtable history, boolean isTopLevel) {
         int kind = read_ulong();
         int oldPos = buf_.pos_ - 4;
-        logger.finest("Reading a TypeCode of kind " + kind + " from position " + oldPos); 
+        if (logger.isLoggable(Level.FINEST))
+            logger.finest(String.format("Reading a TypeCode of kind %d from position 0x%x", kind, oldPos));
 
         TypeCode tc = null;
         if (kind == -1) {
@@ -94,135 +109,252 @@
             TypeCode p = (TypeCode) history.get(new Integer(indirectionPos));
             if (p == null) {
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvTypeCodeIndirection),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvTypeCodeIndirection,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvTypeCodeIndirection),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvTypeCodeIndirection, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
             }
             history.put(new Integer(oldPos), p);
             tc = p;
         } else {
             switch (kind) {
-            case org.omg.CORBA.TCKind._tk_null:
-            case org.omg.CORBA.TCKind._tk_void:
-            case org.omg.CORBA.TCKind._tk_short:
-            case org.omg.CORBA.TCKind._tk_long:
-            case org.omg.CORBA.TCKind._tk_ushort:
-            case org.omg.CORBA.TCKind._tk_ulong:
-            case org.omg.CORBA.TCKind._tk_float:
-            case org.omg.CORBA.TCKind._tk_double:
-            case org.omg.CORBA.TCKind._tk_boolean:
-            case org.omg.CORBA.TCKind._tk_char:
-            case org.omg.CORBA.TCKind._tk_octet:
-            case org.omg.CORBA.TCKind._tk_any:
-            case org.omg.CORBA.TCKind._tk_TypeCode:
-            case org.omg.CORBA.TCKind._tk_Principal:
-            case org.omg.CORBA.TCKind._tk_longlong:
-            case org.omg.CORBA.TCKind._tk_ulonglong:
-            case org.omg.CORBA.TCKind._tk_longdouble:
-            case org.omg.CORBA.TCKind._tk_wchar:
-                tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                        .createPrimitiveTC(org.omg.CORBA_2_4.TCKind
-                                .from_int(kind));
-                history.put(new Integer(oldPos), tc);
-                break;
+                case org.omg.CORBA.TCKind._tk_null :
+                case org.omg.CORBA.TCKind._tk_void :
+                case org.omg.CORBA.TCKind._tk_short :
+                case org.omg.CORBA.TCKind._tk_long :
+                case org.omg.CORBA.TCKind._tk_ushort :
+                case org.omg.CORBA.TCKind._tk_ulong :
+                case org.omg.CORBA.TCKind._tk_float :
+                case org.omg.CORBA.TCKind._tk_double :
+                case org.omg.CORBA.TCKind._tk_boolean :
+                case org.omg.CORBA.TCKind._tk_char :
+                case org.omg.CORBA.TCKind._tk_octet :
+                case org.omg.CORBA.TCKind._tk_any :
+                case org.omg.CORBA.TCKind._tk_TypeCode :
+                case org.omg.CORBA.TCKind._tk_Principal :
+                case org.omg.CORBA.TCKind._tk_longlong :
+                case org.omg.CORBA.TCKind._tk_ulonglong :
+                case org.omg.CORBA.TCKind._tk_longdouble :
+                case org.omg.CORBA.TCKind._tk_wchar :
+                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createPrimitiveTC(org.omg.CORBA_2_4.TCKind.from_int(kind));
+                    history.put(new Integer(oldPos), tc);
+                    break;
 
-            case org.omg.CORBA.TCKind._tk_fixed: {
-                short digits = read_ushort();
-                short scale = read_short();
-                tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                        .createFixedTC(digits, scale);
-                history.put(new Integer(oldPos), tc);
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_objref: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
-
-                String id = read_string();
-
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                            .createInterfaceTC(id, read_string());
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
+                case org.omg.CORBA.TCKind._tk_fixed : {
+                    short digits = read_ushort();
+                    short scale = read_short();
+                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createFixedTC(digits, scale);
+                    history.put(new Integer(oldPos), tc);
+                    break;
                 }
 
-                history.put(new Integer(oldPos), tc);
-                swap_ = swap;
-                break;
-            }
+                case org.omg.CORBA.TCKind._tk_objref : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
 
-            case org.omg.CORBA.TCKind._tk_struct:
-            case org.omg.CORBA.TCKind._tk_except: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();  
+                    String id = read_string();
 
-                String id = read_string();
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createInterfaceTC(id, read_string());
 
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    //
-                    // For potentially recursive types, we must
-                    // construct the TypeCode manually in order to
-                    // add it to the history
-                    //
-                    TypeCode p = new TypeCode();
-                    history.put(new Integer(oldPos), p);
-                    p.kind_ = org.omg.CORBA_2_4.TCKind.from_int(kind);
-                    p.id_ = id;
-                    p.name_ = read_string();
-                    int num = read_ulong();
-                    p.memberNames_ = new String[num];
-                    p.memberTypes_ = new TypeCode[num];
-                    for (int i = 0; i < num; i++) {
-                        p.memberNames_[i] = read_string();
-                        p.memberTypes_[i] = (TypeCode) readTypeCodeImpl(
-                                history, false);
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
                     }
 
-                    tc = p;
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
+                    history.put(new Integer(oldPos), tc);
+                    swap_ = swap;
+                    break;
                 }
 
-                swap_ = swap;
-                break;
-            }
+                case org.omg.CORBA.TCKind._tk_struct :
+                case org.omg.CORBA.TCKind._tk_except : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
 
-            case org.omg.CORBA.TCKind._tk_union: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
+                    String id = read_string();
 
-                String id = read_string();
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        //
+                        // For potentially recursive types, we must
+                        // construct the TypeCode manually in order to
+                        // add it to the history
+                        //
+                        TypeCode p = new TypeCode();
+                        history.put(new Integer(oldPos), p);
+                        p.kind_ = org.omg.CORBA_2_4.TCKind.from_int(kind);
+                        p.id_ = id;
+                        p.name_ = read_string();
+                        int num = read_ulong();
+                        p.memberNames_ = new String[num];
+                        p.memberTypes_ = new TypeCode[num];
+                        for (int i = 0; i < num; i++) {
+                            p.memberNames_[i] = read_string();
+                            p.memberTypes_[i] = (TypeCode) readTypeCodeImpl(history, false);
+                        }
 
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
+                        tc = p;
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
+                    swap_ = swap;
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_union : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
+
+                    String id = read_string();
+
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        //
+                        // For potentially recursive types, we must construct
+                        // the TypeCode manually in order to add it to the
+                        // history
+                        //
+                        TypeCode p = new TypeCode();
+                        history.put(new Integer(oldPos), p);
+                        p.kind_ = org.omg.CORBA.TCKind.tk_union;
+                        p.id_ = id;
+                        p.name_ = read_string();
+                        p.discriminatorType_ = (TypeCode) readTypeCodeImpl(history, false);
+                        int defaultIndex = read_long();
+                        int num = read_ulong();
+                        p.labels_ = new Any[num];
+                        p.memberNames_ = new String[num];
+                        p.memberTypes_ = new TypeCode[num];
+
+                        //
+                        // Check the discriminator type
+                        //
+                        TypeCode origTC = p.discriminatorType_._OB_getOrigType();
+
+                        switch (origTC.kind().value()) {
+                            case org.omg.CORBA.TCKind._tk_short :
+                            case org.omg.CORBA.TCKind._tk_ushort :
+                            case org.omg.CORBA.TCKind._tk_long :
+                            case org.omg.CORBA.TCKind._tk_ulong :
+                            case org.omg.CORBA.TCKind._tk_longlong :
+                            case org.omg.CORBA.TCKind._tk_ulonglong :
+                            case org.omg.CORBA.TCKind._tk_boolean :
+                            case org.omg.CORBA.TCKind._tk_char :
+                            case org.omg.CORBA.TCKind._tk_enum :
+                                break;
+                            default :
+                                //
+                                // Invalid discriminator type
+                                //
+                                throw new org.omg.CORBA.BAD_TYPECODE(
+                                        org.apache.yoko.orb.OB.MinorCodes
+                                                .describeBadTypecode(org.apache.yoko.orb.OB.MinorCodes.MinorInvalidUnionDiscriminator),
+                                        org.apache.yoko.orb.OB.MinorCodes.MinorInvalidUnionDiscriminator, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        }
+
+                        for (int i = 0; i < num; i++) {
+                            p.labels_[i] = new Any();
+                            if (i == defaultIndex) {
+                                //
+                                // Unmarshal a dummy value of the
+                                // appropriate size for the
+                                // discriminator type
+                                //
+                                Any dummy = new Any();
+                                dummy.read_value(this, p.discriminatorType_);
+
+                                //
+                                // Default label value is the zero octet
+                                //
+                                p.labels_[i].insert_octet((byte) 0);
+                            } else {
+                                p.labels_[i].read_value(this, p.discriminatorType_);
+                            }
+                            p.memberNames_[i] = read_string();
+                            p.memberTypes_[i] = (TypeCode) readTypeCodeImpl(history, false);
+                        }
+
+                        tc = p;
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
+                    swap_ = swap;
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_enum : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
+
+                    String id = read_string();
+
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        String name = read_string();
+                        int num = read_ulong();
+                        String[] members = new String[num];
+                        for (int i = 0; i < num; i++)
+                            members[i] = read_string();
+                        tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createEnumTC(id, name, members);
+                        history.put(new Integer(oldPos), tc);
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
+                    swap_ = swap;
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_string : {
+                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createStringTC(read_ulong());
+                    history.put(new Integer(oldPos), tc);
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_wstring : {
+                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createWStringTC(read_ulong());
+                    history.put(new Integer(oldPos), tc);
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_sequence :
+                case org.omg.CORBA.TCKind._tk_array : {
+                    read_ulong(); // encapsulation length
+                    boolean swap = swap_;
+                    _OB_readEndian();
+
                     //
                     // For potentially recursive types, we must construct
                     // the TypeCode manually in order to add it to the
@@ -230,340 +362,201 @@
                     //
                     TypeCode p = new TypeCode();
                     history.put(new Integer(oldPos), p);
-                    p.kind_ = org.omg.CORBA.TCKind.tk_union;
-                    p.id_ = id;
-                    p.name_ = read_string();
-                    p.discriminatorType_ = (TypeCode) readTypeCodeImpl(history,
-                            false);
-                    int defaultIndex = read_long();
-                    int num = read_ulong();
-                    p.labels_ = new Any[num];
-                    p.memberNames_ = new String[num];
-                    p.memberTypes_ = new TypeCode[num];
-
-                    //
-                    // Check the discriminator type
-                    //
-                    TypeCode origTC = p.discriminatorType_._OB_getOrigType();
-
-                    switch (origTC.kind().value()) {
-                    case org.omg.CORBA.TCKind._tk_short:
-                    case org.omg.CORBA.TCKind._tk_ushort:
-                    case org.omg.CORBA.TCKind._tk_long:
-                    case org.omg.CORBA.TCKind._tk_ulong:
-                    case org.omg.CORBA.TCKind._tk_longlong:
-                    case org.omg.CORBA.TCKind._tk_ulonglong:
-                    case org.omg.CORBA.TCKind._tk_boolean:
-                    case org.omg.CORBA.TCKind._tk_char:
-                    case org.omg.CORBA.TCKind._tk_enum:
-                        break;
-                    default:
-                        //
-                        // Invalid discriminator type
-                        //
-                        throw new org.omg.CORBA.BAD_TYPECODE(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeBadTypecode(org.apache.yoko.orb.OB.MinorCodes.MinorInvalidUnionDiscriminator),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorInvalidUnionDiscriminator,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-                    }
-
-                    for (int i = 0; i < num; i++) {
-                        p.labels_[i] = new Any();
-                        if (i == defaultIndex) {
-                            //
-                            // Unmarshal a dummy value of the
-                            // appropriate size for the
-                            // discriminator type
-                            //
-                            Any dummy = new Any();
-                            dummy.read_value(this, p.discriminatorType_);
-
-                            //
-                            // Default label value is the zero octet
-                            //
-                            p.labels_[i].insert_octet((byte) 0);
-                        } else {
-                            p.labels_[i].read_value(this, p.discriminatorType_);
-                        }
-                        p.memberNames_[i] = read_string();
-                        p.memberTypes_[i] = (TypeCode) readTypeCodeImpl(
-                                history, false);
-                    }
-
-                    tc = p;
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
-                }
-
-                swap_ = swap;
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_enum: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
-
-                String id = read_string();
-
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    String name = read_string();
-                    int num = read_ulong();
-                    String[] members = new String[num];
-                    for (int i = 0; i < num; i++)
-                        members[i] = read_string();
-                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                            .createEnumTC(id, name, members);
-                    history.put(new Integer(oldPos), tc);
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
-                }
-
-                swap_ = swap;
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_string: {
-                tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                        .createStringTC(read_ulong());
-                history.put(new Integer(oldPos), tc);
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_wstring: {
-                tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                        .createWStringTC(read_ulong());
-                history.put(new Integer(oldPos), tc);
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_sequence:
-            case org.omg.CORBA.TCKind._tk_array: {
-                read_ulong(); // encapsulation length
-                boolean swap = swap_;
-                _OB_readEndian();
-
-                //
-                // For potentially recursive types, we must construct
-                // the TypeCode manually in order to add it to the
-                // history
-                //
-                TypeCode p = new TypeCode();
-                history.put(new Integer(oldPos), p);
-                p.kind_ = org.omg.CORBA_2_4.TCKind.from_int(kind);
-                p.contentType_ = (TypeCode) readTypeCodeImpl(history, false);
-                p.length_ = read_ulong();
-
-                tc = p;
-
-                swap_ = swap;
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_alias: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
-
-                String id = read_string();
-
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                            .createAliasTC(id, read_string(), readTypeCodeImpl(
-                                    history, false));
-
-                    history.put(new Integer(oldPos), tc);
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
-                }
-
-                swap_ = swap;
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_value: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
-
-                String id = read_string();
-
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    //
-                    // For potentially recursive types, we must
-                    // construct the TypeCode manually in order to
-                    // add it to the history
-                    //
-                    TypeCode p = new TypeCode();
-                    history.put(new Integer(oldPos), p);
                     p.kind_ = org.omg.CORBA_2_4.TCKind.from_int(kind);
-                    p.id_ = id;
-                    p.name_ = read_string();
-                    p.typeModifier_ = read_short();
-                    p.concreteBaseType_ = (TypeCode) readTypeCodeImpl(history,
-                            false);
-                    if (p.concreteBaseType_.kind().value() == org.omg.CORBA.TCKind._tk_null)
-                        p.concreteBaseType_ = null;
-                    int num = read_ulong();
-                    p.memberNames_ = new String[num];
-                    p.memberTypes_ = new TypeCode[num];
-                    p.memberVisibility_ = new short[num];
-                    for (int i = 0; i < num; i++) {
-                        p.memberNames_[i] = read_string();
-                        p.memberTypes_[i] = (TypeCode) readTypeCodeImpl(
-                                history, false);
-                        p.memberVisibility_[i] = read_short();
-                    }
+                    p.contentType_ = (TypeCode) readTypeCodeImpl(history, false);
+                    p.length_ = read_ulong();
 
                     tc = p;
 
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
+                    swap_ = swap;
+                    break;
                 }
 
-                swap_ = swap;
-                break;
-            }
+                case org.omg.CORBA.TCKind._tk_alias : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
 
-            case org.omg.CORBA.TCKind._tk_value_box: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
+                    String id = read_string();
 
-                String id = read_string();
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createAliasTC(id, read_string(), readTypeCodeImpl(history, false));
 
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                            .createValueBoxTC(id, read_string(),
-                                    readTypeCodeImpl(history, false));
+                        history.put(new Integer(oldPos), tc);
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
+                    swap_ = swap;
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_value : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
+
+                    String id = read_string();
+
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        //
+                        // For potentially recursive types, we must
+                        // construct the TypeCode manually in order to
+                        // add it to the history
+                        //
+                        TypeCode p = new TypeCode();
+                        history.put(new Integer(oldPos), p);
+                        p.kind_ = org.omg.CORBA_2_4.TCKind.from_int(kind);
+                        p.id_ = id;
+                        p.name_ = read_string();
+                        p.typeModifier_ = read_short();
+                        p.concreteBaseType_ = (TypeCode) readTypeCodeImpl(history, false);
+                        if (p.concreteBaseType_.kind().value() == org.omg.CORBA.TCKind._tk_null)
+                            p.concreteBaseType_ = null;
+                        int num = read_ulong();
+                        p.memberNames_ = new String[num];
+                        p.memberTypes_ = new TypeCode[num];
+                        p.memberVisibility_ = new short[num];
+                        for (int i = 0; i < num; i++) {
+                            p.memberNames_[i] = read_string();
+                            p.memberTypes_[i] = (TypeCode) readTypeCodeImpl(history, false);
+                            p.memberVisibility_[i] = read_short();
+                        }
+
+                        tc = p;
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
+                    swap_ = swap;
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_value_box : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
+
+                    String id = read_string();
+
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createValueBoxTC(id, read_string(), readTypeCodeImpl(history, false));
+                        history.put(new Integer(oldPos), tc);
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
+                    swap_ = swap;
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_abstract_interface : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
+
+                    String id = read_string();
+
+                    if (logger.isLoggable(Level.FINE))
+                        logger.fine(String.format("Abstract interface typecode encapsulaton length=0x%x id=%s", length, id));
+
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createAbstractInterfaceTC(id, read_string());
+                        history.put(new Integer(oldPos), tc);
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
+                    swap_ = swap;
+                    break;
+                }
+
+                case org.omg.CORBA.TCKind._tk_native : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
+
+                    String id = read_string();
+
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createNativeTC(id, read_string());
+
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
+
                     history.put(new Integer(oldPos), tc);
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
+                    swap_ = swap;
+                    break;
                 }
 
-                swap_ = swap;
-                break;
-            }
+                case org.omg.CORBA_2_4.TCKind._tk_local_interface : {
+                    int length = read_ulong(); // encapsulation length
+                    // save this position after the read, since we might be on a chunk boundary.
+                    // however, we do an explicit check for the chunk boundary before doing the 
+                    // read. 
+                    checkChunk();
+                    int typePos = buf_.pos_;
+                    boolean swap = swap_;
+                    _OB_readEndian();
 
-            case org.omg.CORBA.TCKind._tk_abstract_interface: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
+                    String id = read_string();
 
-                String id = read_string();
-                
-                logger.fine("Abstract interface typecode encapsulaton length=" + length + " id=" + id); 
+                    if (isTopLevel && cache_ != null)
+                        tc = checkCache(id, typePos, length); // may advance pos
+                    if (tc == null) {
+                        tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory.createLocalInterfaceTC(id, read_string());
+                        history.put(new Integer(oldPos), tc);
 
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                            .createAbstractInterfaceTC(id, read_string());
-                    history.put(new Integer(oldPos), tc);
+                        if (id.length() > 0 && cache_ != null)
+                            cache_.put(id, tc);
+                    }
 
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
+                    swap_ = swap;
+                    break;
                 }
 
-                swap_ = swap;
-                break;
-            }
-
-            case org.omg.CORBA.TCKind._tk_native: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
-
-                String id = read_string();
-
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                            .createNativeTC(id, read_string());
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
-                }
-
-                history.put(new Integer(oldPos), tc);
-                swap_ = swap;
-                break;
-            }
-
-            case org.omg.CORBA_2_4.TCKind._tk_local_interface: {
-                int length = read_ulong(); // encapsulation length
-                // save this position after the read, since we might be on a chunk boundary.
-                // however, we do an explicit check for the chunk boundary before doing the 
-                // read. 
-                checkChunk(); 
-                int typePos = buf_.pos_;
-                boolean swap = swap_;
-                _OB_readEndian();
-
-                String id = read_string();
-
-                if (isTopLevel && cache_ != null)
-                    tc = checkCache(id, typePos, length); // may advance pos
-                if (tc == null) {
-                    tc = (TypeCode) org.apache.yoko.orb.OB.TypeCodeFactory
-                            .createLocalInterfaceTC(id, read_string());
-                    history.put(new Integer(oldPos), tc);
-
-                    if (id.length() > 0 && cache_ != null)
-                        cache_.put(id, tc);
-                }
-
-                swap_ = swap;
-                break;
-            }
-
-            default:
-                throw new org.omg.CORBA.BAD_TYPECODE("Unknown TypeCode kind: "
-                        + kind);
+                default :
+                    throw new org.omg.CORBA.BAD_TYPECODE("Unknown TypeCode kind: " + kind);
             }
         }
 
@@ -580,7 +573,7 @@
     // reads wide-characters using the old non-compliant method
     //
     private char _OB_read_wchar_old() {
-        checkChunk(); 
+        checkChunk();
 
         if (wCharConversionRequired_) {
             final org.apache.yoko.orb.OB.CodeConverterBase converter = codeConverters_.inputWcharConverter;
@@ -592,30 +585,28 @@
             // as ushort or ulong, depending on their maximum length
             // listed in the code set registry.
             //
-            switch (GIOPVersion_) {
+            switch (giopVersion_) {
 
-            case 0x0101: {
-                if (converter.getFrom().max_bytes <= 2)
-                    value = (char) read_ushort();
-                else
-                    value = (char) read_ulong();
+                case GIOP1_1: {
+                    if (converter.getFrom().max_bytes <= 2)
+                        value = (char) read_ushort();
+                    else
+                        value = (char) read_ulong();
 
-                break;
-            }
+                    break;
+                }
 
-            default: {
-                final int wcharLen = buf_.data_[buf_.pos_++] & 0xff;
-                if (buf_.pos_ + wcharLen > buf_.len_)
-                    throw new org.omg.CORBA.MARSHAL(
-                            org.apache.yoko.orb.OB.MinorCodes
-                                    .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                default : {
+                    final int wcharLen = buf_.data_[buf_.pos_++] & 0xff;
+                    if (buf_.pos_ + wcharLen > buf_.len_)
+                        throw new org.omg.CORBA.MARSHAL(
+                                org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow),
+                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-                value = converter.read_wchar(this, wcharLen);
+                    value = converter.read_wchar(this, wcharLen);
 
-                break;
-            }
+                    break;
+                }
             }
 
             return converter.convert(value);
@@ -624,40 +615,37 @@
         // UTF-16
         //
         else {
-            switch (GIOPVersion_) {
+            switch (giopVersion_) {
 
             //
             // Orbix2000/ORBacus/E compatible GIOP 1.0 marshaling
             //
-            case 0x0100: {
-                buf_.pos_ += (buf_.pos_ & 0x1);
+                case GIOP1_0: {
+                    buf_.pos_ += (buf_.pos_ & 0x1);
 
-                if (buf_.pos_ + 2 > buf_.len_)
-                    throw new org.omg.CORBA.MARSHAL(
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    if (buf_.pos_ + 2 > buf_.len_)
+                        throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
+                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-                //
-                // Assume big endian
-                //
-                return (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
-            }
+                    //
+                    // Assume big endian
+                    //
+                    return (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
+                }
 
-            case 0x0101: {
-                return (char) read_ushort();
-            }
+                case GIOP1_1: {
+                    return (char) read_ushort();
+                }
 
-            default: {
-                final int wcharLen = buf_.data_[buf_.pos_++] & 0xff;
-                if (buf_.pos_ + wcharLen > buf_.len_)
-                    throw new org.omg.CORBA.MARSHAL(
-                            org.apache.yoko.orb.OB.MinorCodes
-                                    .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                default : {
+                    final int wcharLen = buf_.data_[buf_.pos_++] & 0xff;
+                    if (buf_.pos_ + wcharLen > buf_.len_)
+                        throw new org.omg.CORBA.MARSHAL(
+                                org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow),
+                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-                return (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
-            }
+                    return (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
+                }
             }
         }
     }
@@ -666,44 +654,43 @@
     // reads wide-characters using compliant method
     //
     private char _OB_read_wchar_new(boolean partOfString) {
-        checkChunk(); 
-        
+        checkChunk();
+
         char value;
         final org.apache.yoko.orb.OB.CodeConverterBase converter = codeConverters_.inputWcharConverter;
 
         if (wCharReaderRequired_) {
             if (partOfString == false)
-                converter
-                        .set_reader_flags(org.apache.yoko.orb.OB.CodeSetReader.FIRST_CHAR);
+                converter.set_reader_flags(org.apache.yoko.orb.OB.CodeSetReader.FIRST_CHAR);
 
             int wcLen = 2;
 
-            switch (GIOPVersion_) {
-            case 0x0100:
-                //
-                // we should not require a reader for GIOP 1.0
-                // wchars since this would mean we are using UTF-16.
-                // This is not available in Orbix/E compatibility,
-                // only UCS-2...
-                //
-                org.apache.yoko.orb.OB.Assert._OB_assert(false);
-                break;
+            switch (giopVersion_) {
+                case GIOP1_0:
+                    //
+                    // we should not require a reader for GIOP 1.0
+                    // wchars since this would mean we are using UTF-16.
+                    // This is not available in Orbix/E compatibility,
+                    // only UCS-2...
+                    //
+                    org.apache.yoko.orb.OB.Assert._OB_assert(false);
+                    break;
 
-            case 0x0101:
-                //
-                // align on two-byte boundary
-                // 
-                buf_.pos_ += (buf_.pos_ & 1);
+                case GIOP1_1:
+                    //
+                    // align on two-byte boundary
+                    // 
+                    buf_.pos_ += (buf_.pos_ & 1);
 
-                break;
+                    break;
 
-            default:
-                //
-                // get the octet indicating the wchar len
-                //
-                wcLen = buf_.data_[buf_.pos_++] & 0xff;
+                default :
+                    //
+                    // get the octet indicating the wchar len
+                    //
+                    wcLen = buf_.data_[buf_.pos_++] & 0xff;
 
-                break;
+                    break;
             }
 
             //
@@ -711,10 +698,8 @@
             //
             if (buf_.pos_ + wcLen > buf_.len_)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             //
             // read in the value with the reader
@@ -724,76 +709,73 @@
             //
             // no reader is required then
             //
-            switch (GIOPVersion_) {
-            case 0x0100:
-                //
-                // UCS-2 is the native wchar codeset for both Orbacus
-                // and Orbix/E so conversion should not be necessary
-                // 
-                org.apache.yoko.orb.OB.Assert
-                        ._OB_assert(!wCharConversionRequired_);
-
-                //
-                // align to 2-byte boundary
-                //
-                buf_.pos_ += (buf_.pos_ & 1);
-
-                //
-                // check for overflow on reader
-                // 
-                if (buf_.pos_ + 2 > buf_.len_)
-                    throw new org.omg.CORBA.MARSHAL(
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                //
-                // assume big-endian (both Orbacus and Orbix/E do here)
-                // and read in the wchar
-                //
-                return (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
-
-            case 0x0101:
-                //
-                // read according to the endian of the message
-                //
-                if (converter.getFrom().max_bytes <= 2)
-                    value = (char) read_ushort();
-                else
-                    value = (char) read_ulong();
-
-                break;
-
-            default: {
-                //
-                // read the length octet off the front
-                // 
-                final int wcLen = buf_.data_[buf_.pos_++] & 0xff;
-
-                //
-                // check for an overflow
-                //
-                if (buf_.pos_ + wcLen > buf_.len_)
-                    throw new org.omg.CORBA.MARSHAL(
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                //
-                // read the character off in proper endian format
-                // 
-                if (swap_) {
+            switch (giopVersion_) {
+                case GIOP1_0:
                     //
-                    // the message was in little endian format
+                    // UCS-2 is the native wchar codeset for both Orbacus
+                    // and Orbix/E so conversion should not be necessary
+                    // 
+                    org.apache.yoko.orb.OB.Assert._OB_assert(!wCharConversionRequired_);
+
                     //
-                    value = (char) ((buf_.data_[buf_.pos_++] & 0xff) | (buf_.data_[buf_.pos_++] << 8));
-                } else {
+                    // align to 2-byte boundary
                     //
-                    // the message was in big endian format
+                    buf_.pos_ += (buf_.pos_ & 1);
+
                     //
-                    value = (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
+                    // check for overflow on reader
+                    // 
+                    if (buf_.pos_ + 2 > buf_.len_)
+                        throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
+                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                    //
+                    // assume big-endian (both Orbacus and Orbix/E do here)
+                    // and read in the wchar
+                    //
+                    return (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
+
+                case GIOP1_1:
+                    //
+                    // read according to the endian of the message
+                    //
+                    if (converter.getFrom().max_bytes <= 2)
+                        value = (char) read_ushort();
+                    else
+                        value = (char) read_ulong();
+
+                    break;
+
+                default : {
+                    //
+                    // read the length octet off the front
+                    // 
+                    final int wcLen = buf_.data_[buf_.pos_++] & 0xff;
+
+                    //
+                    // check for an overflow
+                    //
+                    if (buf_.pos_ + wcLen > buf_.len_)
+                        throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes.MinorReadWCharOverflow,
+                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                    //
+                    // read the character off in proper endian format
+                    // 
+                    if (swap_) {
+                        //
+                        // the message was in little endian format
+                        //
+                        value = (char) ((buf_.data_[buf_.pos_++] & 0xff) | (buf_.data_[buf_.pos_++] << 8));
+                    } else {
+                        //
+                        // the message was in big endian format
+                        //
+                        value = (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
+                    }
+
+                    break;
                 }
-
-                break;
-            }
             }
         }
 
@@ -812,7 +794,7 @@
     private String _OB_read_wstring_old() {
         String s = "";
 
-        checkChunk(); 
+        checkChunk();
         int len = read_ulong();
 
         //
@@ -825,103 +807,90 @@
         //
         // For GIOP 1.1 the length must not be 0.
         //
-        switch (GIOPVersion_) {
+        switch (giopVersion_) {
 
-        case 0x0100:
-        case 0x0101: {
-            if (len == 0)
-                throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            case GIOP1_0:
+            case GIOP1_1: {
+                if (len == 0)
+                    throw new org.omg.CORBA.MARSHAL(
+                            org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength),
+                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-            char[] tmp = new char[len];
-            read_wchar_array(tmp, 0, len);
+                char[] tmp = new char[len];
+                read_wchar_array(tmp, 0, len);
 
-            //
-            // Check for terminating null wchar
-            //
-            if (tmp[len - 1] != 0)
-                throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                //
+                // Check for terminating null wchar
+                //
+                if (tmp[len - 1] != 0)
+                    throw new org.omg.CORBA.MARSHAL(
+                            org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator),
+                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-            s = new String(tmp, 0, len - 1);
+                s = new String(tmp, 0, len - 1);
 
-            break;
-        }
-
-        default: {
-            StringBuffer stringBuffer = new StringBuffer(len);
-
-            if (wCharConversionRequired_) {
-                final org.apache.yoko.orb.OB.CodeConverterBase converter = codeConverters_.inputWcharConverter;
-
-                while (len > 0) {
-                    final int wcharLen = converter
-                            .read_count_wchar((char) buf_.data_[buf_.pos_]);
-                    len -= wcharLen;
-                    if (buf_.pos_ + wcharLen > buf_.len_)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    char c = converter.read_wchar(this, wcharLen);
-
-                    c = converter.convert(c);
-
-                    //
-                    // String must not contain null characters
-                    //
-                    if (c == 0)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    stringBuffer.append(c);
-                }
-            }
-            //
-            // UTF-16
-            //
-            else {
-                while (len > 0) {
-                    final int wcharLen = 2;
-                    len -= wcharLen;
-                    if (buf_.pos_ + wcharLen > buf_.len_)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    char c = (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
-
-                    //
-                    // String must not contain null characters
-                    //
-                    if (c == 0)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    stringBuffer.append(c);
-                }
+                break;
             }
 
-            s = stringBuffer.toString();
+            default : {
+                StringBuffer stringBuffer = new StringBuffer(len);
 
-            break;
-        }
+                if (wCharConversionRequired_) {
+                    final org.apache.yoko.orb.OB.CodeConverterBase converter = codeConverters_.inputWcharConverter;
+
+                    while (len > 0) {
+                        final int wcharLen = converter.read_count_wchar((char) buf_.data_[buf_.pos_]);
+                        len -= wcharLen;
+                        if (buf_.pos_ + wcharLen > buf_.len_)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        char c = converter.read_wchar(this, wcharLen);
+
+                        c = converter.convert(c);
+
+                        //
+                        // String must not contain null characters
+                        //
+                        if (c == 0)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        stringBuffer.append(c);
+                    }
+                }
+                //
+                // UTF-16
+                //
+                else {
+                    while (len > 0) {
+                        final int wcharLen = 2;
+                        len -= wcharLen;
+                        if (buf_.pos_ + wcharLen > buf_.len_)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        char c = (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
+
+                        //
+                        // String must not contain null characters
+                        //
+                        if (c == 0)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        stringBuffer.append(c);
+                    }
+                }
+
+                s = stringBuffer.toString();
+
+                break;
+            }
         }
 
         return s;
@@ -932,7 +901,7 @@
     //
     private String _OB_read_wstring_new() {
         String s = "";
-        checkChunk(); 
+        checkChunk();
 
         final org.apache.yoko.orb.OB.CodeConverterBase converter = codeConverters_.inputWcharConverter;
 
@@ -941,160 +910,145 @@
         // GIOP 1.0/1.1 and in octets for GIOP 1.2+)
         // 
         int len = read_ulong();
-        logger.fine("Reading wstring of length " + len); 
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Reading wstring of length 0x%x", len));
 
-        switch (GIOPVersion_) {
+        switch (giopVersion_) {
 
-        case 0x0100:
-        case 0x0101: {
-            //
-            // it is not legal in GIOP 1.0/1.1 for a string to be 0 in
-            // length... it MUST have a null terminator
-            // 
-            if (len == 0) {
-                throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-            }
+            case GIOP1_0:
+            case GIOP1_1: {
+                //
+                // it is not legal in GIOP 1.0/1.1 for a string to be 0 in
+                // length... it MUST have a null terminator
+                // 
+                if (len == 0) {
+                    throw new org.omg.CORBA.MARSHAL(
+                            org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength),
+                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringZeroLength, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                }
 
-            char[] tmp = new char[len];
+                char[] tmp = new char[len];
 
-            if (wCharReaderRequired_) {
-                converter.set_reader_flags(org.apache.yoko.orb.OB.CodeSetReader.FIRST_CHAR);
-            }
+                if (wCharReaderRequired_) {
+                    converter.set_reader_flags(org.apache.yoko.orb.OB.CodeSetReader.FIRST_CHAR);
+                }
 
-            for (int i = 0; i < len; i++) {
-                tmp[i] = read_wchar(true);
-            }
-
-            //
-            // Check for terminating null wchar
-            //
-            if (tmp[len - 1] != 0)
-                throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-            //
-            // create the final string
-            // 
-            s = new String(tmp, 0, len - 1);
-
-            break;
-        }
-
-        default: {
-            StringBuffer stringBuffer = new StringBuffer(len);
-
-            if (wCharReaderRequired_) {
-                converter
-                        .set_reader_flags(org.apache.yoko.orb.OB.CodeSetReader.FIRST_CHAR);
+                for (int i = 0; i < len; i++) {
+                    tmp[i] = read_wchar(true);
+                }
 
                 //
-                // start adding the characters to the string buffer
+                // Check for terminating null wchar
                 //
-                while (len > 0) {
-                    if (buf_.pos_ + 2 > buf_.len_)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                if (tmp[len - 1] != 0)
+                    throw new org.omg.CORBA.MARSHAL(
+                            org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator),
+                            org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNoTerminator, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-                    int checkChar = (buf_.data_[buf_.pos_] << 8)
-                            | (buf_.data_[buf_.pos_ + 1] & 0xff);
+                //
+                // create the final string
+                // 
+                s = new String(tmp, 0, len - 1);
 
-                    int wcLen = converter.read_count_wchar((char) checkChar);
-
-                    len -= wcLen;
-
-                    // 
-                    // check for an overflow in the read
-                    //
-                    if (buf_.pos_ + wcLen > buf_.len_)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    //
-                    // read the character and convert if necessary
-                    // 
-                    char c = converter.read_wchar(this, wcLen);
-                    if (wCharConversionRequired_)
-                        c = converter.convert(c);
-
-                    //
-                    // check for invalid null character
-                    //
-                    if (c == 0)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    // 
-                    // append to the string buffer
-                    //
-                    stringBuffer.append(c);
-                }
-            } else {
-                final int wcLen = 2;
-
-                while (len > 0) {
-                    len -= wcLen;
-
-                    //
-                    // check for an overflow condition
-                    // 
-                    if (buf_.pos_ + wcLen > buf_.len_)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    //
-                    // read in the char using the message endian
-                    // format for GIOP 1.2/1.3
-                    // REVISIT: GIOP 1.4 changes these rules
-                    // 
-                    char c;
-                    if (swap_)
-                        c = (char) ((buf_.data_[buf_.pos_++] & 0xff) | (buf_.data_[buf_.pos_++] << 8));
-                    else
-                        c = (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
-
-                    if (wCharConversionRequired_)
-                        c = converter.convert(c);
-
-                    //
-                    // check for invalid null character
-                    //
-                    if (c == 0)
-                        throw new org.omg.CORBA.MARSHAL(
-                                org.apache.yoko.orb.OB.MinorCodes
-                                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-                    //
-                    // append to the string buffer
-                    //
-                    stringBuffer.append(c);
-                }
+                break;
             }
 
-            s = stringBuffer.toString();
+            default : {
+                StringBuffer stringBuffer = new StringBuffer(len);
 
-            break;
-        }
+                if (wCharReaderRequired_) {
+                    converter.set_reader_flags(org.apache.yoko.orb.OB.CodeSetReader.FIRST_CHAR);
+
+                    //
+                    // start adding the characters to the string buffer
+                    //
+                    while (len > 0) {
+                        if (buf_.pos_ + 2 > buf_.len_)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        int checkChar = (buf_.data_[buf_.pos_] << 8) | (buf_.data_[buf_.pos_ + 1] & 0xff);
+
+                        int wcLen = converter.read_count_wchar((char) checkChar);
+
+                        len -= wcLen;
+
+                        // 
+                        // check for an overflow in the read
+                        //
+                        if (buf_.pos_ + wcLen > buf_.len_)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        //
+                        // read the character and convert if necessary
+                        // 
+                        char c = converter.read_wchar(this, wcLen);
+                        if (wCharConversionRequired_)
+                            c = converter.convert(c);
+
+                        //
+                        // check for invalid null character
+                        //
+                        if (c == 0)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        // 
+                        // append to the string buffer
+                        //
+                        stringBuffer.append(c);
+                    }
+                } else {
+                    final int wcLen = 2;
+
+                    while (len > 0) {
+                        len -= wcLen;
+
+                        //
+                        // check for an overflow condition
+                        // 
+                        if (buf_.pos_ + wcLen > buf_.len_)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        //
+                        // read in the char using the message endian
+                        // format for GIOP 1.2/1.3
+                        // REVISIT: GIOP 1.4 changes these rules
+                        // 
+                        char c;
+                        if (swap_)
+                            c = (char) ((buf_.data_[buf_.pos_++] & 0xff) | (buf_.data_[buf_.pos_++] << 8));
+                        else
+                            c = (char) ((buf_.data_[buf_.pos_++] << 8) | (buf_.data_[buf_.pos_++] & 0xff));
+
+                        if (wCharConversionRequired_)
+                            c = converter.convert(c);
+
+                        //
+                        // check for invalid null character
+                        //
+                        if (c == 0)
+                            throw new org.omg.CORBA.MARSHAL(
+                                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar),
+                                    org.apache.yoko.orb.OB.MinorCodes.MinorReadWStringNullWChar, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                        //
+                        // append to the string buffer
+                        //
+                        stringBuffer.append(c);
+                    }
+                }
+
+                s = stringBuffer.toString();
+
+                break;
+            }
         }
 
         return s;
@@ -1110,7 +1064,7 @@
     }
 
     public int read() throws java.io.IOException {
-        checkChunk(); 
+        checkChunk();
         if (buf_.pos_ + 1 > buf_.len_)
             return -1;
 
@@ -1124,28 +1078,25 @@
     }
 
     public boolean read_boolean() {
-        checkChunk(); 
+        checkChunk();
 
         if (buf_.pos_ + 1 > buf_.len_) {
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
         }
 
-        logger.finest("Boolean value is " + buf_.data_[buf_.pos_] + " from position " + buf_.pos_); 
+        if (logger.isLoggable(Level.FINEST))
+            logger.finest(String.format("Boolean value is %b from position 0x%x", buf_.data_[buf_.pos_], buf_.pos_));
         return buf_.data_[buf_.pos_++] != (byte) 0;
     }
 
     public char read_char() {
-        checkChunk(); 
+        checkChunk();
         if (buf_.pos_ + 1 > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadCharOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadCharOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadCharOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadCharOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (charReaderRequired_ || charConversionRequired_) {
             final org.apache.yoko.orb.OB.CodeConverterBase converter = codeConverters_.inputCharConverter;
@@ -1155,8 +1106,7 @@
             else if (charReaderRequired_)
                 return converter.read_char(this);
             else
-                return converter
-                        .convert((char) (buf_.data_[buf_.pos_++] & 0xff));
+                return converter.convert((char) (buf_.data_[buf_.pos_++] & 0xff));
         } else {
             //
             // Note: byte must be masked with 0xff to correct negative values
@@ -1176,27 +1126,23 @@
     }
 
     public byte read_octet() {
-        checkChunk(); 
+        checkChunk();
         if (buf_.pos_ + 1 > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         return buf_.data_[buf_.pos_++];
     }
 
     public short read_short() {
-        checkChunk(); 
+        checkChunk();
         buf_.pos_ += (buf_.pos_ & 0x1);
 
         if (buf_.pos_ + 2 > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadShortOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadShortOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadShortOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadShortOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (swap_)
             return (short) ((buf_.data_[buf_.pos_++] & 0xff) | (buf_.data_[buf_.pos_++] << 8));
@@ -1209,7 +1155,7 @@
     }
 
     public int read_long() {
-        checkChunk(); 
+        checkChunk();
         return _OB_readLongUnchecked();
     }
 
@@ -1218,17 +1164,15 @@
     }
 
     public long read_longlong() {
-        checkChunk(); 
+        checkChunk();
         final int pmod8 = buf_.pos_ & 0x7;
         if (pmod8 != 0)
             buf_.pos_ += 8 - pmod8;
 
         if (buf_.pos_ + 8 > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (swap_)
             return ((long) buf_.data_[buf_.pos_++] & 0xffL)
@@ -1263,7 +1207,7 @@
     }
 
     public String read_string() {
-        checkChunk(); 
+        checkChunk();
 
         //
         // Number of octets (i.e. bytes) in the string (including
@@ -1274,20 +1218,17 @@
 
         if (length == 0) {
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringZeroLength),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadStringZeroLength,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringZeroLength),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadStringZeroLength, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
         }
 
         int newPos = buf_.pos_ + length;
         if (newPos < buf_.pos_ || newPos > buf_.len_) {
-            logger.fine("String length=" + length + " newPos=" + newPos + " buf_.pos=" + buf_.pos_ + " buf_.len=" + buf_.len_); 
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format("String length=0x%x newPos=0x%x buf_.pos=0x%x buf_.len=0x%x", length, newPos, buf_.pos_, buf_.len_));
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadStringOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadStringOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
         }
 
         length--;
@@ -1313,10 +1254,8 @@
                 //
                 if (arr[i] == 0)
                     throw new org.omg.CORBA.MARSHAL(
-                            org.apache.yoko.orb.OB.MinorCodes
-                                    .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                            org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar),
+                            org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
             }
         } else {
             final org.apache.yoko.orb.OB.CodeConverterBase converter = codeConverters_.inputCharConverter;
@@ -1340,10 +1279,8 @@
                 //
                 if (value == 0)
                     throw new org.omg.CORBA.MARSHAL(
-                            org.apache.yoko.orb.OB.MinorCodes
-                                    .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                            org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar),
+                            org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNullChar, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
                 if (charConversionRequired_)
                     arr[i] = converter.convert(value);
@@ -1358,10 +1295,8 @@
         buf_.pos_ = newPos;
         if (buf_.data_[buf_.pos_ - 1] != 0)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNoTerminator),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNoTerminator,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNoTerminator),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadStringNoTerminator, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         int numExtraBytes = 0;
         if (numChars != 0 && numChars != maxChars) {
@@ -1391,15 +1326,12 @@
 
     public void read_boolean_array(boolean[] value, int offset, int length) {
         if (length > 0) {
-            checkChunk(); 
+            checkChunk();
 
-            if (buf_.pos_ + length < buf_.pos_
-                    || buf_.pos_ + length > buf_.len_)
+            if (buf_.pos_ + length < buf_.pos_ || buf_.pos_ + length > buf_.len_)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanArrayOverflow),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanArrayOverflow,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanArrayOverflow),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadBooleanArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             for (int i = offset; i < offset + length; i++)
                 value[i] = buf_.data_[buf_.pos_++] != (byte) 0;
@@ -1408,15 +1340,12 @@
 
     public void read_char_array(char[] value, int offset, int length) {
         if (length > 0) {
-            checkChunk(); 
+            checkChunk();
 
-            if (buf_.pos_ + length < buf_.pos_
-                    || buf_.pos_ + length > buf_.len_)
+            if (buf_.pos_ + length < buf_.pos_ || buf_.pos_ + length > buf_.len_)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             if (!(charReaderRequired_ || charConversionRequired_)) {
                 for (int i = offset; i < offset + length; i++) {
@@ -1432,8 +1361,7 @@
                 //
                 // Intermediate variable used for efficiency
                 //
-                boolean bothRequired = charReaderRequired_
-                        && charConversionRequired_;
+                boolean bothRequired = charReaderRequired_ && charConversionRequired_;
 
                 for (int i = offset; i < offset + length; i++) {
                     if (bothRequired)
@@ -1455,13 +1383,10 @@
 
     public void read_wchar_array(char[] value, int offset, int length) {
         if (length > 0) {
-            if (buf_.pos_ + length < buf_.pos_
-                    || buf_.pos_ + length > buf_.len_)
+            if (buf_.pos_ + length < buf_.pos_ || buf_.pos_ + length > buf_.len_)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadCharArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             for (int i = offset; i < offset + length; i++)
                 value[i] = read_wchar(false);
@@ -1470,15 +1395,13 @@
 
     public void read_octet_array(byte[] value, int offset, int length) {
         if (length > 0) {
-            checkChunk(); 
+            checkChunk();
 
             int newPos = buf_.pos_ + length;
             if (newPos < buf_.pos_ || newPos > buf_.len_)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetArrayOverflow),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetArrayOverflow,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetArrayOverflow),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadOctetArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             System.arraycopy(buf_.data_, buf_.pos_, value, offset, length);
 
@@ -1490,16 +1413,14 @@
         if (length <= 0)
             return;
 
-        checkChunk(); 
+        checkChunk();
         buf_.pos_ += (buf_.pos_ & 0x1);
 
         int newPos = buf_.pos_ + length * 2;
         if (newPos < buf_.pos_ || newPos > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadShortArrayOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadShortArrayOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadShortArrayOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadShortArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (swap_)
             for (int i = offset; i < offset + length; i++)
@@ -1516,7 +1437,7 @@
     public void read_long_array(int[] value, int offset, int length) {
         if (length <= 0)
             return;
-        checkChunk(); 
+        checkChunk();
         final int pmod4 = buf_.pos_ & 0x3;
         if (pmod4 != 0)
             buf_.pos_ += 4 - pmod4;
@@ -1524,10 +1445,8 @@
         int newPos = buf_.pos_ + length * 4;
         if (newPos < buf_.pos_ || newPos > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongArrayOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongArrayOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongArrayOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (swap_)
             for (int i = offset; i < offset + length; i++)
@@ -1551,8 +1470,8 @@
         if (length <= 0)
             return;
 
-        checkChunk(); 
-        
+        checkChunk();
+
         final int pmod8 = buf_.pos_ & 0x7;
         if (pmod8 != 0)
             buf_.pos_ += 8 - pmod8;
@@ -1560,10 +1479,8 @@
         int newPos = buf_.pos_ + length * 8;
         if (newPos < buf_.pos_ || newPos > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongArrayOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongArrayOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongArrayOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongLongArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (swap_)
             for (int i = offset; i < offset + length; i++)
@@ -1593,7 +1510,7 @@
 
     public void read_float_array(float[] value, int offset, int length) {
         if (length > 0) {
-            checkChunk(); 
+            checkChunk();
 
             final int pmod4 = buf_.pos_ & 0x3;
             if (pmod4 != 0)
@@ -1602,10 +1519,8 @@
             int newPos = buf_.pos_ + length * 4;
             if (newPos < buf_.pos_ || newPos > buf_.len_)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFloatArrayOverflow),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadFloatArrayOverflow,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFloatArrayOverflow),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadFloatArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             if (swap_)
                 for (int i = offset; i < offset + length; i++) {
@@ -1632,7 +1547,7 @@
         if (length <= 0)
             return;
 
-        checkChunk(); 
+        checkChunk();
         final int pmod8 = buf_.pos_ & 0x7;
         if (pmod8 != 0)
             buf_.pos_ += 8 - pmod8;
@@ -1640,10 +1555,8 @@
         int newPos = buf_.pos_ + length * 8;
         if (newPos < buf_.pos_ || newPos > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadDoubleArrayOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadDoubleArrayOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadDoubleArrayOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadDoubleArrayOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (swap_)
             for (int i = offset; i < offset + length; i++) {
@@ -1674,7 +1587,7 @@
     }
 
     public org.omg.CORBA.Object read_Object() {
-        checkChunk(); 
+        checkChunk();
 
         org.omg.IOP.IOR ior = org.omg.IOP.IORHelper.read(this);
 
@@ -1682,110 +1595,103 @@
             return null;
 
         if (orbInstance_ == null)
-            throw new org.omg.CORBA.INITIALIZE("InputStream must be created "
-                    + "by a full ORB");
+            throw new org.omg.CORBA.INITIALIZE("InputStream must be created " + "by a full ORB");
 
-        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_
-                .getObjectFactory();
+        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_.getObjectFactory();
         return objectFactory.createObject(ior);
     }
 
-    public org.omg.CORBA.Object read_Object(java.lang.Class clz) {
-        //
-        // clz represents the stub class of the expected static type
-        //
+    public org.omg.CORBA.Object read_Object(Class expectedType) {
         org.omg.CORBA.Object obj = read_Object();
 
-        if (obj != null) {
-            // OK, we have two possibilities here.  The usual possibility is we're asked to load 
-            // an object using a specified Stub class.  We just create an instance of the stub class, 
-            // attach the object as a delegate, and we're done. 
-            // 
-            // The second possibility is a request for an instance of an interface.  This will require
-            // us to locate a stub class using the defined Stub search orders.  After that, the process 
-            // is largely the same. 
-            org.omg.CORBA.portable.ObjectImpl impl = (org.omg.CORBA.portable.ObjectImpl) obj;
-            
-            if (org.omg.CORBA.portable.ObjectImpl.class.isAssignableFrom(clz)) {
-                java.lang.Object stubObject;
-                try {
-                    stubObject = clz.newInstance();
-                    org.omg.CORBA.portable.ObjectImpl stubImpl = (org.omg.CORBA.portable.ObjectImpl) stubObject;
-                    stubImpl._set_delegate(impl._get_delegate());
-                    return stubImpl;
-                } catch (IllegalAccessException ex) {
-                    logger.log(java.util.logging.Level.FINE, "Exception creating object stub", ex); 
-                } catch (InstantiationException ex) {
-                    logger.log(java.util.logging.Level.FINE, "Exception creating object stub", ex); 
-                }
-                throw new org.omg.CORBA.MARSHAL("Unable to create stub for class " + clz.getName(), 
-                    org.apache.yoko.orb.OB.MinorCodes.MinorLoadStub, 
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-            }
-            else {
-                try {
-                    Class stubClass = getIDLStubClass(((org.omg.CORBA_2_3.portable.ObjectImpl)impl)._get_codebase(), clz); 
-                    
-                    java.lang.Object stubObject = stubClass.newInstance();
-                    org.omg.CORBA.portable.ObjectImpl stubImpl = (org.omg.CORBA.portable.ObjectImpl)stubObject;
-                    stubImpl._set_delegate(impl._get_delegate());
-                    return stubImpl;
-                } catch (IllegalAccessException ex) {
-                    logger.log(java.util.logging.Level.FINE, "Exception creating object stub", ex); 
-                } catch (InstantiationException ex) {
-                    logger.log(java.util.logging.Level.FINE, "Exception creating object stub", ex); 
-                } catch (ClassNotFoundException ex) {
-                    logger.log(java.util.logging.Level.FINE, "Exception creating object stub", ex); 
-                } catch (ClassCastException ex) {
-                    logger.log(java.util.logging.Level.FINE, "Exception creating object stub", ex); 
-                }
-                throw new org.omg.CORBA.MARSHAL("Unable to create stub for class " + clz.getName(), 
-                    org.apache.yoko.orb.OB.MinorCodes.MinorLoadStub, 
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-            }
+        if (obj == null) return null;
+
+        // OK, we have two possibilities here.  The usual possibility is we're asked to load 
+        // an object using a specified Stub class.  We just create an instance of the stub class, 
+        // attach the object as a delegate, and we're done. 
+        // 
+        // The second possibility is a request for an instance of an interface.  This will require
+        // us to locate a stub class using the defined Stub search orders.  After that, the process 
+        // is largely the same. 
+        org.omg.CORBA.portable.ObjectImpl impl = (org.omg.CORBA.portable.ObjectImpl) obj;
+
+        if (org.omg.CORBA.portable.ObjectImpl.class.isAssignableFrom(expectedType)) {
+            return createStub(expectedType, impl._get_delegate());
         }
-        // null object, just return null. 
-        return null;
+
+        final String codebase = ((org.omg.CORBA_2_3.portable.ObjectImpl) impl)._get_codebase();
+
+        try {
+            if (IDLEntity.class.isAssignableFrom(expectedType)) {
+                final Class<?> helperClass = Util.loadClass(expectedType.getName() + "Helper", codebase, expectedType.getClassLoader());
+                final Method helperNarrow = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
+                    @Override
+                    public Method run() throws NoSuchMethodException {
+                        return helperClass.getMethod("narrow", org.omg.CORBA.Object.class);
+                    }
+                });
+                return (org.omg.CORBA.Object) helperNarrow.invoke(null, impl);
+            }
+
+            return createStub(getRMIStubClass(codebase, expectedType), impl._get_delegate());
+        } catch (IllegalAccessException | ClassNotFoundException | ClassCastException | PrivilegedActionException | InvocationTargetException ex) {
+            logger.log(java.util.logging.Level.FINE, "Exception creating object stub", ex);
+            MARSHAL m = new org.omg.CORBA.MARSHAL("Unable to create stub for class " + expectedType.getName(),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorLoadStub, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            m.initCause(ex);
+            throw m;
+        }
     }
 
+    private org.omg.CORBA.Object createStub(Class<?> stubClass, org.omg.CORBA.portable.Delegate delegate) {
+        Assert._OB_assert(ObjectImpl.class.isAssignableFrom(stubClass), "stub class " + stubClass.getName() + " must extend ObjectImpl");
+        @SuppressWarnings("unchecked")
+        Class<? extends ObjectImpl> clz = (Class<? extends ObjectImpl>) stubClass;
+        try {
+            org.omg.CORBA.portable.ObjectImpl stub = clz.newInstance();
+            stub._set_delegate(delegate);
+            return stub;
+        } catch (IllegalAccessException | InstantiationException ex) {
+            logger.log(Level.FINE, "Exception creating object stub", ex);
+            MARSHAL m = new MARSHAL("Unable to create stub for class " + clz.getName(), MinorCodes.MinorLoadStub, CompletionStatus.COMPLETED_NO);
+            m.initCause(ex);
+            throw m;
+        }
+    }
 
     /**
-     * Convert a class type into a stub class name using the
-     * ISL stub name rules.
-     * 
-     * @param c      The class we need to stub.
-     * 
-     * @return The target stub class name. 
+     * Convert a class type into a stub class name using the RMI stub name rules.
+     * @param c The class we need to stub.
+     * @return The target stub class name.
      */
-    private String getIDLStubClassName(Class c) {
-
-        String cname = c.getName();
-
-        //String pkgname = null;
+    private String getRMIStubClassName(Class<?> c) {
+        final String cname = c.getName();
         int idx = cname.lastIndexOf('.');
-
-        if (idx == -1) {
-            return "_" + cname + "Stub";
-        } else {
-            return cname.substring(0, idx + 1) + "_" + cname.substring(idx + 1) + "Stub";
-        }
+        return cname.substring(0, idx + 1) + "_" + cname.substring(idx + 1) + "_Stub";
     }
-    
-    
+
     /**
-     * Load a statically-created Stub class for a type, 
-     * attempting both the old and new stub class rules.
-     * 
+     * Load a statically-created Stub class for a type, attempting both the old
+     * and new stub class rules.
      * @param codebase The search codebase to use.
-     * @param type     The type we need a stub for.
-     * 
+     * @param type The type we need a stub for.
      * @return A loaded stub class.
      */
-    private Class getIDLStubClass(String codebase, Class type) throws ClassNotFoundException {
-        String name = getIDLStubClassName(type); 
-        return Util.loadClass(name, codebase, type.getClassLoader()); 
+    @SuppressWarnings("unchecked")
+    private Class<? extends org.omg.CORBA.portable.ObjectImpl> getRMIStubClass(String codebase, Class<?> type) throws ClassNotFoundException {
+        String name = getRMIStubClassName(type);
+        ClassLoader cl = type.getClassLoader();
+        try {
+            return Util.loadClass(name, codebase, cl);
+        } catch (ClassNotFoundException e1) {
+            try {
+                return Util.loadClass("org.omg.stub." + name, codebase, cl);
+            } catch (ClassNotFoundException e2) {
+                e2.addSuppressed(e1);
+                throw e2;
+            }
+        }
     }
-    
 
     public org.omg.CORBA.TypeCode read_TypeCode() {
         //
@@ -1796,7 +1702,7 @@
         // encapsulation in a separate buffer.
         //
 
-        checkChunk(); 
+        checkChunk();
         java.util.Hashtable history = new java.util.Hashtable(11);
         return readTypeCodeImpl(history, true);
     }
@@ -1833,10 +1739,8 @@
             int hi = (b >>> 4) & 0x0f;
             if (hi > 9)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             //
             // 0 as high nibble is only valid if it's not the first nibble
@@ -1853,10 +1757,8 @@
                 break;
             } else
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             first = false;
         }
@@ -1867,10 +1769,8 @@
             return new java.math.BigDecimal(sBuffer.toString());
         } catch (NumberFormatException ex) {
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadFixedInvalid, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
         }
     }
 
@@ -1886,8 +1786,7 @@
         return valueReader().readValue(clz);
     }
 
-    public java.io.Serializable read_value(
-            org.omg.CORBA.portable.BoxedValueHelper helper) {
+    public java.io.Serializable read_value(org.omg.CORBA.portable.BoxedValueHelper helper) {
         return valueReader().readValueBox(helper);
     }
 
@@ -1921,31 +1820,28 @@
     // Application programs must not use these functions directly
     // ------------------------------------------------------------------
 
-    public InputStream(org.apache.yoko.orb.OCI.Buffer buf, int offs,
-            boolean swap, org.apache.yoko.orb.OB.CodeConverters codeConverters,
-            int GIOPVersion) {
+    public InputStream(org.apache.yoko.orb.OCI.Buffer buf, int offs, boolean swap, org.apache.yoko.orb.OB.CodeConverters codeConverters,
+            GiopVersion giopVersion) {
         buf_ = buf;
         buf_.pos(offs);
         swap_ = swap;
         origPos_ = offs;
         origSwap_ = swap;
 
-        _OB_codeConverters(codeConverters, GIOPVersion);
+        _OB_codeConverters(codeConverters, giopVersion);
     }
 
-    public InputStream(org.apache.yoko.orb.OCI.Buffer buf, int offs,
-            boolean swap) {
-        this(buf, offs, swap, null, 0);
+    public InputStream(org.apache.yoko.orb.OCI.Buffer buf, int offs, boolean swap) {
+        this(buf, offs, swap, null, null);
     }
 
     public InputStream(org.apache.yoko.orb.OCI.Buffer buf) {
-        this(buf, 0, false, null, 0);
+        this(buf, 0, false, null, null);
     }
 
-    public void _OB_codeConverters(
-            org.apache.yoko.orb.OB.CodeConverters converters, int GIOPVersion) {
-        if (GIOPVersion != 0)
-            GIOPVersion_ = GIOPVersion;
+    public void _OB_codeConverters(org.apache.yoko.orb.OB.CodeConverters converters, GiopVersion giopVersion) {
+        if (giopVersion != null)
+            giopVersion_ = giopVersion;
 
         charReaderRequired_ = false;
         charConversionRequired_ = false;
@@ -1956,17 +1852,13 @@
 
         if (converters != null) {
             if (codeConverters_.inputCharConverter != null) {
-                charReaderRequired_ = codeConverters_.inputCharConverter
-                        .readerRequired();
-                charConversionRequired_ = codeConverters_.inputCharConverter
-                        .conversionRequired();
+                charReaderRequired_ = codeConverters_.inputCharConverter.readerRequired();
+                charConversionRequired_ = codeConverters_.inputCharConverter.conversionRequired();
             }
 
             if (codeConverters_.inputWcharConverter != null) {
-                wCharReaderRequired_ = codeConverters_.inputWcharConverter
-                        .readerRequired();
-                wCharConversionRequired_ = codeConverters_.inputWcharConverter
-                        .conversionRequired();
+                wCharReaderRequired_ = codeConverters_.inputWcharConverter.readerRequired();
+                wCharConversionRequired_ = codeConverters_.inputWcharConverter.conversionRequired();
             }
         }
     }
@@ -2000,10 +1892,8 @@
 
         byte[] data = new byte[buf_.len_];
         System.arraycopy(buf_.data_, 0, data, 0, buf_.len_);
-        org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
-                data, data.length);
-        result = new InputStream(buf, origPos_, origSwap_, codeConverters_,
-                GIOPVersion_);
+        org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(data, data.length);
+        result = new InputStream(buf, origPos_, origSwap_, codeConverters_, giopVersion_);
         result.orbInstance_ = orbInstance_;
 
         return result;
@@ -2017,11 +1907,8 @@
     public void _OB_skip(int n) {
         int newPos = buf_.pos_ + n;
         if (newPos < buf_.pos_ || newPos > buf_.len_)
-            throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         buf_.pos_ = newPos;
     }
@@ -2032,10 +1919,8 @@
 
             if (newPos < buf_.pos_ || newPos > buf_.len_)
                 throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorReadOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
             buf_.pos_ = newPos;
         }
@@ -2072,10 +1957,8 @@
 
         if (buf_.pos_ + 4 > buf_.len_)
             throw new org.omg.CORBA.MARSHAL(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongOverflow),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongOverflow,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    org.apache.yoko.orb.OB.MinorCodes.describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadLongOverflow),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorReadLongOverflow, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         if (swap_)
             return (buf_.data_[buf_.pos_++] & 0xff)
@@ -2102,29 +1985,38 @@
     }
 
     public void __setSendingContextRuntime(org.omg.SendingContext.CodeBase runtime) {
-    		sendingContextRuntime_ = runtime;
+        sendingContextRuntime_ = runtime;
     }
-    
-	public org.omg.SendingContext.CodeBase __getSendingContextRuntime() {
-		return sendingContextRuntime_;
-	}
 
-	public void __setCodeBase(String codebase) {
-		this.codebase_ = codebase;
-	}
-	
-	public String __getCodeBase() {
-		return codebase_;
-	}
-    
-    public String dumpData() {
-        return buf_.dumpData(); 
+    public org.omg.SendingContext.CodeBase __getSendingContextRuntime() {
+        return sendingContextRuntime_;
     }
-    
+
+    public void __setCodeBase(String codebase) {
+        this.codebase_ = codebase;
+    }
+
+    public String __getCodeBase() {
+        return codebase_;
+    }
+
+    public String dumpData() {
+        return buf_.dumpData();
+    }
+
     private void checkChunk() {
         if (valueReader_ != null) {
             valueReader_.checkChunk();
         }
     }
-}
 
+    @Override
+    public void end_value() {
+        valueReader().endValue();
+    }
+
+    @Override
+    public void start_value() {
+        valueReader().beginValue();
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/ObjectImpl.java b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/ObjectImpl.java
index c95bb58..5a456c2 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/ObjectImpl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/ObjectImpl.java
@@ -17,6 +17,8 @@
 
 package org.apache.yoko.orb.CORBA;
 
+import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_2;
+
 import org.apache.yoko.osgi.ProviderLocator;
 
 //
@@ -173,7 +175,7 @@
         org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
                 32);
         org.apache.yoko.orb.CORBA.OutputStream out = new org.apache.yoko.orb.CORBA.OutputStream(
-                buf, null, 258);
+                buf, null, GIOP1_2);
 
         //
         // Put the exception into the output stream
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/OutputStream.java b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/OutputStream.java
index 0e8740d..c9f627f 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/OutputStream.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/OutputStream.java
@@ -20,14 +20,17 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-final public class OutputStream extends org.omg.CORBA_2_3.portable.OutputStream {
-    static final Logger logger = Logger.getLogger(OutputStream.class.getName());
-    
+import org.apache.yoko.orb.OCI.GiopVersion;
+import org.omg.CORBA.portable.ValueOutputStream;
+
+final public class OutputStream extends org.omg.CORBA_2_3.portable.OutputStream implements ValueOutputStream {
+    static final Logger LOGGER = Logger.getLogger(OutputStream.class.getName());
+
     private org.apache.yoko.orb.OB.ORBInstance orbInstance_; // Java only
 
     public org.apache.yoko.orb.OCI.Buffer buf_;
 
-    private int GIOPVersion_ = org.apache.yoko.orb.OB.OB_Extras.DEFAULT_GIOP_VERSION;
+    private GiopVersion giopVersion_ = org.apache.yoko.orb.OB.OB_Extras.DEFAULT_GIOP_VERSION;
 
     private org.apache.yoko.orb.OB.CodeConverters codeConverters_;
 
@@ -60,7 +63,7 @@
 
     // Write a gap of four bytes (ulong aligned), avoids byte shifts
     private int writeGap() {
-        logger.finest("Writing a gap value"); 
+        LOGGER.finest("Writing a gap value");
         addCapacity(4, 4);
         int result = buf_.pos_;
         buf_.pos_ += 4;
@@ -69,7 +72,7 @@
 
     private void writeLength(int start) {
         int length = buf_.pos_ - (start + 4);
-        logger.finest("Writing a length value of " + length + " at offset " + start); 
+        LOGGER.finest("Writing a length value of " + length + " at offset " + start);
 
         buf_.data_[start++] = (byte) (length >>> 24);
         buf_.data_[start++] = (byte) (length >>> 16);
@@ -102,8 +105,8 @@
                 return;
             }
         }
-        
-        logger.finest("Writing a type code of type " + tc.kind().value()); 
+
+        LOGGER.finest("Writing a type code of type " + tc.kind().value());
 
         //
         // For performance reasons, handle the primitive TypeCodes first
@@ -138,7 +141,7 @@
         if (indirectionPos != null) {
             write_long(-1);
             int offs = indirectionPos.intValue() - buf_.pos_;
-            logger.finest("Writing an indirect type code for offset " + offs); 
+            LOGGER.finest("Writing an indirect type code for offset " + offs);
             write_long(offs);
         } else {
             write_ulong(tc.kind().value());
@@ -434,6 +437,24 @@
         }
     }
 
+    private int roundUp(final int i, final int align) {
+        switch (align) {
+            case 0x00: return i;
+            case 0x01: return i;
+            case 0x02: return ((i + 0b0001) & ~(0b0001));
+            case 0x04: return ((i + 0b0011) & ~(0b0011));
+            case 0x08: return ((i + 0b0111) & ~(0b0111));
+            case 0x10: return ((i + 0b1111) & ~(0b1111));
+            default:
+                if (LOGGER.isLoggable(Level.WARNING))
+                    LOGGER.warning(String.format("Aligning on a strange number 0x%x", align));
+                final int j = (i + align - 1);
+                return (j - (j % align));
+        }
+    }
+
+    private static final byte PAD_BYTE = (byte)0xbd;
+
     private void addCapacity(int size, int align) {
         // use addCapacity(int) if align == 0
         org.apache.yoko.orb.OB.Assert._OB_assert(align > 0);
@@ -455,12 +476,7 @@
             alignNext_ = 0;
         }
 
-        //
-        // Align to the requested boundary
-        //
-        int newPos = buf_.pos_ + align - 1;
-        newPos -= newPos % align;
-        buf_.pos_ = newPos;
+        final int newPos = roundUp(buf_.pos_, align);
 
         //
         // If there isn't enough room, then reallocate the buffer
@@ -469,6 +485,13 @@
         if (len > buf_.len_) {
             buf_.realloc(len);
         }
+
+        //
+        // Pad to the requested boundary
+        //
+        for (; buf_.pos_ < newPos; buf_.pos_++) {
+            buf_.data_[buf_.pos_] = PAD_BYTE;
+        }
     }
 
     //
@@ -485,8 +508,8 @@
             // as ushort or ulong, depending on their maximum length
             // listed in the code set registry.
             //
-            switch (GIOPVersion_) {
-            case 0x0101: {
+            switch (giopVersion_) {
+            case GIOP1_1: {
                 if (converter.getTo().max_bytes <= 2)
                     write_ushort((short) value);
                 else
@@ -507,19 +530,17 @@
         // UTF-16
         //
         else {
-            switch (GIOPVersion_) {
-            case 0x0100:
-            case 0x0101: {
+            switch (giopVersion_) {
+            case GIOP1_0:
+            case GIOP1_1:
                 write_ushort((short) value);
-            }
                 break;
 
-            default: {
+            default:
                 addCapacity(3);
                 buf_.data_[buf_.pos_++] = 2;
                 buf_.data_[buf_.pos_++] = (byte) (value >> 8);
                 buf_.data_[buf_.pos_++] = (byte) value;
-            }
                 break;
             }
         }
@@ -533,7 +554,7 @@
 
         //
         // pre-convert the character if necessary
-        // 
+        //
         if (wCharConversionRequired_)
             value = converter.convert(value);
 
@@ -547,8 +568,8 @@
             // as ushort or ulong, depending on their maximum length
             // listed in the code set registry.
             //
-            switch (GIOPVersion_) {
-            case 0x0100: {
+            switch (giopVersion_) {
+            case GIOP1_0: {
                 //
                 // we don't support special writers for GIOP 1.0 if
                 // conversion is required or if a writer is required
@@ -557,7 +578,7 @@
             }
                 break;
 
-            case 0x0101: {
+            case GIOP1_1: {
                 //
                 // get the length of the character
                 //
@@ -605,8 +626,8 @@
                 break;
             }
         } else {
-            switch (GIOPVersion_) {
-            case 0x0100: {
+            switch (giopVersion_) {
+            case GIOP1_0: {
                 //
                 // Orbix2000/Orbacus/E compatible 1.0 marshal
                 //
@@ -618,13 +639,13 @@
 
                 //
                 // write 2-byte character in big endian
-                // 
+                //
                 buf_.data_[buf_.pos_++] = (byte) (value >>> 8);
                 buf_.data_[buf_.pos_++] = (byte) (value & 0xff);
             }
                 break;
 
-            case 0x0101: {
+            case GIOP1_1: {
                 write_ushort((short) value);
             }
                 break;
@@ -637,12 +658,12 @@
 
                 //
                 // write the octet length at the start
-                // 
+                //
                 buf_.data_[buf_.pos_++] = 2;
 
                 //
                 // write the character in big endian format
-                // 
+                //
                 buf_.data_[buf_.pos_++] = (byte) (value >>> 8);
                 buf_.data_[buf_.pos_++] = (byte) (value & 0xff);
             }
@@ -666,9 +687,9 @@
         // and contents include a terminating null. The terminating null
         // character for a wstring is also a wide character.
         //
-        switch (GIOPVersion_) {
-        case 0x0100:
-        case 0x0101: {
+        switch (giopVersion_) {
+        case GIOP1_0:
+        case GIOP1_1: {
             write_ulong(len + 1);
             write_wchar_array(arr, 0, len);
             write_wchar((char) 0);
@@ -729,7 +750,7 @@
         final char[] arr = value.toCharArray();
         final int len = arr.length;
 
-        logger.finest("Writing wstring value " + value); 
+        LOGGER.finest("Writing wstring value " + value);
         //
         // get converter/writer instance
         //
@@ -749,24 +770,26 @@
         // strings requiring a writer/converter (or not) since they can
         // be handled by the write_wchar() method
         //
-        if (GIOPVersion_ == 0x0100 || GIOPVersion_ == 0x0101) {
-            //
-            // write the length of the string
-            //
-            write_ulong(len + 1);
+        switch (giopVersion_) {
+            case GIOP1_0:
+            case GIOP1_1:
+                //
+                // write the length of the string
+                //
+                write_ulong(len + 1);
 
-            //
-            // now write all the characters
-            //
-            for (int i = 0; i < len; i++)
-                write_wchar(arr[i], true);
+                //
+                // now write all the characters
+                //
+                for (int i = 0; i < len; i++)
+                    write_wchar(arr[i], true);
 
-            // 
-            // and the null terminator
-            //
-            write_wchar((char) 0, true);
-
-            return;
+                //
+                // and the null terminator
+                //
+                write_wchar((char) 0, true);
+                return;
+            default:
         }
 
         //
@@ -777,7 +800,7 @@
 
         //
         // we've handled GIOP 1.0/1.1 above so this must be GIOP 1.2+
-        // 
+        //
         if (wCharWriterRequired_) {
             for (int i = 0; i < len; i++) {
                 char v = arr[i];
@@ -815,7 +838,7 @@
             for (int i = 0; i < len; i++) {
                 char v = arr[i];
 
-                // 
+                //
                 // check for conversion
                 //
                 if (wCharConversionRequired_)
@@ -843,7 +866,7 @@
         //
         // this matches the behaviour of this function in the Java ORB
         // and not what is outlined in the java.io.OutputStream
-        // 
+        //
         write_long(b);
     }
 
@@ -858,15 +881,15 @@
                 buf_.len_);
         if (buf_.len_ > 0)
             System.arraycopy(buf_.data_, 0, buf.data_, 0, buf_.len_);
-        
-// this is a useful tracepoint, but produces a lot of data, so turn on only 
-// if really needed. 
+
+// this is a useful tracepoint, but produces a lot of data, so turn on only
+// if really needed.
 //      if (logger.isLoggable(Level.FINEST)) {
-//          logger.fine("new input stream created:\n" + buf.dumpData()); 
+//          logger.fine("new input stream created:\n" + buf.dumpData());
 //      }
 
         InputStream in = new InputStream(buf, 0, false, codeConverters_,
-                GIOPVersion_);
+                giopVersion_);
         in._OB_ORBInstance(orbInstance_);
         return in;
     }
@@ -958,7 +981,7 @@
     }
 
     public void write_string(String value) {
-        logger.finest("Writing string value " + value); 
+        LOGGER.finest("Writing string value " + value);
         final char[] arr = value.toCharArray();
         int len = arr.length;
         int capacity = len + 1;
@@ -1187,7 +1210,7 @@
 
     public void write_Object(org.omg.CORBA.Object value) {
         if (value == null) {
-            logger.finest("Writing a null CORBA object value"); 
+            LOGGER.finest("Writing a null CORBA object value");
             org.omg.IOP.IOR ior = new org.omg.IOP.IOR();
             ior.type_id = "";
             ior.profiles = new org.omg.IOP.TaggedProfile[0];
@@ -1224,7 +1247,7 @@
     }
 
     public void write_any(org.omg.CORBA.Any value) {
-        logger.finest("Writing an ANY value of type " + value.type().kind()); 
+        LOGGER.finest("Writing an ANY value of type " + value.type().kind());
         write_TypeCode(value.type());
         value.write_value(this);
     }
@@ -1321,8 +1344,8 @@
         }
 
         try {
-            logger.fine("writing a value of type " + tc.kind().value()); 
-            
+            LOGGER.fine("writing a value of type " + tc.kind().value());
+
             switch (tc.kind().value()) {
             case org.omg.CORBA.TCKind._tk_null:
             case org.omg.CORBA.TCKind._tk_void:
@@ -1825,9 +1848,9 @@
                 org.apache.yoko.orb.OB.Assert._OB_assert("unsupported types");
             }
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            org.apache.yoko.orb.OB.Assert._OB_assert(ex);    
+            org.apache.yoko.orb.OB.Assert._OB_assert(ex);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            org.apache.yoko.orb.OB.Assert._OB_assert(ex);    
+            org.apache.yoko.orb.OB.Assert._OB_assert(ex);
         }
     }
 
@@ -1837,15 +1860,15 @@
     // ------------------------------------------------------------------
 
     public OutputStream(org.apache.yoko.orb.OCI.Buffer buf) {
-        this(buf, null, 0);
+        this(buf, null, null);
     }
 
     public OutputStream(org.apache.yoko.orb.OCI.Buffer buf,
-            org.apache.yoko.orb.OB.CodeConverters converters, int GIOPVersion) {
+            org.apache.yoko.orb.OB.CodeConverters converters, GiopVersion giopVersion) {
         buf_ = buf;
 
-        if (GIOPVersion != 0)
-            GIOPVersion_ = GIOPVersion;
+        if (giopVersion != null)
+            giopVersion_ = giopVersion;
 
         charWriterRequired_ = false;
         charConversionRequired_ = false;
@@ -1933,4 +1956,16 @@
     public java.lang.Object _OB_delegateContext() {
         return delegateContext_;
     }
+
+    @Override
+    public void end_value() {
+        _OB_endValue();
+    }
+
+    @Override
+    public void start_value(String rep_id) {
+        final int tag = 0x7fffff02;
+        final String[] ids = { rep_id };
+        _OB_beginValue(tag, ids, true);
+    }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/TypeCode.java b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/TypeCode.java
index 662412d..562a0a7 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/TypeCode.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CORBA/TypeCode.java
@@ -1229,8 +1229,9 @@
         if (inner.recId_ != null) {
             if (inner.recId_.equals(outer.id_)) {
                 if (inner.recType_ != null) {
+                    // Recursive TC already embedded - ensure it's the right one
                     org.apache.yoko.orb.OB.Assert
-                            ._OB_assert(inner.recType_ != outer);
+                            ._OB_assert(inner.recType_ == outer);
                 } else {
                     //
                     // Embed the recursive placeholder TypeCode
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming/TransientNameService.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming/TransientNameService.java
index 7739386..f1bb0d4 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming/TransientNameService.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming/TransientNameService.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -16,7 +16,6 @@
  *  limitations under the License.
  */
 
-
 /**
  * @version $Rev: 555715 $ $Date: 2007-07-12 11:36:16 -0700 (Thu, 12 Jul 2007) $
  */
@@ -25,7 +24,6 @@
 import java.util.Properties;
 
 import org.omg.CORBA.ORB;
-
 import org.omg.CORBA.Policy;
 import org.omg.PortableServer.IdAssignmentPolicyValue;
 import org.omg.PortableServer.LifespanPolicyValue;
@@ -33,12 +31,11 @@
 import org.omg.PortableServer.ServantRetentionPolicyValue;
 
 /**
- * A transient name service attached to an ORB.  This
- * class manages all of the housekeeping for creating a
- * TransientNamingContext and a exposing it using an
+ * A transient name service attached to an ORB. This class manages all of the
+ * housekeeping for creating a TransientNamingContext and a exposing it using an
  * ORB.
  */
-public class TransientNameService {
+public class TransientNameService implements AutoCloseable {
     // the default registered name service
     static public final String DEFAULT_SERVICE_NAME = "TNameService";
     // the default listening port
@@ -52,40 +49,35 @@
     protected int port;
     // initial listening host
     protected String host;
-    // the service name (used for registing for the corbaloc:: URL name
+    // the service name (used for registering for the corbaloc:: URL name
     protected String serviceName;
     // the orb instance we're running on
     protected ORB createdOrb;
 
-
     /**
-     * Create a new TransientNameService, using all default
-     * attributes.
+     * Create a new TransientNameService, using all default attributes.
      */
     public TransientNameService() {
         this(DEFAULT_SERVICE_HOST, DEFAULT_SERVICE_PORT, DEFAULT_SERVICE_NAME);
     }
 
     /**
-     * Create a default-named name service using the specified
-     * host and port parameters.
-     *
-     * @param host   The host to expose this under.
-     * @param port   The initial listening port.
+     * Create a default-named name service using the specified host and port
+     * parameters.
+     * @param host The host to expose this under.
+     * @param port The initial listening port.
      */
     public TransientNameService(String host, int port) {
         this(host, port, DEFAULT_SERVICE_NAME);
     }
 
-
     /**
-     * Create a specifically-named name service using the specified
-     * host and port parameters.
-     *
-     * @param host   The host to expose this under.
-     * @param port   The initial listening port.
-     * @param name   The name to register this service under using the
-     *               BootManager.
+     * Create a specifically-named name service using the specified host and
+     * port parameters.
+     * @param host The host to expose this under.
+     * @param port The initial listening port.
+     * @param name The name to register this service under using the
+     *            BootManager.
      */
     public TransientNameService(String host, int port, String name) {
         this.port = port;
@@ -94,64 +86,57 @@
     }
 
     /**
-     * Start up the name service, including creating an
-     * ORB instance to expose it under.
-     *
+     * Start up the name service, including creating an ORB instance to expose
+     * it under.
      * @exception TransientServiceException
      */
     public void run() throws TransientServiceException {
-	    // Create an ORB object
+        // Create an ORB object
         java.util.Properties props = new Properties();
         props.putAll(System.getProperties());
 
-	    props.put("org.omg.CORBA.ORBServerId", "1000000" ) ;
+        props.put("org.omg.CORBA.ORBServerId", "1000000");
         props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
         props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
         props.put("yoko.orb.oa.endpoint", "iiop --host " + host + " --port " + port);
-//      props.put("yoko.orb.poamanager.TNameService.endpoint", "iiop --host " + host);
 
-	    createdOrb = ORB.init((String[])null, props) ;
+        createdOrb = ORB.init((String[]) null, props);
 
         // now initialize the service
         initialize(createdOrb);
     }
 
     /**
-     * Initialize a transient name service on a specific
-     * ORB.
-     *
-     * @param orb    The ORB hosting the service.
-     *
+     * Initialize a transient name service on a specific ORB.
+     * @param orb The ORB hosting the service.
      * @exception TransientServiceException
      */
     public void initialize(ORB orb) throws TransientServiceException {
         try {
-            // get the root POA.  We're going to re
+            // Fire up the RootPOA
             POA rootPOA = (POA) orb.resolve_initial_references("RootPOA");
             rootPOA.the_POAManager().activate();
 
-            // we need to create a POA to manage this named instance, and then activate
-            // a context on it.
+            // we need to create a POA to manage this named instance, and then activate a context on it.
             Policy[] policy = new Policy[3];
             policy[0] = rootPOA.create_lifespan_policy(LifespanPolicyValue.TRANSIENT);
             policy[1] = rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.SYSTEM_ID);
             policy[2] = rootPOA.create_servant_retention_policy(ServantRetentionPolicyValue.RETAIN);
 
-            POA nameServicePOA = rootPOA.create_POA("TNameService", null, policy );
+            POA nameServicePOA = rootPOA.create_POA("TNameService", null, policy);
             nameServicePOA.the_POAManager().activate();
 
             // create our initial context, and register that with the ORB as the name service
             initialContext = new TransientNamingContext(orb, nameServicePOA);
 
-            //
-            // Resolve the Boot Manager and register the context object so we can resolve it
-            // using a corbaloc:: URL
-            org.apache.yoko.orb.OB.BootManager bootManager = org.apache.yoko.orb.OB.BootManagerHelper
-                    .narrow(orb.resolve_initial_references("BootManager"));
+            // Resolve the Boot Manager and register the context object so we can resolve it using a corbaloc:: URL
+            org.apache.yoko.orb.OB.BootManager bootManager = org.apache.yoko.orb.OB.BootManagerHelper.narrow(orb
+                    .resolve_initial_references("BootManager"));
             byte[] objectId = serviceName.getBytes();
             bootManager.add_binding(objectId, initialContext.getRootContext());
             // now register this as the naming service for the ORB as well.
-            ((org.apache.yoko.orb.CORBA.ORB)orb).register_initial_reference("NameService", initialContext.getRootContext());
+            ((org.apache.yoko.orb.CORBA.ORB) orb).register_initial_reference("NameService",
+                    initialContext.getRootContext());
         } catch (Exception e) {
             throw new TransientServiceException("Unable to initialize name service", e);
         }
@@ -167,5 +152,9 @@
             createdOrb = null;
         }
     }
-}
 
+    @Override
+    public void close() throws Exception {
+        destroy();
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/BindingIteratorImpl.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/BindingIteratorImpl.java
new file mode 100644
index 0000000..3d4322b
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/BindingIteratorImpl.java
@@ -0,0 +1,175 @@
+package org.apache.yoko.orb.CosNaming.tnaming2;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.yoko.orb.CosNaming.tnaming2.NamingContextImpl.BoundObject;
+import org.apache.yoko.orb.spi.naming.RemoteAccess;
+import org.omg.CORBA.LocalObject;
+import org.omg.CosNaming.Binding;
+import org.omg.CosNaming.BindingHolder;
+import org.omg.CosNaming.BindingIterator;
+import org.omg.CosNaming.BindingIteratorPOA;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.BindingType;
+import org.omg.CosNaming.NameComponent;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.Servant;
+
+public final class BindingIteratorImpl extends LocalObject implements BindingIterator, RemotableObject {
+    private static final long serialVersionUID = 1L;
+
+    private static final class Core extends BindingIteratorPOA {
+        private static final AtomicLong NEXT_ID = new AtomicLong();
+        private final long instanceId = NEXT_ID.getAndIncrement();
+        // the iterator use to access the bindings
+        private final Iterator<BoundObject> iterator;
+
+        private static final NameComponent[] ZERO_NC_ARRAY = new NameComponent[0];
+        /**
+         * Create a new BindingIterator to iterate over the given boundObjects.
+         * @param boundObjects The bound objects over which to iterate.
+         */
+        public Core(Collection<BoundObject> boundObjects) {
+            this.iterator = (new ArrayList<BoundObject>(boundObjects)).iterator();
+        }
+
+        private byte[] getServantId() {
+            return ("BindingIterator#" + instanceId).getBytes();
+        }
+
+        /**
+         * Return the next object in the iteration sequence.
+         * @param b The BindingHolder used to return the next item. If we've
+         *            reached the end of the sequence, an item with an empty
+         *            name is returned.
+         * @return true if there is another item, false otherwise.
+         */
+        public boolean next_one(org.omg.CosNaming.BindingHolder b) {
+            if (iterator.hasNext()) {
+                // return this as a Binding value.
+                BoundObject obj = iterator.next();
+                b.value = new Binding(new NameComponent[]{obj.name}, obj.type);
+                return true;
+            } else {
+                // return an empty element
+                b.value = new Binding(ZERO_NC_ARRAY, BindingType.nobject);
+                return false;
+            }
+        }
+
+        /**
+         * Retrieve the next "n" items from the list, returned as a BindingList.
+         * @param how_many The count of items to retrieve.
+         * @param bl A holder for returning an array of Bindings for the
+         *            returned items.
+         * @return true if any items were returned, false if there's nothing left
+         *         to return.
+         */
+        public boolean next_n(int how_many, org.omg.CosNaming.BindingListHolder bl) {
+            List<Binding> accum = new ArrayList<Binding>();
+            BindingHolder holder = new BindingHolder();
+            int i = 0;
+            // Keep iterating as long as there are entries
+            while (i < how_many && next_one(holder)) {
+                accum.add(holder.value);
+                i++;
+            }
+
+            // convert to an array and return whether we found anything.
+            bl.value = accum.toArray(new Binding[accum.size()]);
+            return accum.isEmpty();
+        }
+
+        /**
+         * Destroy this BindingIterator instance
+         */
+        public void destroy() {
+        }
+    }
+
+    private static final class POAServant extends BindingIteratorPOA {
+        // the POA used to activate this object (required for destroy();
+        private final POA poa;
+        private final Core core;
+
+        public POAServant(POA poa, Core core) throws Exception {
+            this.poa = poa;
+            this.core = core;
+            poa.activate_object_with_id(core.getServantId(), this);
+        }
+
+        /**
+         * Return the next object in the iteration sequence.
+         * @param b The BindingHolder used to return the next item. If we've
+         *            reached the end of the sequence, an item with an empty
+         *            name is returned.
+         * @return true if there is another item, false otherwise.
+         */
+        @Override
+        public boolean next_one(org.omg.CosNaming.BindingHolder b) {
+            return core.next_one(b);
+        }
+
+        /**
+         * Retrieve the next "n" items from the list, returned as a BindingList.
+         * @param how_many The count of items to retrieve.
+         * @param bl A holder for returning an array of Bindings for the
+         *            returned items.
+         * @return true if any items were returned, false if there's nothing left
+         *         to return.
+         */
+        @Override
+        public boolean next_n(int how_many, org.omg.CosNaming.BindingListHolder bl) {
+            return core.next_n(how_many, bl);
+        }
+
+        /**
+         * Destroy this BindingIterator instance, which deactivates it from the
+         * hosting POA.
+         */
+        @Override
+        public void destroy() {
+            try {
+                // we need to deactivate this from the POA.
+                byte[] objectId = poa.servant_to_id(this);
+                if (objectId != null) {
+                    poa.deactivate_object(objectId);
+                }
+            } catch (Exception e) {
+            }
+        }
+    }
+
+    private final Core core;
+
+    public BindingIteratorImpl(final Collection<BoundObject> boundObjects) {
+        assert boundObjects != null;
+        core = new Core(boundObjects);
+    }
+
+    @Override
+    public boolean next_one(BindingHolder b) {
+        assert b != null;
+        return core.next_one(b);
+    }
+
+    @Override
+    public boolean next_n(int how_many, BindingListHolder bl) {
+        assert bl != null;
+        return core.next_n(how_many, bl);
+    }
+
+    @Override
+    public void destroy() {
+        core.destroy();
+    }
+
+    @Override
+    public Servant getServant(POA poa, RemoteAccess ignored) throws Exception {
+        return new POAServant(poa, core);
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/NamingContextBase.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/NamingContextBase.java
new file mode 100644
index 0000000..94de6ea
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/NamingContextBase.java
@@ -0,0 +1,738 @@
+/**
+ *
+ * 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.
+ */
+
+/**
+ * @version $Rev: 553831 $ $Date: 2007-07-06 03:52:10 -0700 (Fri, 06 Jul 2007) $
+ */
+
+package org.apache.yoko.orb.CosNaming.tnaming2;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.yoko.orb.spi.naming.Resolvable;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.SystemException;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.BindingType;
+import org.omg.CosNaming.BindingTypeHolder;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextExtPOA;
+import org.omg.CosNaming.NamingContextHelper;
+import org.omg.CosNaming.NamingContextExtPackage.InvalidAddress;
+import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotEmpty;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+import org.omg.CosNaming.NamingContextPackage.NotFoundReason;
+
+public abstract class NamingContextBase extends NamingContextExtPOA {
+    // the real logger backing instance. We use the interface class as the locator
+    protected static final Logger logger = Logger.getLogger(NamingContext.class.getName());
+
+    // set of URL characters that don't require escaping when encoded.
+    protected final String nonEscaped = ";/?:@&=+$;-_.!~* ()";
+
+    /**
+     * Create a new base NamingContext (super class constructor for the derived
+     * classes).
+     */
+    public NamingContextBase() throws Exception {
+        super();
+    }
+
+    /**
+     * Bind an object to a given name.
+     * @param n An array of NameComponents that are the target name. The last
+     *            element in the array is binding name for the object. The
+     *            remainder of the array is the path for resolving the naming
+     *            context, relative to the current context. All path contexts
+     *            must already be bound in the context tree.
+     * @param obj The object to be bound.
+     */
+    public void bind(NameComponent[] n, org.omg.CORBA.Object obj)
+            throws NotFound, CannotProceed, InvalidName, AlreadyBound {
+        // perform various name validations
+        validateName(n);
+
+        logNameComponent("bind() name", n);
+
+        // do we need to push through to a deeper naming context first?
+        if (n.length > 1) {
+            // resolve the top level name to a context, and have that context
+            // resolve the rest.
+            NamingContext context = resolveContext(n[0]);
+            NameComponent[] subName = extractSubName(n);
+
+            // now pass this along to the next context for the real bind operation.
+            context.bind(subName, obj);
+        } else {
+            NameComponent name = n[0];
+            // we need the resolveObject() and bindObject() calls to be consistent, so
+            // synchronize on this
+            synchronized (this) {
+                // see if we have this bound already...can't replace these.
+                BindingTypeHolder type = new BindingTypeHolder();
+                if (resolveObject(name, type) != null) {
+                    throw new AlreadyBound();
+                }
+                type.value = BindingType.nobject;
+                // ok, this is a new binding, go do it.
+                bindObject(name, obj, type);
+            }
+        }
+    }
+
+    /**
+     * Rebind an object to a given name. If an object is already bound with this
+     * name, the new object replaces the bound object's value. If no object has
+     * been bound already, this is the same as a bind operation.
+     * @param n An array of NameComponents that are the target name. The last
+     *            element in the array is binding name for the object. The
+     *            remainder of the array is the path for resolving the naming
+     *            context, relative to the current context. All path contexts
+     *            must already be bound in the context tree.
+     * @param obj The new value for this binding.
+     */
+    public void rebind(NameComponent[] n, org.omg.CORBA.Object obj) throws NotFound, CannotProceed, InvalidName {
+        // perform various name validations
+        validateName(n);
+
+        logNameComponent("rebind() name", n);
+
+        // do we need to push through to a deeper naming context first?
+        if (n.length > 1) {
+            // resolve the top level name to a context, and have that context
+            // resolve the rest.
+            NamingContext context = resolveContext(n[0]);
+            NameComponent[] subName = extractSubName(n);
+
+            // now pass this along to the next context for the real bind operation.
+            context.rebind(subName, obj);
+        } else {
+            NameComponent name = n[0];
+            // we need the resolveObject() and bindObject() calls to be consistent, so
+            // synchronize on this
+            synchronized (this) {
+                // see if we have this bound already...can't replace these.
+                BindingTypeHolder type = new BindingTypeHolder();
+                // for a rebind, we must have an object, and it must be a real object
+                if (resolveObject(name, type) != null) {
+                    // it has to resolve to a real object. If it is a naming context,
+                    // then this is the wrong binding operation.
+                    if (type.value.value() == BindingType._ncontext) {
+                        throw new NotFound(NotFoundReason.not_object, n);
+                    }
+                    // safe to unbind
+                    unbindObject(name);
+                }
+                type.value = BindingType.nobject;
+                // now bind this object
+                bindObject(name, obj, type);
+            }
+        }
+    }
+
+    /**
+     * Bind a new context to a given name.
+     * @param n An array of NameComponents that are the target name. The last
+     *            element in the array is binding name for the object. The
+     *            remainder of the array is the path for resolving the naming
+     *            context, relative to the current context. All path contexts
+     *            must already be bound in the context tree.
+     * @param nc The new naming context added to the tree.
+     */
+    public void bind_context(NameComponent[] n, NamingContext nc) throws NotFound, CannotProceed, InvalidName, AlreadyBound {
+        // perform various name validations
+        validateName(n);
+
+        logNameComponent("bind_context() name", n);
+
+        // do we need to push through to a deeper naming context first?
+        if (n.length > 1) {
+            // resolve the top level name to a context, and have that context
+            // resolve the rest.
+            NamingContext context = resolveContext(n[0]);
+            NameComponent[] subName = extractSubName(n);
+
+            // now pass this along to the next context for the real bind operation.
+            context.bind_context(subName, nc);
+        } else {
+            NameComponent name = n[0];
+            // we need the resolveObject() and bindObject() calls to be consistent, so
+            // synchronize on this
+            synchronized (this) {
+                // see if we have this bound already...can't replace these.
+                BindingTypeHolder type = new BindingTypeHolder();
+                if (resolveObject(name, type) != null) {
+                    throw new AlreadyBound();
+                }
+                type.value = BindingType.ncontext;
+                // ok, this is a new binding, go do it.
+                bindObject(name, nc, type);
+            }
+        }
+    }
+
+    /**
+     * Rebind a context to a given name. If a context is already bound with this
+     * name, the new context replaces the existing context. If no context has
+     * been bound already, this is the same as a bind operation.
+     * @param n An array of NameComponents that are the target name. The last
+     *            element in the array is binding name for the object. The
+     *            remainder of the array is the path for resolving the naming
+     *            context, relative to the current context. All path contexts
+     *            must already be bound in the context tree.
+     * @param nc The new context to be bound with the name.
+     */
+    public void rebind_context(NameComponent[] n, NamingContext nc) throws NotFound, CannotProceed, InvalidName {
+        // perform various name validations
+        validateName(n);
+
+        logNameComponent("rebind_context() name", n);
+
+        // do we need to push through to a deeper naming context first?
+        if (n.length > 1) {
+            // resolve the top level name to a context, and have that context
+            // resolve the rest.
+            NamingContext context = resolveContext(n[0]);
+            NameComponent[] subName = extractSubName(n);
+
+            // now pass this along to the next context for the real bind operation.
+            context.rebind_context(subName, nc);
+        } else {
+            NameComponent name = n[0];
+            // we need the resolveObject() and bindObject() calls to be consistent, so
+            // synchronize on this
+            synchronized (this) {
+                // see if we have this bound already...can't replace these.
+                BindingTypeHolder type = new BindingTypeHolder();
+                // for a rebind, we must have an object, and it must be a real object
+                if (resolveObject(name, type) != null) {
+                    // it has to resolve to a real object. If it is a naming context,
+                    // then this is the wrong binding operation.
+                    if (type.value.value() != BindingType._ncontext) {
+                        throw new NotFound(NotFoundReason.not_context, n);
+                    }
+                    // safe to unbind
+                    unbindObject(name);
+                }
+                type.value = BindingType.ncontext;
+                // now bind this object
+                bindObject(name, nc, type);
+            }
+        }
+    }
+
+    /**
+     * Resolve an an entry in the context tree. The resolved object may be a
+     * bound object or another NamingContext. If the named entry is not found, a
+     * NotFound exception is thrown.
+     * @param n An array of NameComponents that are the target name. The last
+     *            element in the array is binding name for the object. The
+     *            remainder of the array is the path for resolving the naming
+     *            context, relative to the current context. All path contexts
+     *            must already be bound in the context tree.
+     * @return The object bound at the indicated location.
+     */
+    public org.omg.CORBA.Object resolve(NameComponent[] n) throws NotFound, CannotProceed, InvalidName {
+        // perform various name validations
+        validateName(n);
+
+        logNameComponent("resolve() name", n);
+
+        // do we need to push through to a deeper naming context first?
+        if (n.length > 1) {
+            // resolve the top level name to a context, and have that context
+            // resolve the rest.
+            NamingContext context = resolveContext(n[0]);
+            NameComponent[] subName = extractSubName(n);
+
+            // now pass this along to the next context for the real resolve operation.
+            return context.resolve(subName);
+        } else {
+            NameComponent name = n[0];
+            BindingTypeHolder type = new BindingTypeHolder();
+            org.omg.CORBA.Object obj = resolveObject(name, type);
+            if (obj == null) {
+                // Object was not found
+                throw new NotFound(NotFoundReason.missing_node, n);
+            }
+            if (obj instanceof Resolvable) {
+            	return ((Resolvable)obj).resolve();
+            } else {
+            	return obj;
+            }
+        }
+    }
+
+    /**
+     * Remove an entry from the context tree. The target object may be a bound
+     * object or another NamingContext. If the named entry is not found, a
+     * NotFound exception is thrown.
+     * @param n An array of NameComponents that are the target name. The last
+     *            element in the array is binding name for the object. The
+     *            remainder of the array is the path for resolving the naming
+     *            context, relative to the current context. All path contexts
+     *            must already be bound in the context tree.
+     * @exception NotFound
+     * @exception CannotProceed
+     * @exception InvalidName
+     * @exception AlreadyBound
+     */
+    public void unbind(NameComponent[] n) throws NotFound, CannotProceed, InvalidName {
+        // perform various name validations
+        validateName(n);
+
+        logNameComponent("unbind() name", n);
+
+        // do we need to push through to a deeper naming context first?
+        if (n.length > 1) {
+            // resolve the top level name to a context, and have that context
+            // resolve the rest.
+            NamingContext context = resolveContext(n[0]);
+            NameComponent[] subName = extractSubName(n);
+
+            // now pass this along to the next context for the real bind operation.
+            context.unbind(subName);
+        } else {
+            NameComponent name = n[0];
+            synchronized (this) {
+                // see if we have this bound already...can't replace these.
+                org.omg.CORBA.Object obj = unbindObject(name);
+                if (obj == null) {
+                    // Object was not found
+                    throw new NotFound(NotFoundReason.missing_node, n);
+                }
+            }
+        }
+    }
+
+    /**
+     * Create a new context and bind it in at the target location.
+     * @param n An array of NameComponents that are the target name. The last
+     *            element in the array is binding name for the object. The
+     *            remainder of the array is the path for resolving the naming
+     *            context, relative to the current context. All path contexts
+     *            must already be bound in the context tree.
+     * @return The newly created context.
+     */
+    public synchronized NamingContext bind_new_context(NameComponent[] n)
+            throws NotFound, AlreadyBound, CannotProceed, InvalidName {
+        logNameComponent("bind_new_context() name", n);
+
+        NamingContext context = new_context();
+        try {
+            bind_context(n, context);
+            NamingContext returnContext = context;
+            // transfer this to another variable so the finally block doesn't try to destroy this.
+            context = null;
+            return returnContext;
+        } finally {
+            // if there is a bind failure on this, we need to ensure the context has
+            // an opportunity to clean up any of its resources.
+            if (context != null) {
+                try {
+                    context.destroy();
+                } catch (NotEmpty e) {
+                    // new contexts should be empty.
+                }
+            }
+        }
+    }
+
+    /**
+     * Convert an array of NameComponents into the string form of a context
+     * name.
+     * @param n The array of NameComponents to convert.
+     * @return The context name, in string form.
+     */
+    public String to_string(NameComponent[] n) throws InvalidName {
+        validateName(n);
+
+        logNameComponent("to_string() name", n);
+
+        // convert the first part of the name
+        StringBuffer value = new StringBuffer();;
+        // convert the first component, then build up from there.
+        nameToString(n[0], value);
+
+        // the remainder need to get a separator
+        for (int i = 1; i < n.length; i++) {
+            value.append('/');
+            nameToString(n[i], value);
+        }
+        return value.toString();
+    }
+
+    /**
+     * Perform the reverse operation of the to_string() method, parsing a String
+     * context name into an array of NameComponents.
+     * @param sn The string form of the name.
+     * @return An array of NameComponents parsed from the String name.
+     */
+    public NameComponent[] to_name(String sn) throws InvalidName {
+        // must have a argument to parse
+        if (sn == null || sn.length() == 0) {
+            throw new InvalidName();
+        }
+
+        List<NameComponent> components = new ArrayList<NameComponent>();
+
+        StringBuffer component = new StringBuffer();
+
+        int index = 0;
+        String id = null;
+        String kind = null;
+        while (index < sn.length()) {
+            char ch = sn.charAt(index++);
+
+            // found an escape character or a delimiter?
+            if (ch == '\\') {
+                // nothing after the escape? Trouble
+                if (index >= sn.length()) {
+                    throw new InvalidName();
+                }
+                // get the next character
+                ch = sn.charAt(index++);
+                component.append(ch);
+            }
+            // we need to process the periods here, to avoid getting
+            // mixed up with unescaped periods.
+            else if (ch == '.') {
+                // already seen a period while scanning? That's not allowed
+                if (id != null) {
+                    throw new InvalidName();
+                }
+                // pull off the id piece and reset the buffer
+                id = component.toString();
+                component.setLength(0);
+            }
+            // found a component delimiter?
+            else if (ch == '/') {
+                // not seen a id/kind separator yet? This is an id with no kind
+                if (id == null) {
+                    id = component.toString();
+                    kind = "";
+                } else {
+                    // we have an id already, pull off the kind
+                    kind = component.toString();
+                }
+                // add the parsed name component
+                components.add(new NameComponent(id, kind));
+                // make sure these are all reset after pulling off a component
+                component.setLength(0);
+                id = null;
+                kind = null;
+            } else {
+                component.append(ch);
+            }
+        }
+
+        // parse the last section
+        // not seen a id/kind separator yet? This is an id with no kind
+        if (id == null) {
+            id = component.toString();
+            kind = "";
+        } else {
+            // we have an id already, pull off the kind
+            kind = component.toString();
+        }
+        // add the parsed name component
+        components.add(new NameComponent(id, kind));
+
+        // and turn this into a component array
+        return (NameComponent[]) components.toArray(new NameComponent[components.size()]);
+    }
+
+    /**
+     * Create a URL name for accessing a component by name. The URL will have a
+     * corbaname: protocol.
+     * @param addr The address location for the naming service used to resolve
+     *            the object. This is in "host:port" form, just line a corbaloc:
+     *            URL.
+     * @param sn The string mae of the target object.
+     * @return A URL for accessing this object, in String form.
+     */
+    public String to_url(String addr, String sn) throws InvalidAddress, InvalidName {
+        // basic validation
+        if (addr == null || addr.length() == 0) {
+            throw new InvalidAddress();
+        }
+
+        if (sn == null || sn.length() == 0) {
+            throw new InvalidName();
+        }
+
+        // TODO: What validation, if any, needs to be done here?
+        return "corbaname:" + addr + "#" + encodeRFC2396Name(sn);
+    }
+
+    /**
+     * Resolve a bound object or context using a name in String form.
+     * @param n The string name of the object context. This must be a form
+     *            parseable by to_name().
+     * @return The bound object or context.
+     */
+    public org.omg.CORBA.Object resolve_str(String n) throws NotFound, CannotProceed, InvalidName {
+        // this is just a simple convenience method
+        return resolve(to_name(n));
+    }
+
+    // abstract methods that are part of the NamingContext interface that need
+    // to be implemented by the subclasses.
+
+    /**
+     * Create a new context of the same type as the calling context.
+     * @return A new NamingContext item.
+     */
+    public abstract NamingContext new_context() throws SystemException;
+
+    /**
+     * Destroy a context. This method should clean up any backing resources
+     * associated with the context.
+     */
+    public abstract void destroy() throws NotEmpty;
+
+    /**
+     * Create a list of bound objects and contexts contained within this context.
+     * @param how_many The count of elements to return as a BindingList.
+     * @param bl A holder element for returning the source binding list.
+     * @param bi A holder for returning a BindingIterator. Any extra elements
+     *            not returned in the BindingList are returned in the
+     *            BindingIterator.
+     */
+    public abstract void list(int how_many, BindingListHolder bl,
+            BindingIteratorHolder bi) throws SystemException;
+
+    // abstract methods for the sub class to implement
+
+    /**
+     * Resolve an object in this context (single level resolution).
+     * @param n The name of the target object.
+     * @param type A type holder for returning the bound object type
+     *            information.
+     * @return The bound object. Returns null if the object does not exist in
+     *         the context.
+     */
+    protected abstract org.omg.CORBA.Object resolveObject(NameComponent n, BindingTypeHolder type) throws SystemException;
+
+    /**
+     * Bind an object into the current context. This can be either an object or
+     * a naming context.
+     * @param n The single-level name of the target object.
+     * @param obj The object or context to be bound.
+     * @param type
+     */
+    protected abstract void bindObject(NameComponent n, org.omg.CORBA.Object obj, BindingTypeHolder type) throws SystemException, CannotProceed;
+
+    /**
+     * Unbind an object from the current context.
+     * @param n The name of the target object (single level).
+     * @return The object associated with the binding. Returns null if there was
+     *         no binding currently associated with this name.
+     */
+    protected abstract org.omg.CORBA.Object unbindObject(NameComponent n) throws SystemException, CannotProceed;
+
+    // implementation specific routines
+
+    /**
+     * Resolve a name to a context object stored that has already been stored in
+     * this context. Throws an exception if the name cannot be resolved or if
+     * the resolved object is not a naming context.
+     * @param name The target name.
+     * @return The resolved NamingContext object.
+     */
+    protected synchronized NamingContext resolveContext(NameComponent name) throws NotFound {
+        BindingTypeHolder type = new BindingTypeHolder();
+        // Resolve this to an object. We must be able to resolve this.
+        org.omg.CORBA.Object resolvedReference = resolveObject(name, type);
+        if (resolvedReference == null) {
+            throw new NotFound(NotFoundReason.missing_node, new NameComponent[]{name});
+        }
+
+        // it has to resolve to a naming context
+        if (type.value.value() != BindingType._ncontext) {
+            throw new NotFound(NotFoundReason.not_context, new NameComponent[]{name});
+        }
+
+        // in theory, this is a naming context. Narrow it and return. Any
+        // errors just become a NotFound exception
+        try {
+            return NamingContextHelper.narrow(resolvedReference);
+        } catch (org.omg.CORBA.BAD_PARAM ex) {
+            throw new NotFound(NotFoundReason.not_context, new NameComponent[]{name});
+        }
+    }
+
+    /**
+     * Extract the tail portion of a name. This is used to strip off the first
+     * name element so we can recurse on the name resolutions with a resolved
+     * context.
+     * @param name The current name array (this MUST have 2 or more elements).
+     * @return An array of NameComponent items that is one element smaller than
+     *         the argument array, with the elements shifted over.
+     */
+    protected NameComponent[] extractSubName(NameComponent[] name) {
+        NameComponent[] subName = new NameComponent[name.length - 1];
+        System.arraycopy(name, 1, subName, 0, name.length - 1);
+        return subName;
+    }
+
+    /**
+     * Perform common name validity checking.
+     * @param n The NameComponent array to check.
+     */
+    protected void validateName(NameComponent[] n) throws InvalidName {
+        // perform various name validations
+        if (n == null) {
+            throw new BAD_PARAM(org.apache.yoko.orb.OB.MinorCodes.MinorObjectIsNull, CompletionStatus.COMPLETED_NO);
+        }
+
+        // Valid name?
+        if (n.length < 1) {
+            throw new InvalidName();
+        }
+
+        // we have at least one name, so validate the toplevel item
+        NameComponent name = n[0];
+
+        // for remote invocation, client would have received an NPE on marshalling a NameComponent with a null field
+        // for local invocation, ok to propagate the NPE and not a CORBA BAD_PARAM
+        Objects.requireNonNull(name.id, "A NameComponent must not have a null id field");
+        Objects.requireNonNull(name.kind, "A NameComponent must not have a null kind field");
+
+        // This ensures the name is not completely empty, but is this correct? CosNaming1.4 2.4.1 says:
+        // > The single '.' character is the only representation of a name with empty id and kind fields.
+        if (name.id.isEmpty() && name.kind.isEmpty()) {
+            throw new InvalidName();
+        }
+    }
+
+    /**
+     * Convert a NameComponent item into a string form, appending it to a
+     * StringBuffer.
+     * @param name The source NameComponent.
+     * @param out The StringBuffer location used to store the name value
+     *            (appended to the end).
+     */
+    protected void nameToString(NameComponent name, StringBuffer out) {
+        // if the id is null, then we base off of the kind.
+        if (name.id == null || name.id.length() == 0) {
+            out.append(".");
+            // true null name element? That displays as a "."
+            if (name.kind != null && name.kind.length() != 0) {
+                escapeName(name.kind, out);
+            }
+        } else {
+            // escape the name
+            escapeName(name.id, out);
+            // have a kind qualifier to add on?
+            if (name.kind != null && name.kind.length() != 0) {
+                out.append(".");
+                escapeName(name.kind, out);
+            }
+        }
+    }
+
+    /**
+     * Process a name or kind element of a NameComponent, adding escape
+     * characters for '.' or '/' characters that might appear in the name.
+     * @param name The name element to process.
+     * @param out The StringBuffer to copy the escaped name into.
+     */
+    protected void escapeName(String name, StringBuffer out) {
+        // no characters requiring escapes (common)?
+        // use this directly
+        if (name.indexOf('.') == -1 && name.indexOf('/') == -1) {
+            out.append(name);
+        } else {
+            // scan the string adding the escapes
+            for (int i = 0; i < name.length(); i++) {
+                char ch = name.charAt(i);
+                if (ch == '.' || ch == '/' || ch == '\\') {
+                    out.append('\\');
+                }
+                out.append(ch);
+            }
+        }
+    }
+
+    /**
+     * Perform RFC 2396 escape encoding of a name value.
+     * @param name The input name value.
+     * @return An encoded name, with special characters converted into a hex
+     *         encoded value.
+     */
+    protected String encodeRFC2396Name(String name) {
+        StringBuffer value = new StringBuffer();
+
+        for (int i = 0; i < name.length(); i++) {
+            char ch = name.charAt(i);
+
+            // Alphanumerics and the "acceptable" set of special characters just
+            // get copied without encoding.
+            if (Character.isLetterOrDigit(ch) || nonEscaped.indexOf(ch) != -1) {
+                value.append(ch);
+            } else {
+                // this gets converted into a hex value, marked by "%".
+                value.append('%');
+                value.append(Integer.toHexString((int) ch));
+            }
+        }
+        return value.toString();
+    }
+
+    /**
+     * Test if debug logging is currently available.
+     * @return True if debug level (FINE) logging is currently turned on.
+     */
+    protected boolean isDebugEnabled() {
+        return logger.isLoggable(Level.FINE);
+    }
+
+    /**
+     * Log a line of debug output
+     * @param message The message to log
+     */
+    protected void debug(String message) {
+        logger.fine(message);
+    }
+
+    /**
+     * Log the name components passed in for a request.
+     * @param message A message describing the request context.
+     * @param n The array of name components.
+     */
+    protected void logNameComponent(String message, NameComponent[] n) {
+        if (isDebugEnabled()) {
+            debug(message);
+            for (int i = 0; i < n.length; i++) {
+                debug("   NameComponent " + i + " id=" + n[i].id + " kind=" + n[i].kind);
+            }
+        }
+    }
+
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/NamingContextImpl.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/NamingContextImpl.java
new file mode 100644
index 0000000..ff20584
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/NamingContextImpl.java
@@ -0,0 +1,506 @@
+package org.apache.yoko.orb.CosNaming.tnaming2;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.yoko.orb.spi.naming.RemoteAccess;
+import org.apache.yoko.orb.util.UnmodifiableEnumMap;
+import org.omg.CORBA.INTERNAL;
+import org.omg.CORBA.LocalObject;
+import org.omg.CORBA.NO_PERMISSION;
+import org.omg.CORBA.SystemException;
+import org.omg.CosNaming.BindingIteratorHelper;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.BindingType;
+import org.omg.CosNaming.BindingTypeHolder;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextHelper;
+import org.omg.CosNaming.NamingContextExtPackage.InvalidAddress;
+import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotEmpty;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.Servant;
+import org.omg.PortableServer.POAPackage.ObjectNotActive;
+
+public final class NamingContextImpl extends LocalObject implements NamingContextExt, RemotableObject {
+    private static final long serialVersionUID = 1L;
+
+    private static final class ServantCreationLock {
+    }
+
+    private static final class Core extends NamingContextBase {
+        private static final AtomicLong NEXT_ID = new AtomicLong();
+
+        /** Unique number for this core */
+        private final long instanceId = NEXT_ID.getAndIncrement();
+
+        /** the unique ids for this context's servants (one per remote access level) */
+        @SuppressWarnings("serial")
+        private final Map<RemoteAccess, String> servantIds = new UnmodifiableEnumMap<RemoteAccess, String>(RemoteAccess.class) {
+            public String computeValueFor(RemoteAccess key) {
+                return "NamingContext#" + instanceId + "$" + key;
+            }
+        };
+
+        /** the bindings maintained by this context */
+        private final HashMap<BindingKey, BoundObject> bindings = new HashMap<BindingKey, BoundObject>();
+
+        /** the root context object */
+        private final org.omg.CORBA.Object rootContext;
+
+        private Core(org.omg.CORBA.Object rootContext) throws Exception {
+            this.rootContext = rootContext;
+        }
+
+        /**
+         * Get the servant id to use for this context with the specified remote
+         * access level
+         */
+        private byte[] getServantId(RemoteAccess access) {
+            return servantIds.get(access).getBytes();
+        }
+
+        // abstract methods part of the interface contract that the
+        // implementation is required
+        // to supply.
+
+        /**
+         * Create a new context of the same type as the calling context.
+         * @return A new NamingContext item.
+         */
+        @Override
+        public NamingContext new_context() {
+            try {
+                // create a new context.
+                NamingContextImpl newContext = new NamingContextImpl(rootContext);
+
+                return newContext;
+            } catch (SystemException e) {
+                // just propagate system exceptions
+                throw e;
+            } catch (Exception e) {
+                throw (INTERNAL) (new INTERNAL("Unable to create new naming context").initCause(e));
+            }
+        }
+
+        /**
+         * Destroy a context. This method should clean up any backing resources
+         * associated with the context.
+         */
+        @Override
+        public synchronized void destroy() throws NotEmpty {
+            // still holding bound objects? Not allowed to destroy
+            if (!bindings.isEmpty()) {
+                throw new NotEmpty();
+            }
+        }
+
+        /**
+         * Create a list of bound objects an contexts contained within this
+         * context.
+         * @param how_many The count of elements to return as a BindingList.
+         * @param bl A holder element for returning the source binding list.
+         * @param bi A holder for returning a BindingIterator. Any extra
+         *            elements not returned in the BindingList are returned in
+         *            the BindingIterator.
+         */
+        @Override
+        public synchronized void list(int how_many, BindingListHolder bl, BindingIteratorHolder bi) {
+            BindingIteratorImpl iterator = new BindingIteratorImpl(bindings.values());
+            // have the iterator fill in the entries here
+            iterator.next_n(how_many, bl);
+            bi.value = iterator;
+        }
+
+        // lower level functions that are used by the base class
+
+        /**
+         * Resolve an object in this context (single level resolution).
+         * @param n The name of the target object.
+         * @param type A type holder for returning the bound object type
+         *            information.
+         * @return The bound object. Returns null if the object does not exist
+         *         in the context.
+         */
+        @Override
+        protected org.omg.CORBA.Object resolveObject(NameComponent n, BindingTypeHolder type) {
+            // special call to resolve the root context. This is the only one
+            // that goes backwards.
+            if (n.id.length() == 0 && n.kind.length() == 0) {
+                // this is a name context item, so set it properly.
+                type.value = BindingType.ncontext;
+                return rootContext;
+            }
+
+            BindingKey key = new BindingKey(n);
+            BoundObject obj = (BoundObject) bindings.get(key);
+            // if not in the table, just return null
+            if (obj == null) {
+                return null;
+            }
+            // update the type information and return the bound object
+            // reference.
+            type.value = obj.type;
+            return obj.boundObject;
+        }
+
+        /**
+         * Bind an object into the current context. This can be either an object
+         * or a naming context.
+         * @param n The single-level name of the target object.
+         * @param obj The object or context to be bound.
+         * @param type
+         */
+        @Override
+        protected void bindObject(NameComponent n, org.omg.CORBA.Object obj, BindingTypeHolder type) {
+            // fairly simple table put...
+            bindings.put(new BindingKey(n), new BoundObject(n, obj, type.value));
+        }
+
+        /**
+         * Unbind an object from the current context.
+         * @param n The name of the target object (single level).
+         * @return The object associated with the binding. Returns null if there
+         *         was no binding currently associated with this name.
+         */
+        @Override
+        protected org.omg.CORBA.Object unbindObject(NameComponent n) {
+            // remove the object from the hash table, returning the bound object
+            // if it exists.
+            BindingKey key = new BindingKey(n);
+            BoundObject obj = (BoundObject) bindings.remove(key);
+
+            if (obj != null) {
+                return obj.boundObject;
+            }
+            return null;
+        }
+
+        /**
+         * Internal class used for HashMap lookup keys.
+         */
+        private static final class BindingKey {
+            // the name component this is a HashMap key for.
+            private final NameComponent name;
+            private final int hashval;
+
+            /**
+             * Create a new BindingKey for a NameComponent.
+             * @param n The lookup name.
+             */
+            public BindingKey(NameComponent n) {
+                name = n;
+                hashval = Objects.hashCode(name.id) + Objects.hashCode(name.kind);
+            }
+
+            /**
+             * Return the hashcode associated with this binding key. The
+             * hashcode is created using the NameComponent id and kind fields.
+             * @return The lookup hashvalue associated with this key.
+             */
+            @Override
+            public int hashCode() {
+                return hashval;
+            }
+
+            /**
+             * Compare two BindingKeys for equality (used for HashMap lookups).
+             * @param other The comparison partner.
+             * @return True if the keys are equivalent, false otherwise.
+             */
+            @Override
+            public boolean equals(Object other) {
+                // if not given or the wrong type, this is false.
+                if (!!!(other instanceof BindingKey)) {
+                    return false;
+                }
+
+                BindingKey otherKey = (BindingKey) other;
+
+                return (Objects.equals(name.id, otherKey.name.id) && Objects.equals(name.kind, otherKey.name.kind));
+            }
+
+            @Override
+            public String toString() {
+                return "" + name;
+            }
+        }
+
+    }
+
+    private static abstract class POAServant extends NamingContextBase {
+        static POAServant create(NamingContextImpl localContext, Core core, POA poa, RemoteAccess remoteAccess) throws Exception {
+            switch (remoteAccess) {
+                case readOnly :
+                    return new ReadOnly(localContext, core, poa);
+                case readWrite :
+                    return new ReadWrite(localContext, core, poa);
+                default :
+                    throw new IllegalArgumentException("Unsupported remote access type: " + remoteAccess);
+            }
+        }
+
+        final Object localContext;
+        final NamingContextBase core;
+        final POA poa;
+
+        protected POAServant(NamingContextImpl localContext, Core core, POA poa, byte[] servantId) throws Exception {
+            this.localContext = localContext;
+            this.core = core;
+            this.poa = poa;
+            poa.activate_object_with_id(servantId, this);
+        }
+
+        abstract Servant convertLocalContextToRemoteContext(NamingContextImpl o) throws Exception;
+
+        @Override
+        protected final org.omg.CORBA.Object resolveObject(NameComponent n, BindingTypeHolder type) {
+            try {
+                org.omg.CORBA.Object o = core.resolveObject(n, type);
+                if (o == localContext) {
+                    return _this_object();
+                } else if (!!!(o instanceof NamingContextImpl)) {
+                    return o;
+                }
+                Servant poaNamingContext = convertLocalContextToRemoteContext((NamingContextImpl) o);
+                return NamingContextHelper.narrow(poaNamingContext._this_object());
+            } catch (SystemException e) {
+                // just propagate system exceptions
+                throw e;
+            } catch (Exception e) {
+                throw (INTERNAL) (new INTERNAL("Unable to create new naming context").initCause(e));
+            }
+        }
+
+        @Override
+        public final void list(int how_many, BindingListHolder bl, BindingIteratorHolder bi) {
+            core.list(how_many, bl, bi);
+            try {
+                Servant iterator = ((BindingIteratorImpl) bi.value).getServant(poa, null);
+                bi.value = BindingIteratorHelper.narrow(iterator._this_object());
+            } catch (SystemException e) {
+                // just propagate system exceptions
+                throw e;
+            } catch (Exception e) {
+                throw (INTERNAL) (new INTERNAL("Unable to activate BindingIterator").initCause(e));
+            }
+        }
+
+        private static final class ReadOnly extends POAServant {
+            ReadOnly(NamingContextImpl localContext, Core core, POA poa) throws Exception {
+                super(localContext, core, poa, core.getServantId(RemoteAccess.readOnly));
+            }
+
+            private SystemException newSystemException() {
+                return new NO_PERMISSION();
+            }
+
+            @Override
+            public NamingContext new_context() {
+                throw newSystemException();
+            }
+
+            @Override
+            protected void bindObject(NameComponent n, org.omg.CORBA.Object obj, BindingTypeHolder type) {
+                throw newSystemException();
+            }
+
+            @Override
+            protected org.omg.CORBA.Object unbindObject(NameComponent n) {
+                throw newSystemException();
+            }
+
+            @Override
+            protected Servant convertLocalContextToRemoteContext(NamingContextImpl context) throws Exception {
+                return context.getServant(poa, RemoteAccess.readOnly);
+            }
+
+            @Override
+            public void destroy() {
+                throw newSystemException();
+            }
+        }
+
+        private static final class ReadWrite extends POAServant {
+            ReadWrite(NamingContextImpl localContext, Core core, POA poa) throws Exception {
+                super(localContext, core, poa, core.getServantId(RemoteAccess.readWrite));
+            }
+
+            @Override
+            public NamingContext new_context() {
+                try {
+                    NamingContextImpl nci = (NamingContextImpl) core.new_context();
+                    Servant newContext = nci.getServant(poa, RemoteAccess.readWrite);
+                    return NamingContextHelper.narrow(newContext._this_object());
+                } catch (SystemException e) {
+                    // just propagate system exceptions
+                    throw e;
+                } catch (Exception e) {
+                    throw (INTERNAL) (new INTERNAL("Unable to create new naming context").initCause(e));
+                }
+            }
+
+            @Override
+            protected void bindObject(NameComponent n, org.omg.CORBA.Object obj, BindingTypeHolder type) throws SystemException, CannotProceed {
+                core.bindObject(n, obj, type);
+            }
+
+            @Override
+            protected org.omg.CORBA.Object unbindObject(NameComponent n) throws SystemException, CannotProceed {
+                return core.unbindObject(n);
+            }
+
+            protected Servant convertLocalContextToRemoteContext(NamingContextImpl context) throws Exception {
+                return context.getServant(poa, RemoteAccess.readWrite);
+            }
+
+            @Override
+            public void destroy() throws NotEmpty {
+                try {
+                    // we need to deactivate this from the POA.
+                    byte[] objectId = poa.servant_to_id(this);
+                    if (objectId != null) {
+                        poa.deactivate_object(objectId);
+                    }
+                } catch (Exception e) {
+                }
+            }
+        }
+    }
+
+    /**
+     * Internal class used to store bound objects in the HashMap.
+     */
+    public static final class BoundObject {
+        // the name this object is bound under.
+        public final NameComponent name;
+        // the type of binding (either nobject or ncontext).
+        public final BindingType type;
+        // the actual bound object.
+        public final org.omg.CORBA.Object boundObject;
+
+        /**
+         * Create a new object binding for our HashMap.
+         * @param name The bound object's name.
+         * @param boundObject The bound object (real object or NamingContext).
+         * @param type The type information associated with this binding.
+         */
+        private BoundObject(NameComponent name, org.omg.CORBA.Object boundObject, BindingType type) {
+            this.name = name;
+            this.boundObject = boundObject;
+            this.type = type;
+        }
+
+        @Override
+        public String toString() {
+            return name + "->" + boundObject;
+        }
+    }
+
+    private final Core core;
+
+    /** lock for servant creation */
+    private final Object servantCreationLock = new ServantCreationLock();
+
+    public NamingContextImpl() throws Exception {
+        core = new Core(this);
+    }
+
+    public NamingContextImpl(org.omg.CORBA.Object rootContext) throws Exception {
+        core = new Core(rootContext);
+    }
+
+    @Override
+    public void bind(NameComponent[] n, org.omg.CORBA.Object obj) throws NotFound, CannotProceed, InvalidName, AlreadyBound {
+        core.bind(n, obj);
+    }
+
+    @Override
+    public void bind_context(NameComponent[] n, NamingContext nc) throws NotFound, CannotProceed, InvalidName, AlreadyBound {
+        core.bind_context(n, nc);
+    }
+
+    @Override
+    public void rebind(NameComponent[] n, org.omg.CORBA.Object obj) throws NotFound, CannotProceed, InvalidName {
+        core.rebind(n, obj);
+    }
+
+    @Override
+    public void rebind_context(NameComponent[] n, NamingContext nc) throws NotFound, CannotProceed, InvalidName {
+        core.rebind_context(n, nc);
+    }
+
+    @Override
+    public org.omg.CORBA.Object resolve(NameComponent[] n) throws NotFound, CannotProceed, InvalidName {
+        return core.resolve(n);
+    }
+
+    @Override
+    public void unbind(NameComponent[] n) throws NotFound, CannotProceed, InvalidName {
+        core.unbind(n);
+    }
+
+    @Override
+    public void list(int how_many, BindingListHolder bl, BindingIteratorHolder bi) {
+        core.list(how_many, bl, bi);
+    }
+
+    @Override
+    public NamingContext new_context() {
+        return core.new_context();
+    }
+
+    @Override
+    public NamingContext bind_new_context(NameComponent[] n) throws NotFound, AlreadyBound, CannotProceed, InvalidName {
+        return core.bind_new_context(n);
+    }
+
+    @Override
+    public void destroy() throws NotEmpty {
+        core.destroy();
+    }
+
+    @Override
+    public Servant getServant(POA poa, RemoteAccess remoteAccess) throws Exception {
+        byte[] sid = core.getServantId(remoteAccess);
+
+        // synchronize around creation to avoid a race
+        synchronized (servantCreationLock) {
+            // check whether the servant needs to be created
+            try {
+                return poa.id_to_servant(sid);
+            } catch (ObjectNotActive expected) {
+                // guaranteed to be the unique creator-thread for this servant
+                return POAServant.create(this, core, poa, remoteAccess);
+            }
+        }
+    }
+
+    @Override
+    public String to_string(NameComponent[] n) throws InvalidName {
+        return core.to_string(n);
+    }
+
+    @Override
+    public NameComponent[] to_name(String sn) throws InvalidName {
+        return core.to_name(sn);
+    }
+
+    @Override
+    public String to_url(String addr, String sn) throws InvalidAddress, InvalidName {
+        return core.to_url(addr, sn);
+    }
+
+    @Override
+    public org.omg.CORBA.Object resolve_str(String n) throws NotFound, CannotProceed, InvalidName {
+        return core.resolve_str(n);
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/RemotableObject.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/RemotableObject.java
new file mode 100644
index 0000000..0290918
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/RemotableObject.java
@@ -0,0 +1,9 @@
+package org.apache.yoko.orb.CosNaming.tnaming2;
+
+import org.apache.yoko.orb.spi.naming.RemoteAccess;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.Servant;
+
+public interface RemotableObject {
+    Servant getServant(POA poa, RemoteAccess remoteAccess) throws Exception;
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientNameServer.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientNameServer.java
new file mode 100644
index 0000000..279d836
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientNameServer.java
@@ -0,0 +1,76 @@
+/**
+ *
+ * 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.
+ */
+
+/**
+ * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
+ */
+package org.apache.yoko.orb.CosNaming.tnaming2;
+
+/**
+ * A stand-alone naming service launchable from a command line.
+ */
+public class TransientNameServer {
+    /**
+     * Launch a name service as a stand alone process. The Host, port, and
+     * service name are controlled using program arguments.
+     * 
+     * @param args
+     *            The array of arguments for tailoring the service.
+     * 
+     * @exception Exception
+     */
+    public static void main(String args[]) throws Exception {
+        int port = TransientNameService.DEFAULT_SERVICE_PORT;
+        String host = TransientNameService.DEFAULT_SERVICE_HOST;
+        String serviceName = TransientNameService.DEFAULT_SERVICE_NAME;
+
+        // see if we have
+        for (int i = 0; i < args.length; i++) {
+            if (args[i].equals("-ORBInitialPort")) {
+                i++;
+                if (i < args.length) {
+                    port = java.lang.Integer.parseInt(args[i]);
+                } else {
+                    throw new IllegalArgumentException("Invalid -ORBInitialPort option");
+                }
+            } else if (args[i].equals("-ORBInitialHost")) {
+                i++;
+                if (i < args.length) {
+                    host = args[i];
+                } else {
+                    throw new IllegalArgumentException("Invalid -ORBInitialHost option");
+                }
+            } else if (args[i].equals("-ORBServiceName")) {
+                i++;
+                if (i < args.length) {
+                    serviceName = args[i];
+                } else {
+                    throw new IllegalArgumentException("Invalid -ORBServiceName option");
+                }
+            }
+
+        }
+        // create a services, and just spin it off. We wait forever after that.
+        try (TransientNameService service = new TransientNameService(host, port, serviceName)) {
+            service.run();
+            synchronized (service) {
+                service.wait();
+            }
+        }
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientNameService.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientNameService.java
new file mode 100644
index 0000000..ef4868f
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientNameService.java
@@ -0,0 +1,117 @@
+/**
+ *
+ * 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.
+ */
+
+/**
+ * @version $Rev: 555715 $ $Date: 2007-07-12 11:36:16 -0700 (Thu, 12 Jul 2007) $
+ */
+package org.apache.yoko.orb.CosNaming.tnaming2;
+
+import java.util.Properties;
+
+import org.apache.yoko.orb.spi.naming.NameServiceInitializer;
+import org.omg.CORBA.ORB;
+
+/**
+ * A transient name service attached to an ORB. This class manages all of the
+ * housekeeping for creating a TransientNamingContext and a exposing it using an
+ * ORB.
+ */
+public class TransientNameService implements AutoCloseable {
+    // the default registered name service
+    static public final String DEFAULT_SERVICE_NAME = "TNameService";
+    // the default listening port
+    static public final int DEFAULT_SERVICE_PORT = 900;
+    // the default host name
+    static public final String DEFAULT_SERVICE_HOST = "localhost";
+    // initial listening port
+    protected int port;
+    // initial listening host
+    protected String host;
+    // the service name (used for registering for the corbaloc:: URL name
+    protected String serviceName;
+    // the orb instance we're running on
+    protected ORB createdOrb;
+
+    /**
+     * Create a new TransientNameService, using all default attributes.
+     */
+    public TransientNameService() {
+        this(DEFAULT_SERVICE_HOST, DEFAULT_SERVICE_PORT, DEFAULT_SERVICE_NAME);
+    }
+
+    /**
+     * Create a default-named name service using the specified host and port
+     * parameters.
+     * @param host The host to expose this under.
+     * @param port The initial listening port.
+     */
+    public TransientNameService(String host, int port) {
+        this(host, port, DEFAULT_SERVICE_NAME);
+    }
+
+    /**
+     * Create a specifically-named name service using the specified host and
+     * port parameters.
+     * @param host The host to expose this under.
+     * @param port The initial listening port.
+     * @param name The name to register this service under using the
+     *            BootManager.
+     */
+    public TransientNameService(String host, int port, String name) {
+        this.port = port;
+        this.host = host;
+        this.serviceName = name;
+    }
+
+    /**
+     * Start up the name service, including creating an ORB instance to expose
+     * it under.
+     * @exception TransientServiceException
+     */
+    public void run() throws TransientServiceException {
+        // Create an ORB object
+        java.util.Properties props = new Properties();
+        props.putAll(System.getProperties());
+
+        props.put("org.omg.CORBA.ORBServerId", "1000000");
+        props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
+        props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
+        props.put("org.omg.PortableInterceptor.ORBInitializerClass." + NameServiceInitializer.class.getName(), "");
+        props.put("yoko.orb.oa.endpoint", "iiop --host " + host + " --port " + port);
+
+        createdOrb = ORB.init(new String[]{"ORBNameService=" + serviceName}, props);
+
+        // service initialized by orb initializer
+    }
+
+    /**
+     * Destroy the created service.
+     */
+    public void destroy() {
+        // only destroy this if we created the orb instance.
+        if (createdOrb != null) {
+            createdOrb.destroy();
+            createdOrb = null;
+        }
+    }
+
+    @Override
+    public void close() throws Exception {
+        destroy();
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientServiceException.java b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientServiceException.java
new file mode 100644
index 0000000..24f39fc
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/CosNaming/tnaming2/TransientServiceException.java
@@ -0,0 +1,39 @@
+/**
+ *
+ * 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.
+ */
+
+/**
+ * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
+ */
+package org.apache.yoko.orb.CosNaming.tnaming2;
+
+public class TransientServiceException extends Exception {
+    private static final long serialVersionUID = 1L;
+
+    public TransientServiceException() {
+        super();
+    }
+
+    public TransientServiceException(String reason) {
+        super(reason);
+    }
+
+    public TransientServiceException(String reason, Exception cause) {
+        super(reason, cause);
+    }
+
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Client.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Client.java
index 5cc1af9..bc98124 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Client.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Client.java
@@ -53,7 +53,7 @@
     //
     // Destroy the client
     //
-    public abstract void destroy(boolean terminate);
+    public abstract void destroy();
 
     //
     // Increment usage (not mutex protected)
@@ -85,7 +85,7 @@
     //
     // Get a new request ID
     //
-    public abstract int requestId();
+    public abstract int getNewRequestID();
 
     //
     // get a list of ServiceContexts that have to be sent on an AMI router
@@ -119,7 +119,7 @@
     //
     // Checks whether this client is equal to another client
     //
-    public abstract boolean equal(Client clt);
+    public abstract boolean matches(Client clt);
 
     //
     // Force connection establishment
@@ -130,4 +130,6 @@
     // Determines whether this client supports twoway invocations
     //
     public abstract boolean twoway();
+
+    public void prepareForDowncall(RefCountPolicyList policies) {}
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ClientManager.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ClientManager.java
index 20e6405..e5f6ff7 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ClientManager.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ClientManager.java
@@ -16,16 +16,14 @@
  */
 
 package org.apache.yoko.orb.OB;
- 
-import java.util.logging.Level;
+
+import java.util.Arrays;
+import java.util.Vector;
 import java.util.logging.Logger;
 
-import org.apache.yoko.orb.OB.CONNECTION_REUSE_POLICY_ID;
-import org.apache.yoko.orb.OB.ConnectionReusePolicy;
-import org.apache.yoko.orb.OB.ConnectionReusePolicyHelper;
-import org.apache.yoko.orb.OB.PROTOCOL_POLICY_ID;
-import org.apache.yoko.orb.OB.ProtocolPolicy;
-import org.apache.yoko.orb.OB.ProtocolPolicyHelper;
+import org.apache.yoko.orb.OCI.ConnectorInfo;
+import org.omg.CORBA.Policy;
+import org.omg.IOP.IOR;
 import org.omg.PortableServer.POAManagerPackage.State;
 
 public final class ClientManager {
@@ -40,12 +38,12 @@
     //
     // All clients
     //
-    private java.util.Vector allClients_ = new java.util.Vector();
+    private Vector<Client> allClients_ = new Vector<>();
 
     //
     // All reusable clients
     //
-    private java.util.Vector reusableClients_ = new java.util.Vector();
+    private Vector<Client> reusableClients_ = new Vector<>();
 
     //
     // The concurrency model with which new Clients are created
@@ -84,11 +82,7 @@
         //
         // Destroy all clients
         //
-        java.util.Enumeration e = allClients_.elements();
-        while (e.hasMoreElements()) {
-            Client client = (Client) e.nextElement();
-            client.destroy(false);
-        }
+        for (Client c : allClients_) c.destroy();
 
         //
         // Reset internal data
@@ -114,8 +108,7 @@
     //
     // Get a list of ClientProfilePairs for an IOR and a list of policies
     //
-    public synchronized java.util.Vector getClientProfilePairs(
-            org.omg.IOP.IOR ior, org.omg.CORBA.Policy[] policies) {
+    public synchronized Vector<ClientProfilePair> getClientProfilePairs(IOR ior, Policy[] policies) {
         Assert._OB_assert(ior.type_id != null);
 
         //
@@ -135,18 +128,15 @@
                     org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed,
                     org.omg.CORBA.CompletionStatus.COMPLETED_NO);
         }
-            
+
 
         //
         // Find out whether private clients are requested
         //
         boolean privateClients = false;
-        for (int i = 0; i < policies.length; i++) {
-            if (policies[i].policy_type() == CONNECTION_REUSE_POLICY_ID.value) {
-                ConnectionReusePolicy p = ConnectionReusePolicyHelper.narrow(policies[i]);
-                if (p.value() == false) {
-                    privateClients = true;
-                }
+        for (Policy pol : policies) {
+            if (pol.policy_type() == CONNECTION_REUSE_POLICY_ID.value) {
+                privateClients = !!!(ConnectionReusePolicyHelper.narrow(pol).value());
                 break;
             }
         }
@@ -155,9 +145,9 @@
         // Get the protocol policy, if any
         //
         ProtocolPolicy protocolPolicy = null;
-        for (int i = 0; i < policies.length; i++) {
-            if (policies[i].policy_type() == PROTOCOL_POLICY_ID.value) {
-                protocolPolicy = ProtocolPolicyHelper.narrow(policies[i]);
+        for (Policy pol : policies) {
+            if (pol.policy_type() == PROTOCOL_POLICY_ID.value) {
+                protocolPolicy = ProtocolPolicyHelper.narrow(pol);
                 break;
             }
         }
@@ -166,44 +156,39 @@
         // check whether the BiDir policy is enabled
         //
         boolean enableBidir = false;
-        for (int i = 0; i < policies.length; i++) {
-            if (policies[i].policy_type() == org.omg.BiDirPolicy.BIDIRECTIONAL_POLICY_TYPE.value) {
+        for (Policy pol : policies) {
+            if (pol.policy_type() == org.omg.BiDirPolicy.BIDIRECTIONAL_POLICY_TYPE.value) {
                 org.omg.BiDirPolicy.BidirectionalPolicy p = org.omg.BiDirPolicy.BidirectionalPolicyHelper
-                        .narrow(policies[i]);
+                        .narrow(pol);
                 if (p.value() == org.omg.BiDirPolicy.BOTH.value) {
                     enableBidir = true;
                 }
             }
         }
 
-        java.util.Vector pairs = new java.util.Vector();
+        Vector<ClientProfilePair> pairs = new Vector<>();
 
         //
         // First try to create CollocatedClients
         //
         org.apache.yoko.orb.OBPortableServer.POAManagerFactory pmFactory = orbInstance_.getPOAManagerFactory();
-        org.omg.PortableServer.POAManager[] managers = pmFactory.list();
-
-        for (int i = 0; i < managers.length; i++) {
+        for (org.omg.PortableServer.POAManager mgr : pmFactory.list()) {
             try {
-                org.apache.yoko.orb.OCI.Acceptor[] acceptors = ((org.apache.yoko.orb.OBPortableServer.POAManager) managers[i])
-                        .get_acceptors();
-
                 boolean local = false;
-                for (int j = 0; j < acceptors.length && !local; j++) {
-                    org.apache.yoko.orb.OCI.ProfileInfo[] localProfileInfos = acceptors[j].get_local_profiles(ior);
+                for (org.apache.yoko.orb.OCI.Acceptor acceptor : ((org.apache.yoko.orb.OBPortableServer.POAManager)mgr).get_acceptors()) {
+                    org.apache.yoko.orb.OCI.ProfileInfo[] localProfileInfos = acceptor.get_local_profiles(ior);
                     if (localProfileInfos.length > 0) {
                         local = true;
                     }
                 }
 
-                // we can get into hang situations if we return a collocated server for an 
-                // inactive POA.  This can happen with the RootPOA, which is generally not activated. 
-                if (local && managers[i].get_state() == State.ACTIVE) {
+                // we can get into hang situations if we return a collocated server for an
+                // inactive POA.  This can happen with the RootPOA, which is generally not activated.
+                if (local && mgr.get_state() == State.ACTIVE) {
                     //
                     // Retrieve the CollocatedServer from the POAManager
                     //
-                    org.apache.yoko.orb.OBPortableServer.POAManager_impl manager = (org.apache.yoko.orb.OBPortableServer.POAManager_impl) managers[i];
+                    org.apache.yoko.orb.OBPortableServer.POAManager_impl manager = (org.apache.yoko.orb.OBPortableServer.POAManager_impl) mgr;
                     CollocatedServer collocatedServer = manager._OB_getCollocatedServer();
 
                     //
@@ -215,11 +200,10 @@
                     Client client = new CollocatedClient(collocatedServer, concModel_, conv);
                     allClients_.addElement(client);
 
-                    org.apache.yoko.orb.OCI.ProfileInfo[] profileInfos = client.getUsableProfiles(ior, policies);
-                    for (int j = 0; j < profileInfos.length; j++) {
+                    for (org.apache.yoko.orb.OCI.ProfileInfo profileInfo : client.getUsableProfiles(ior, policies)) {
                         ClientProfilePair pair = new ClientProfilePair();
                         pair.client = client;
-                        pair.profile = profileInfos[j];
+                        pair.profile = profileInfo;
                         pairs.addElement(pair);
                     }
 
@@ -227,8 +211,7 @@
                     // TODO: Introduce reusable CollocatedClients?
                     //
                 }
-            } catch (org.omg.PortableServer.POAManagerPackage.AdapterInactive ex) {
-                // Ignore
+            } catch (org.omg.PortableServer.POAManagerPackage.AdapterInactive ignored) {
             }
         }
 
@@ -237,8 +220,7 @@
         // clients which are usable for the given IOR and policies
         //
         if (!privateClients) {
-            for (int i = 0; i < reusableClients_.size(); i++) {
-                Client reusableClient = (Client) reusableClients_.elementAt(i);
+            for (Client reusableClient : reusableClients_) {
 
                 //
                 // Skip any client whose protocol is not present in the
@@ -246,19 +228,15 @@
                 //
                 if (protocolPolicy != null) {
                     org.apache.yoko.orb.OCI.ConnectorInfo info = reusableClient.connectorInfo();
-                    if (info != null) {
-                        if (!protocolPolicy.contains(info.id())) {
-                            continue;
-                        }
+                    if (info != null && !protocolPolicy.contains(info.id())) {
+                        continue;
                     }
                 }
 
-                org.apache.yoko.orb.OCI.ProfileInfo[] profileInfos = reusableClient
-                        .getUsableProfiles(ior, policies);
-                for (int j = 0; j < profileInfos.length; j++) {
+                for (org.apache.yoko.orb.OCI.ProfileInfo profileInfo : reusableClient.getUsableProfiles(ior, policies)) {
                     ClientProfilePair pair = new ClientProfilePair();
                     pair.client = reusableClient;
-                    pair.profile = profileInfos[j];
+                    pair.profile = profileInfo;
                     pairs.addElement(pair);
                 }
             }
@@ -267,30 +245,22 @@
         //
         // Finally, create new GIOPClients for all connectors we can get
         //
-        org.apache.yoko.orb.OCI.ConFactoryRegistry conFactoryRegistry = orbInstance_
-                .getConFactoryRegistry();
-        org.apache.yoko.orb.OCI.ConFactory[] factories = conFactoryRegistry
-                .get_factories();
-        for (int i = 0; i < factories.length; i++) {
-            org.apache.yoko.orb.OCI.Connector[] connectors = factories[i]
-                    .create_connectors(ior, policies);
-            for (int j = 0; j < connectors.length; j++) {
+        org.apache.yoko.orb.OCI.ConFactoryRegistry conFactoryRegistry = orbInstance_.getConFactoryRegistry();
+        for (org.apache.yoko.orb.OCI.ConFactory factory : conFactoryRegistry.get_factories()) {
+            for (org.apache.yoko.orb.OCI.Connector connector : factory.create_connectors(ior, policies)) {
                 //
                 // Skip any connector whose protocol is not present in the
                 // protocol list
                 //
-                if (protocolPolicy != null)
-                {
-                    if (!protocolPolicy.contains(connectors[j].id())) {
-                        continue;
-                    }
+                if (protocolPolicy != null && !protocolPolicy.contains(connector.id())) {
+                    continue;
                 }
 
                 //
                 // Get all usable profiles
                 //
-                org.apache.yoko.orb.OCI.ProfileInfo[] profileInfos = connectors[j].get_usable_profiles(ior, policies);
-                Assert._OB_assert(profileInfos.length >= 1);
+                org.apache.yoko.orb.OCI.ProfileInfo[] profileInfos = connector.get_usable_profiles(ior, policies);
+                Assert._OB_assert(profileInfos.length != 0);
 
                 //
                 // Create a new GIOPClient for each usable profile, and set
@@ -298,25 +268,23 @@
                 // clients that are equivalent to other clients we already
                 // have.
                 //
-                for (int k = 0; k < profileInfos.length; k++) {
-                    CodeConverters conv = CodeSetUtil.getCodeConverters(
-                            orbInstance_, profileInfos[k]);
+                for (org.apache.yoko.orb.OCI.ProfileInfo profileInfo: profileInfos) {
+                    CodeConverters conv = CodeSetUtil.getCodeConverters(orbInstance_, profileInfo);
 
-                    Client client = new GIOPClient(orbInstance_, connectors[j],
-                            concModel_, conv, enableBidir);
+                    Client newClient = new GIOPClient(orbInstance_, connector, concModel_, conv, enableBidir);
 
                     if (!pairs.isEmpty()) {
-                        int l;
+                        boolean matched = false;
 
-                        for (l = 0; l < pairs.size(); l++) {
-                            ClientProfilePair pair = (ClientProfilePair) pairs.elementAt(l);
-                            if (pair.client.equal(client)) {
+                        for (ClientProfilePair pair : pairs) {
+                            if (pair.client.matches(newClient)) {
+                                matched = true;
                                 break;
                             }
                         }
 
-                        if (l != pairs.size()) {
-                            client.destroy(false);
+                        if (matched) {
+                            newClient.destroy();
                             continue;
                         }
                     }
@@ -324,17 +292,15 @@
                     //
                     // Add the new client to the list of all clients
                     //
-                    allClients_.addElement(client);
+                    allClients_.addElement(newClient);
 
                     //
                     // Add client/profile pairs
                     //
-                    org.apache.yoko.orb.OCI.ProfileInfo[] clientProfileInfos = client
-                            .getUsableProfiles(ior, policies);
-                    for (int l = 0; l < clientProfileInfos.length; l++) {
+                    for (org.apache.yoko.orb.OCI.ProfileInfo clientProfileInfo : newClient.getUsableProfiles(ior, policies)) {
                         ClientProfilePair pair = new ClientProfilePair();
-                        pair.client = client;
-                        pair.profile = clientProfileInfos[l];
+                        pair.client = newClient;
+                        pair.profile = clientProfileInfo;
                         pairs.addElement(pair);
                     }
 
@@ -343,7 +309,7 @@
                     // client to the list of existing reusable clients
                     //
                     if (!privateClients) {
-                        reusableClients_.addElement(client);
+                        reusableClients_.addElement(newClient);
                     }
                 }
             }
@@ -359,15 +325,13 @@
         if (!pairs.isEmpty() && protocolPolicy != null) {
             String[] protocols = protocolPolicy.value();
 
-            java.util.Vector newPairs = new java.util.Vector();
+            Vector<ClientProfilePair> newPairs = new Vector<>();
 
             //
             // First, add any pairs whose clients do not have ConnectorInfo
             //
-            for (int i = 0; i < pairs.size(); i++) {
-                ClientProfilePair pair = (ClientProfilePair) pairs.elementAt(i);
-                org.apache.yoko.orb.OCI.ConnectorInfo info = pair.client.connectorInfo();
-                if (info == null) {
+            for (ClientProfilePair pair : pairs) {
+                if (pair.client.connectorInfo() == null) {
                     newPairs.addElement(pair);
                 }
             }
@@ -375,14 +339,11 @@
             //
             // Next, add the pairs in the order specified by the policy
             //
-            for (int i = 0; i < protocols.length; i++) {
-                for (int j = 0; j < pairs.size(); j++) {
-                    ClientProfilePair pair = (ClientProfilePair) pairs.elementAt(j);
-                    org.apache.yoko.orb.OCI.ConnectorInfo info = pair.client.connectorInfo();
-                    if (info != null) {
-                        if (protocols[i].equals(info.id())) {
-                            newPairs.addElement(pair);
-                        }
+            for (String protocol : protocols) {
+                for (ClientProfilePair pair : pairs) {
+                    ConnectorInfo info = pair.client.connectorInfo();
+                    if (info != null && protocol.equals(info.id())) {
+                        newPairs.addElement(pair);
                     }
                 }
             }
@@ -405,14 +366,13 @@
         //
         // Increment the usage count on all clients
         //
-        for (int i = 0; i < pairs.size(); i++) {
-            ClientProfilePair pair = (ClientProfilePair) pairs.elementAt(i);
+        for (ClientProfilePair pair : pairs) {
             pair.client.incUsage();
         }
         return pairs;
     }
 
-    public synchronized void releaseClient(Client client, boolean terminate) {
+    public synchronized void releaseClient(Client client) {
         //
         // The ORB destroys this object, so it's an initialization error
         // if this operation is called after ORB destruction
@@ -437,37 +397,21 @@
         boolean inUse = client.decUsage();
 
         if (!inUse) {
-            int i;
+            reusableClients_.remove(client);
 
-            for (i = 0; i < reusableClients_.size(); i++) {
-                Client c = (Client) reusableClients_.elementAt(i);
-                if (c == client) {
-                    reusableClients_.removeElementAt(i);
-                    break;
-                }
+            if (allClients_.remove(client)) {
+                client.destroy();
+            } else {
+                Assert._OB_assert("Release called on unknown client");
             }
-
-            for (i = 0; i < allClients_.size(); i++) {
-                Client c = (Client) allClients_.elementAt(i);
-                if (c == client) {
-                    client.destroy(terminate);
-                    allClients_.removeElementAt(i);
-                    return;
-                }
-            }
-
-            Assert._OB_assert("Release called on unknown client");
         }
     }
 
     public boolean equivalent(org.omg.IOP.IOR ior1, org.omg.IOP.IOR ior2) {
-        org.apache.yoko.orb.OCI.ConFactoryRegistry conFactoryRegistry = orbInstance_
-                .getConFactoryRegistry();
+        org.apache.yoko.orb.OCI.ConFactoryRegistry conFactoryRegistry = orbInstance_.getConFactoryRegistry();
 
-        org.apache.yoko.orb.OCI.ConFactory[] factories = conFactoryRegistry
-                .get_factories();
-        for (int i = 0; i < factories.length; i++) {
-            if (!factories[i].equivalent(ior1, ior2)) {
+        for (org.apache.yoko.orb.OCI.ConFactory factory : conFactoryRegistry.get_factories()) {
+            if (!!!factory.equivalent(ior1, ior2)) {
                 return false;
             }
         }
@@ -475,14 +419,6 @@
     }
 
     public int hash(org.omg.IOP.IOR ior, int maximum) {
-        org.apache.yoko.orb.OCI.ConFactoryRegistry conFactoryRegistry = orbInstance_
-                .getConFactoryRegistry();
-
-        org.apache.yoko.orb.OCI.ConFactory[] factories = conFactoryRegistry.get_factories();
-        int hash = 0;
-        for (int i = 0; i < factories.length; i++) {
-            hash ^= factories[i].hash(ior, maximum);
-        }
-        return hash % (maximum + 1);
+        return Arrays.hashCode(orbInstance_.getConFactoryRegistry().get_factories());
     }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedClient.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedClient.java
index 8abd5fa..0a2f926 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedClient.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedClient.java
@@ -36,14 +36,14 @@
     //
     // Destroy the client
     //
-    public void destroy(boolean terminate) {
+    public void destroy() {
         // Nothing to do here
     }
 
     //
     // Get a new request ID
     //
-    public int requestId() {
+    public int getNewRequestID() {
         //
         // This operation *must* delegate to CollocatedServer, because
         // request IDs must be unique per CollocatedServer, not per
@@ -88,18 +88,10 @@
     //
     // Checks whether this client is equal to another client
     //
-    public boolean equal(Client cl) {
-        CollocatedClient client = null;
-        try {
-            client = (CollocatedClient) cl;
-        } catch (ClassCastException ex) {
-            return false;
-        }
-
-        if (server_ != client.server_)
-            return false;
-
-        return true;
+    public boolean matches(Client other) {
+        if (!!!(other instanceof CollocatedClient)) return false;
+        CollocatedClient that = (CollocatedClient) other;
+        return (this.server_ == that.server_);
     }
 
     //
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedServer.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedServer.java
index bd3ac2a..9bbcdbc 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedServer.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CollocatedServer.java
@@ -146,7 +146,7 @@
         // dispatch thread is used, we could avoid initializing the
         // state monitor when it is not needed.
         //
-        down.initStateMonitor();
+        down.allowWaiting();
 
         Upcall up;
 
@@ -344,8 +344,7 @@
 
         if (replySCL.length > 0) {
             synchronized (this) {
-                Downcall down = (Downcall) callMap_.get(new Integer(upcall
-                        .requestId()));
+                Downcall down = (Downcall) callMap_.get(new Integer(upcall.requestId()));
 
                 //
                 // Might be null if the request timed out or destroyed
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbalocURLScheme_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbalocURLScheme_impl.java
index e68a685..8d9fee0 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbalocURLScheme_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbalocURLScheme_impl.java
@@ -39,7 +39,7 @@
                 throw new org.omg.CORBA.BAD_PARAM(
                         MinorCodes
                                 .describeBadParam(org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart)
-                                + ": invalid character in key",
+                                + ": invalid character in key, char value = 0x" + Integer.toHexString(ch),
                         org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart,
                         org.omg.CORBA.CompletionStatus.COMPLETED_NO);
             }
@@ -80,7 +80,7 @@
                 throw new org.omg.CORBA.BAD_PARAM(
                         MinorCodes
                                 .describeBadParam(org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart)
-                                + ": invalid initial reference token",
+                                + ": invalid initial reference token \"" + keyStr + "\"",
                         org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart,
                         org.omg.CORBA.CompletionStatus.COMPLETED_NO);
             }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbanameURLScheme_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbanameURLScheme_impl.java
index 1e20a5d..da352c1 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbanameURLScheme_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/CorbanameURLScheme_impl.java
@@ -17,10 +17,17 @@
 
 package org.apache.yoko.orb.OB;
 
+import static org.apache.yoko.orb.OB.MinorCodes.MinorOther;
+import static org.omg.CORBA.CompletionStatus.COMPLETED_NO;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 import org.apache.yoko.orb.OB.CorbalocURLScheme;
 import org.apache.yoko.orb.OB.CorbalocURLSchemeHelper;
 import org.apache.yoko.orb.OB.URLRegistry;
 import org.apache.yoko.orb.OB.URLScheme;
+import org.omg.CORBA.BAD_PARAM;
 
 public class CorbanameURLScheme_impl extends org.omg.CORBA.LocalObject
         implements URLScheme {
@@ -115,6 +122,7 @@
         // Make a DII invocation on the Naming Service to resolve the
         // specified context
         //
+        Exception failureCause;
         try {
             //
             // Create typecodes for Name and NameComponent
@@ -144,7 +152,7 @@
                 throw new org.omg.CORBA.BAD_PARAM(
                         MinorCodes
                                 .describeBadParam(org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart)
-                                + ": invalid stringified name",
+                                + ": invalid stringified name \"" + fragment + "\"",
                         org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart,
                         org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
@@ -209,18 +217,22 @@
             //
             // Return the result if there was no exception
             //
-            if (request.env().exception() == null)
+            failureCause = request.env().exception();
+            if (failureCause == null)
                 return request.return_value().extract_Object();
+            
         } catch (org.omg.CORBA.SystemException ex) {
+            failureCause = ex;
             // Fall through
         } catch (org.omg.CORBA.UserException ex) {
+            failureCause = ex;
             // Fall through
         }
 
-        throw new org.omg.CORBA.BAD_PARAM(org.apache.yoko.orb.OB.MinorCodes
-                .describeBadParam(org.apache.yoko.orb.OB.MinorCodes.MinorOther)
-                + ": corbaname evaluation error", org.apache.yoko.orb.OB.MinorCodes.MinorOther,
-                org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+        final BAD_PARAM bp = new BAD_PARAM(MinorCodes.describeBadParam(MinorOther)
+                + ": corbaname evaluation error:" + failureCause.getMessage(), MinorOther,
+                COMPLETED_NO);
+        throw (BAD_PARAM)bp.initCause(failureCause);
     }
 
     public void destroy() {
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/DispatchRequest_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/DispatchRequest_impl.java
index 3cb2d8c..949cb84 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/DispatchRequest_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/DispatchRequest_impl.java
@@ -54,7 +54,6 @@
 
     public void invoke() {
         poa_._OB_dispatch(oid_, upcall_);
-
         upcall_ = null;
     }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java
index 541a63c..52b8c42 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Downcall.java
@@ -17,83 +17,59 @@
 
 package org.apache.yoko.orb.OB;
 
-import java.util.logging.Level;
+import java.util.Vector;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+
+import org.apache.yoko.orb.OCI.GiopVersion;
+import org.apache.yoko.orb.util.AutoLock;
+import org.apache.yoko.orb.util.AutoReadWriteLock;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.NO_RESPONSE;
+import org.omg.IOP.IOR;
+import org.omg.IOP.ServiceContext;
 
 public class Downcall {
-    //
-    // The ORBInstance object
-    //
-    protected ORBInstance orbInstance_;
-    
-    protected Logger logger_;   // the orbInstance_ logger object 
+    /** The ORBInstance object */
+    protected final ORBInstance orbInstance_;
 
-    //
-    // The client
-    //
-    protected Client client_;
+    private final Logger logger_;   // the orbInstance_ logger object
 
-    //
-    // The downcall emitter
-    //
-    protected DowncallEmitter emitter_;
+    /** The client */
+    private final Client client_;
 
-    //
-    // Information about the IOR profile
-    //
+    /** The downcall emitter */
+    private DowncallEmitter emitter_;
+
+    /** Information about the IOR profile */
     protected org.apache.yoko.orb.OCI.ProfileInfo profileInfo_;
 
-    //
-    // The list of policies
-    //
+    /** The list of policies */
     protected RefCountPolicyList policies_;
 
-    //
-    // The unique request ID
-    //
-    protected int reqId_;
+    /** The unique request ID */
+    private final int reqId_;
 
-    //
-    // The name of the operation
-    //
-    protected String op_;
+    /** The name of the operation */
+    protected final String op_;
 
-    //
-    // Whether a response is expected
-    //
-    protected boolean responseExpected_;
+    /** Whether a response is expected */
+    protected final boolean responseExpected_;
 
-    //
-    // The marshalled headers and parameters
-    //
-    protected org.apache.yoko.orb.CORBA.OutputStream out_;
+    /** The marshalled headers and parameters */
+    private org.apache.yoko.orb.CORBA.OutputStream out_;
 
-    //
-    // Holds the results of the operation
-    //
-    protected org.apache.yoko.orb.CORBA.InputStream in_;
+    /** Holds the results of the operation */
+    private org.apache.yoko.orb.CORBA.InputStream in_;
 
-    //
-    // The state of this invocation
-    //
-    protected static final int DowncallStateUnsent = 0;
+    /** The state of this invocation */
+    protected enum State { UNSENT, PENDING, NO_EXCEPTION, USER_EXCEPTION, SYSTEM_EXCEPTION, FAILURE_EXCEPTION, FORWARD, FORWARD_PERM }
+    
+    protected final AutoReadWriteLock stateLock = new AutoReadWriteLock();
+    
+    protected State state = State.UNSENT;
 
-    protected static final int DowncallStatePending = 1;
-
-    protected static final int DowncallStateNoException = 2;
-
-    protected static final int DowncallStateUserException = 3;
-
-    protected static final int DowncallStateSystemException = 4;
-
-    protected static final int DowncallStateFailureException = 5;
-
-    protected static final int DowncallStateForward = 6;
-
-    protected static final int DowncallStateForwardPerm = 7;
-
-    protected int state_;
-
-    protected java.lang.Object stateMonitor_;
+    private Condition stateWaitCondition;
 
     //
     // Holds the exception if state_ is DowncallStateUserException,
@@ -105,71 +81,62 @@
     // Holds the exception ID if state_ is DowncallStateUserException,
     // DowncallStateSystemException, or DowncallStateFailureException
     //
-    // In Java, we need this member in Downcall, rather than in PIDowncall
-    //
     protected String exId_;
 
     //
     // Holds the forward IOR if state_ is DowncallStateLocationForward
     // or DowncallLocationForwardPerm
     //
-    protected org.omg.IOP.IOR forwardIOR_;
+    protected IOR forwardIOR_;
 
-    //
-    // The request and reply service contexts
-    //
-    protected java.util.Vector requestSCL_ = new java.util.Vector();
+    /** The request and reply service contexts */
+    protected Vector<ServiceContext> requestSCL_ = new Vector<>();
 
-    protected java.util.Vector replySCL_ = new java.util.Vector();
+    protected Vector<ServiceContext> replySCL_ = new Vector<>();
 
     // ----------------------------------------------------------------------
     // Downcall private and protected member implementations
     // ----------------------------------------------------------------------
 
-    //
-    // Raise an exception if necessary
-    //
+    /** Raise an exception if necessary */
     void checkForException() throws LocationForward, FailureException {
-        switch (state_) {
-        case DowncallStateUserException:
-            //
-            // Do not raise UserException in Java
-            //
-            // if(ex_ != null) // Only raise if a user exception has been set
-            // throw ex_;
-            break;
+        try (AutoLock readLock = stateLock.getReadLock()) {
+            switch (state) {
+                case USER_EXCEPTION:
+                    //
+                    // Do not raise UserException in Java
+                    //
+                    // if(ex_ != null) // Only raise if a user exception has been set
+                    // throw ex_;
+                    break;
 
-        case DowncallStateSystemException:
-            Assert._OB_assert(ex_ != null);
-            // update the stack trace to have the caller's stack rather than the 
-            // receiver thread. 
-            ex_.fillInStackTrace();    
-            throw (org.omg.CORBA.SystemException) ex_;
+                case SYSTEM_EXCEPTION:
+                    Assert._OB_assert(ex_ != null);
+                    // update the stack trace to have the caller's stack rather than the 
+                    // receiver thread. 
+                    ex_.fillInStackTrace();    
+                    throw (org.omg.CORBA.SystemException) ex_;
 
-        case DowncallStateFailureException:
-            Assert._OB_assert(ex_ != null);
-            throw new FailureException((org.omg.CORBA.SystemException) ex_);
+                case FAILURE_EXCEPTION:
+                    Assert._OB_assert(ex_ != null);
+                    throw new FailureException((org.omg.CORBA.SystemException) ex_);
 
-        case DowncallStateForward:
-            Assert._OB_assert(forwardIOR_ != null);
-            throw new LocationForward(forwardIOR_, false);
+                case FORWARD:
+                    Assert._OB_assert(forwardIOR_ != null);
+                    throw new LocationForward(forwardIOR_, false);
 
-        case DowncallStateForwardPerm:
-            Assert._OB_assert(forwardIOR_ != null);
-            throw new LocationForward(forwardIOR_, true);
+                case FORWARD_PERM:
+                    Assert._OB_assert(forwardIOR_ != null);
+                    throw new LocationForward(forwardIOR_, true);
 
-        default:
-            break;
+                default:
+                    break;
+            }
         }
     }
 
-    //
-    // Java only
-    //
-    // Required for use by subclasses
-    //
-    protected final org.apache.yoko.orb.CORBA.OutputStream preMarshalBase()
-            throws LocationForward, FailureException {
+    /** Required for use by subclasses */
+    protected final org.apache.yoko.orb.CORBA.OutputStream preMarshalBase() throws LocationForward, FailureException {
         org.apache.yoko.orb.CORBA.OutputStreamHolder out = new org.apache.yoko.orb.CORBA.OutputStreamHolder();
         emitter_ = client_.startDowncall(this, out);
         out_ = out.value;
@@ -191,70 +158,73 @@
         policies_ = policies;
         op_ = op;
         responseExpected_ = resp;
-        state_ = DowncallStateUnsent;
-        stateMonitor_ = null;
+        // since this.state is not volatile we must use a lock to guarantee consistency
+        try (AutoLock writeLock = stateLock.getWriteLock()) {
+            state = State.UNSENT;
+        }
         ex_ = null;
 
         //
         // Get the next request ID
         //
-        reqId_ = client_.requestId();
+        client.prepareForDowncall(policies);
+        reqId_ = client_.getNewRequestID();
         
         logger_.debug("Downcall created for operation " + op + " with id " + reqId_); 
     }
 
-    public ORBInstance orbInstance() {
+    public final ORBInstance orbInstance() {
         return orbInstance_;
     }
 
-    public Client client() {
+    public final Client client() {
         return client_;
     }
 
-    public org.apache.yoko.orb.OCI.ProfileInfo profileInfo() {
+    public final org.apache.yoko.orb.OCI.ProfileInfo profileInfo() {
         return profileInfo_;
     }
 
-    public RefCountPolicyList policies() {
+    public final RefCountPolicyList policies() {
         return policies_;
     }
 
-    public Exception excep() {
+    public final Exception excep() {
         return ex_;
     }
 
-    public int requestId() {
+    public final int requestId() {
         return reqId_;
     }
 
-    public String operation() {
+    public final String operation() {
         return op_;
     }
 
-    public boolean responseExpected() {
+    public final boolean responseExpected() {
         return responseExpected_;
     }
 
-    public org.apache.yoko.orb.CORBA.OutputStream output() {
+    public final org.apache.yoko.orb.CORBA.OutputStream output() {
         return out_;
     }
 
-    public org.apache.yoko.orb.CORBA.InputStream input() {
+    public final org.apache.yoko.orb.CORBA.InputStream input() {
         return in_;
     }
 
-    public org.omg.IOP.ServiceContext[] getRequestSCL() {
+    public final org.omg.IOP.ServiceContext[] getRequestSCL() {
         org.omg.IOP.ServiceContext[] scl = new org.omg.IOP.ServiceContext[requestSCL_
                 .size()];
         requestSCL_.copyInto(scl);
         return scl;
     }
 
-    public void addToRequestSCL(org.omg.IOP.ServiceContext sc) {
+    public final void addToRequestSCL(org.omg.IOP.ServiceContext sc) {
         requestSCL_.addElement(sc);
     }
 
-    public void setReplySCL(org.omg.IOP.ServiceContext[] scl) {
+    public final void setReplySCL(org.omg.IOP.ServiceContext[] scl) {
         // Don't create a new Vector
         Assert._OB_assert(replySCL_.size() == 0);
         replySCL_.setSize(scl.length);
@@ -267,17 +237,17 @@
         return preMarshalBase();
     }
 
-    public void marshalEx(org.omg.CORBA.SystemException ex)
+    public final void marshalEx(org.omg.CORBA.SystemException ex)
             throws LocationForward, FailureException {
         setFailureException(ex);
         checkForException();
         Assert._OB_assert(false);
     }
 
-    public void postMarshal() throws LocationForward, FailureException {
+    public final void postMarshal() throws LocationForward, FailureException {
     }
 
-    public void locate() throws LocationForward, FailureException {
+    public final void locate() throws LocationForward, FailureException {
         Assert._OB_assert(responseExpected_);
         Assert._OB_assert(op_.equals("_locate"));
 
@@ -299,7 +269,7 @@
         checkForException();
     }
 
-    public void request() throws LocationForward, FailureException {
+    public final void request() throws LocationForward, FailureException {
         Assert._OB_assert(responseExpected_);
 
         //
@@ -319,7 +289,7 @@
         checkForException();
     }
 
-    public void oneway() throws LocationForward, FailureException {
+    public final void oneway() throws LocationForward, FailureException {
         Assert._OB_assert(!responseExpected_);
 
         if (policies_.syncScope == org.omg.Messaging.SYNC_WITH_TRANSPORT.value) {
@@ -333,7 +303,7 @@
         }
     }
 
-    public void deferred() throws LocationForward, FailureException {
+    public final void deferred() throws LocationForward, FailureException {
         Assert._OB_assert(responseExpected_);
 
         boolean finished = emitter_.send(this, true);
@@ -341,7 +311,7 @@
             checkForException();
     }
 
-    public void response() throws LocationForward, FailureException {
+    public final void response() throws LocationForward, FailureException {
         Assert._OB_assert(responseExpected_);
 
         boolean finished = emitter_.receive(this, true);
@@ -349,23 +319,25 @@
         checkForException();
     }
 
-    public boolean poll() throws LocationForward, FailureException {
+    public final boolean poll() throws LocationForward, FailureException {
         Assert._OB_assert(responseExpected_);
 
         boolean finished = emitter_.receive(this, false);
         if (finished) {
-            checkForException();
-            return state_ != DowncallStatePending;
+            try (AutoLock lock = stateLock.getReadLock()) {
+                checkForException();
+                return state != State.PENDING;
+            }
         } else
             return false;
     }
 
-    public org.apache.yoko.orb.CORBA.InputStream preUnmarshal()
+    public final org.apache.yoko.orb.CORBA.InputStream preUnmarshal()
             throws LocationForward, FailureException {
         return in_;
     }
 
-    public void unmarshalEx(org.omg.CORBA.SystemException ex)
+    public final void unmarshalEx(org.omg.CORBA.SystemException ex)
             throws LocationForward, FailureException {
         setFailureException(ex);
         checkForException();
@@ -382,291 +354,213 @@
         // the user exception, so we only want to raise UNKNOWN if we
         // don't have the ID
         //
-        if (state_ == DowncallStateUserException && ex_ == null
-                && exId_ == null)
-            setSystemException(new org.omg.CORBA.UNKNOWN(org.apache.yoko.orb.OB.MinorCodes
-                    .describeUnknown(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_YES));
-
-        checkForException();
-    }
-
-    public String unmarshalExceptionId() {
-        Assert._OB_assert(state_ == DowncallStateUserException);
-        int pos = in_._OB_pos();
-        String id = in_.read_string();
-        in_._OB_pos(pos);
-        return id;
-    }
-
-    public boolean unsent() {
-        return state_ == DowncallStateUnsent;
-    }
-
-    public boolean pending() {
-        return state_ == DowncallStatePending;
-    }
-
-    public boolean noException() {
-        return state_ == DowncallStateNoException;
-    }
-
-    public boolean userException() {
-        return state_ == DowncallStateUserException;
-    }
-
-    public boolean failureException() {
-        return state_ == DowncallStateFailureException;
-    }
-
-    public boolean systemException() {
-        return state_ == DowncallStateSystemException;
-    }
-
-    private void setPendingImpl() {
-        Assert._OB_assert(responseExpected_);
-        state_ = DowncallStatePending;
-    }
-
-    public void setPending() {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setPendingImpl();
-                stateMonitor_.notify();
-            }
-        } else
-            setPendingImpl();
-    }
-
-    private void setNoExceptionImpl(org.apache.yoko.orb.CORBA.InputStream in) {
-        state_ = DowncallStateNoException;
-        if (in == null) {
-            Assert._OB_assert(!responseExpected_);
-        } else {
-            Assert._OB_assert(responseExpected_);
-            in_ = in;
-            in_._OB_ORBInstance(orbInstance_);
-            CodeConverters codeConverters = client_.codeConverters();
-            in_._OB_codeConverters(codeConverters, (profileInfo_.major << 8)
-                    | profileInfo_.minor);
+        try (AutoLock lock = stateLock.getReadLock()) {
+            if (state == State.USER_EXCEPTION && ex_ == null && exId_ == null)
+                setSystemException(new org.omg.CORBA.UNKNOWN(org.apache.yoko.orb.OB.MinorCodes
+                        .describeUnknown(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException),
+                        org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException,
+                        org.omg.CORBA.CompletionStatus.COMPLETED_YES));
+            checkForException();
         }
     }
 
-    public void setNoException(org.apache.yoko.orb.CORBA.InputStream in) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setNoExceptionImpl(in);
-                stateMonitor_.notify();
+    public final String unmarshalExceptionId() {
+        try (AutoLock lock = stateLock.getReadLock()) {
+            Assert._OB_assert(state == State.USER_EXCEPTION);
+            int pos = in_._OB_pos();
+            String id = in_.read_string();
+            in_._OB_pos(pos);
+            return id;
+        }
+    }
+
+    public final boolean unsent() {
+        try (AutoLock lock = stateLock.getReadLock()) {
+            return state == State.UNSENT;
+        }
+    }
+
+    public final boolean pending() {
+        try (AutoLock lock = stateLock.getReadLock()) {
+            return state == State.PENDING;
+        }
+    }
+
+    public final boolean noException() {
+        try (AutoLock lock = stateLock.getReadLock()) {
+            return state == State.NO_EXCEPTION;
+        }
+    }
+
+    public final boolean userException() {
+        try (AutoLock lock = stateLock.getReadLock()) {
+            return state == State.USER_EXCEPTION;
+        }
+    }
+
+    public final boolean failureException() {
+        try (AutoLock lock = stateLock.getReadLock()) {
+            return state == State.FAILURE_EXCEPTION;
+        }
+    }
+
+    public final boolean systemException() {
+        try (AutoLock lock = stateLock.getReadLock()) {
+            return state == State.SYSTEM_EXCEPTION;
+        }
+    }
+
+    public final void setPending() {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(responseExpected_);
+            state = State.PENDING;
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
+    }
+
+    public final void setNoException(org.apache.yoko.orb.CORBA.InputStream in) {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            state = State.NO_EXCEPTION;
+            if (in == null) {
+                Assert._OB_assert(!responseExpected_);
+            } else {
+                Assert._OB_assert(responseExpected_);
+                in_ = in;
+                in_._OB_ORBInstance(orbInstance_);
+                CodeConverters codeConverters = client_.codeConverters();
+                in_._OB_codeConverters(codeConverters, GiopVersion.get(profileInfo_.major, profileInfo_.minor));
             }
-        } else
-            setNoExceptionImpl(in);
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
     }
 
-    private void setUserExceptionImpl(org.apache.yoko.orb.CORBA.InputStream in) {
-        Assert._OB_assert(in != null);
-        Assert._OB_assert(responseExpected_);
-        state_ = DowncallStateUserException;
-        in_ = in;
-        in_._OB_ORBInstance(orbInstance_);
-        CodeConverters codeConverters = client_.codeConverters();
-        in_._OB_codeConverters(codeConverters, (profileInfo_.major << 8)
-                | profileInfo_.minor);
-    }
-
-    public void setUserException(org.apache.yoko.orb.CORBA.InputStream in) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setUserExceptionImpl(in);
-                stateMonitor_.notify();
-            }
-        } else
-            setUserExceptionImpl(in);
-    }
-
-    private void setUserExceptionImpl(org.omg.CORBA.UserException ex,
-            String exId) {
-        Assert._OB_assert(responseExpected_);
-        Assert._OB_assert(ex_ == null);
-        state_ = DowncallStateUserException;
-        ex_ = ex;
+    public final void setUserException(org.apache.yoko.orb.CORBA.InputStream in) {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(in != null);
+            Assert._OB_assert(responseExpected_);
+            state = State.USER_EXCEPTION;
+            in_ = in;
+            in_._OB_ORBInstance(orbInstance_);
+            CodeConverters codeConverters = client_.codeConverters();
+            in_._OB_codeConverters(codeConverters, GiopVersion.get(profileInfo_.major, profileInfo_.minor));
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
     }
 
     public void setUserException(org.omg.CORBA.UserException ex, String exId) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setUserExceptionImpl(ex, exId);
-                stateMonitor_.notify();
-            }
-        } else
-            setUserExceptionImpl(ex, exId);
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(responseExpected_);
+            Assert._OB_assert(ex_ == null);
+            state = State.USER_EXCEPTION;
+            ex_ = ex;
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
     }
 
-    private void setUserExceptionImpl(org.omg.CORBA.UserException ex) {
+    public final void setUserException(org.omg.CORBA.UserException ex) {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(responseExpected_);
+            Assert._OB_assert(ex_ == null);
+            state = State.USER_EXCEPTION;
+            ex_ = ex;
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
+    }
+
+    public final void setUserException(String exId) {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(responseExpected_);
+            Assert._OB_assert(ex_ == null);
+            state = State.USER_EXCEPTION;
+            exId_ = exId;
+            logger_.debug("Received user exception " + exId);
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
+    }
+
+    public final void setSystemException(org.omg.CORBA.SystemException ex) {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(responseExpected_);
+            Assert._OB_assert(ex_ == null);
+            state = State.SYSTEM_EXCEPTION;
+            ex_ = ex;
+            logger_.debug("Received system exception", ex);
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
+    }
+
+    public final void setFailureException(org.omg.CORBA.SystemException ex) {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(ex_ == null);
+            state = State.FAILURE_EXCEPTION;
+            ex_ = ex;
+            logger_.debug("Received failure exception", ex);
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
+    }
+
+    public final void setLocationForward(IOR ior, boolean perm) {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(responseExpected_);
+            Assert._OB_assert(forwardIOR_ == null);
+            state = perm ? State.FORWARD_PERM : State.FORWARD;
+            forwardIOR_ = ior;
+            if (null != stateWaitCondition) stateWaitCondition.signalAll();
+        }
         Assert._OB_assert(responseExpected_);
-        Assert._OB_assert(ex_ == null);
-        state_ = DowncallStateUserException;
-        ex_ = ex;
-    }
-
-    public void setUserException(org.omg.CORBA.UserException ex) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setUserExceptionImpl(ex);
-                stateMonitor_.notify();
-            }
-        } else
-            setUserExceptionImpl(ex);
     }
 
     //
-    // Java only
-    //
-    // Required for portable stubs, which do not make the UserException
-    // instance available to the ORB
-    //
-    private void setUserExceptionImpl(String exId) {
-        Assert._OB_assert(responseExpected_);
-        Assert._OB_assert(ex_ == null);
-        state_ = DowncallStateUserException;
-        exId_ = exId;
-        logger_.debug("Received user exception " + exId);
-    }
-
-    public void setUserException(String exId) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setUserExceptionImpl(exId);
-                stateMonitor_.notify();
-            }
-        } else
-            setUserExceptionImpl(exId);
-    }
-
-    private void setSystemExceptionImpl(org.omg.CORBA.SystemException ex) {
-        Assert._OB_assert(responseExpected_);
-        Assert._OB_assert(ex_ == null);
-        state_ = DowncallStateSystemException;
-        ex_ = ex;
-        logger_.debug("Received system exception", ex);
-    }
-
-    public void setSystemException(org.omg.CORBA.SystemException ex) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setSystemExceptionImpl(ex);
-                stateMonitor_.notify();
-            }
-        } else
-            setSystemExceptionImpl(ex);
-    }
-
-    private void setFailureExceptionImpl(org.omg.CORBA.SystemException ex) {
-        Assert._OB_assert(ex_ == null);
-        state_ = DowncallStateFailureException;
-        ex_ = ex;
-        logger_.debug("Received failure exception", ex);
-    }
-
-    public void setFailureException(org.omg.CORBA.SystemException ex) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setFailureExceptionImpl(ex);
-                stateMonitor_.notify();
-            }
-        } else
-            setFailureExceptionImpl(ex);
-    }
-
-    private void setLocationForwardImpl(org.omg.IOP.IOR ior, boolean perm) {
-        Assert._OB_assert(responseExpected_);
-        Assert._OB_assert(forwardIOR_ == null);
-        if (perm)
-            state_ = DowncallStateForwardPerm;
-        else
-            state_ = DowncallStateForward;
-        forwardIOR_ = ior;
-    }
-
-    public void setLocationForward(org.omg.IOP.IOR ior, boolean perm) {
-        if (stateMonitor_ != null) {
-            synchronized (stateMonitor_) {
-                setLocationForwardImpl(ior, perm);
-                stateMonitor_.notify();
-            }
-        } else
-            setLocationForwardImpl(ior, perm);
-    }
-
-    //
-    // Initialize the state monitor. This operation must be called in
+    // Initialize the wait condition. This operation must be called in
     // order to be able to use one of the waitUntil...() operations
     // below
     //
-    public void initStateMonitor() {
-        Assert._OB_assert(stateMonitor_ == null);
-        stateMonitor_ = new java.lang.Object();
+    public final void allowWaiting() {
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(stateWaitCondition == null);
+            stateWaitCondition = lock.newCondition();
+        }
     }
 
-    //
-    // This operation try waits for a specific state, using the
-    // timeout from this downcall's policies. If the timeout expires,
-    // a NO_RESPONSE exception is raised.
-    //
-    // - If the first parameter is set to false, the operation returns
-    // immediately with false if the desired state cannot be
-    // reached.
-    //
-    // - If the return value is true, it's safe to access or modify
-    // the downcall object. If the return value if false, accessing
-    // or modifying the downcall object is not allowed, for thread
-    // safety reasons. (Because the downcall object is not thread
-    // safe.)
-    //
-    public boolean waitUntilCompleted(boolean block) {
+    /**
+     * This operation try waits for a completed state, using the
+     * timeout from this downcall's policies.
+     *
+     * @param block whether to wait for the call to complete
+     * @return true if the call has completed
+     * @throws NO_RESPONSE if a timeout was set and has elapsed
+     */
+    public final boolean waitUntilCompleted(boolean block) {
         //
         // Get the timeout
         //
         int t = policies_.requestTimeout;
 
         //
-        // Yield if non-blocking or blocking with zero timeout
-        //
-        if (!block || (block && t == 0)) {
-            Thread.yield();
-        }
-
-        //
         // Wait for the desired state, taking the timeout and blocking
         // flag into account
         //
-        Assert._OB_assert(stateMonitor_ != null);
-        synchronized (stateMonitor_) {
-            while (state_ == DowncallStateUnsent
-                    || state_ == DowncallStatePending) {
-                if (!block) {
-                    return false;
-                }
+        try (AutoLock lock = stateLock.getWriteLock()) {
+            Assert._OB_assert(stateWaitCondition != null);
+            while (state == State.UNSENT || state == State.PENDING) {
+                if (!block) return false;
 
                 try {
-                    if (t < 0) {
-                        stateMonitor_.wait();
+                    if (t <= 0) {
+                        stateWaitCondition.await();
                     } else {
-                        int oldState = state_;
+                        State oldState = state;
 
-                        stateMonitor_.wait(t);
+                        stateWaitCondition.await(t, TimeUnit.MILLISECONDS);
 
-                        if (state_ == oldState) {
-                            throw new org.omg.CORBA.NO_RESPONSE(
-                                    "Timeout during receive",
-                                    0,
-                                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
+                        if (state == oldState) {
+                            throw new NO_RESPONSE("Timeout during receive", 0, CompletionStatus.COMPLETED_MAYBE);
                         }
                     }
                 } catch (InterruptedException ex) {
                 }
             }
-
+            if (ex_ instanceof UnresolvedException) ex_ = ((UnresolvedException)ex_).resolve();
             //
             // The downcall has completed
             //
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/DowncallStub.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/DowncallStub.java
index 813e96e..b9fc57d 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/DowncallStub.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/DowncallStub.java
@@ -17,10 +17,52 @@
 
 package org.apache.yoko.orb.OB;
  
+import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_2;
+
+import java.util.Vector;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.apache.yoko.orb.OB.RETRY_ALWAYS;
+import org.omg.CORBA.BAD_INV_ORDER;
+import org.omg.CORBA.BooleanHolder;
+import org.omg.CORBA.COMM_FAILURE;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.ExceptionList;
+import org.omg.CORBA.NO_RESPONSE;
+import org.omg.CORBA.NVList;
+import org.omg.CORBA.NamedValue;
+import org.omg.CORBA.OBJECT_NOT_EXIST;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Policy;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.TRANSIENT;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.UserException;
+import org.omg.CORBA.portable.ApplicationException;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.RemarshalException;
+import org.omg.GIOP.MessageHeader_1_1;
+import org.omg.GIOP.MessageHeader_1_2Helper;
+import org.omg.GIOP.MsgType_1_1;
+import org.omg.GIOP.RequestHeader_1_2;
+import org.omg.GIOP.RequestHeader_1_2Helper;
+import org.omg.IOP.INVOCATION_POLICIES;
+import org.omg.IOP.IOR;
+import org.omg.IOP.ServiceContext;
+import org.omg.IOP.ServiceContextListHolder;
+import org.omg.MessageRouting.MessageBody;
+import org.omg.MessageRouting.PersistentRequest;
+import org.omg.MessageRouting.PersistentRequestRouter;
+import org.omg.MessageRouting.ReplyDestination;
+import org.omg.MessageRouting.ReplyDisposition;
+import org.omg.MessageRouting.RequestInfo;
+import org.omg.MessageRouting.RequestMessage;
+import org.omg.MessageRouting.Router;
+import org.omg.MessageRouting.RouterListHolder;
+import org.omg.Messaging.PolicyValue;
+import org.omg.Messaging.PolicyValueSeqHelper;
+import org.omg.Messaging.PolicyValueSeqHolder;
+import org.omg.Messaging.ReplyHandler;
 
 //
 // DowncallStub is equivalent to the C++ class OB::MarshalStubImpl
@@ -35,9 +77,9 @@
     //
     // The IOR and the original IOR
     //
-    private org.omg.IOP.IOR IOR_;
+    private IOR IOR_;
 
-    private org.omg.IOP.IOR origIOR_;
+    private IOR origIOR_;
 
     //
     // The list of policies
@@ -47,7 +89,7 @@
     //
     // All client/profile pairs
     //
-    private java.util.Vector clientProfilePairs_;
+    private Vector<ClientProfilePair> clientProfilePairs_;
 
     //
     // We need a class to carry the DowncallStub and Downcall across
@@ -63,8 +105,7 @@
     // Private and protected member implementations
     // ------------------------------------------------------------------
 
-    private synchronized Client getClientProfilePair(
-            org.apache.yoko.orb.OCI.ProfileInfoHolder profileInfo)
+    private synchronized Client getClientProfilePair(org.apache.yoko.orb.OCI.ProfileInfoHolder profileInfo)
             throws FailureException {
         //
         // Lazy initialization of the client/profile pairs
@@ -87,10 +128,7 @@
                 logger.fine("retry: no profiles available");
             }
 
-            throw new FailureException(new org.omg.CORBA.TRANSIENT(org.apache.yoko.orb.OB.MinorCodes
-                    .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorNoUsableProfileInIOR),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorNoUsableProfileInIOR,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO));
+            throw new FailureException(new TRANSIENT(org.apache.yoko.orb.OB.MinorCodes.describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorNoUsableProfileInIOR), org.apache.yoko.orb.OB.MinorCodes.MinorNoUsableProfileInIOR, CompletionStatus.COMPLETED_NO));
         }
 
         ClientProfilePair clientProfilePair = (ClientProfilePair) clientProfilePairs_.elementAt(0);
@@ -98,17 +136,15 @@
         return clientProfilePair.client;
     }
 
-    private void destroy(boolean terminate) {
+    private void destroy() {
         //
         // If the ORB has been destroyed then the clientManager can be nil
         //
         ClientManager clientManager = orbInstance_.getClientManager();
 
         if (clientManager != null && clientProfilePairs_ != null) {
-            for (int i = 0; i < clientProfilePairs_.size(); i++) {
-                ClientProfilePair pair = (ClientProfilePair) clientProfilePairs_
-                        .elementAt(i);
-                clientManager.releaseClient(pair.client, terminate);
+            for (ClientProfilePair pair: clientProfilePairs_) {
+                clientManager.releaseClient(pair.client);
             }
         }
 
@@ -116,7 +152,7 @@
     }
 
     protected void finalize() throws Throwable {
-        destroy(false);
+        destroy();
 
         super.finalize();
     }
@@ -125,8 +161,7 @@
     // Public member implementations
     // ------------------------------------------------------------------
 
-    public DowncallStub(ORBInstance orbInstance, org.omg.IOP.IOR ior,
-            org.omg.IOP.IOR origIOR, RefCountPolicyList policies) {
+    public DowncallStub(ORBInstance orbInstance, IOR ior, IOR origIOR, RefCountPolicyList policies) {
         clientProfilePairs_ = null;
 
         //
@@ -160,8 +195,7 @@
 
         PIManager piManager = orbInstance_.getPIManager();
         if (piManager.haveClientInterceptors()) {
-            return new PIDowncall(orbInstance_, client, profile.value,
-                    policies_, op, resp, IOR_, origIOR_, piManager);
+            return new PIDowncall(orbInstance_, client, profile.value, policies_, op, resp, IOR_, origIOR_, piManager);
         } else {
             return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
         }
@@ -178,47 +212,35 @@
         return new Downcall(orbInstance_, client, profile.value, policies_, "_locate", true);
     }
 
-    public Downcall createPIArgsDowncall(String op, boolean resp,
-            ParameterDesc[] argDesc, ParameterDesc retDesc,
-            org.omg.CORBA.TypeCode[] exceptionTC) throws FailureException {
+    public Downcall createPIArgsDowncall(String op, boolean resp, ParameterDesc[] argDesc, ParameterDesc retDesc, TypeCode[] exceptionTC) throws FailureException {
         org.apache.yoko.orb.OCI.ProfileInfoHolder profile = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
         Client client = getClientProfilePair(profile);
         Assert._OB_assert(client != null);
 
         if (!policies_.interceptor)
-            return new Downcall(orbInstance_, client, profile.value, policies_,
-                    op, resp);
+            return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
 
         PIManager piManager = orbInstance_.getPIManager();
         if (piManager.haveClientInterceptors()) {
-            return new PIArgsDowncall(orbInstance_, client, profile.value,
-                    policies_, op, resp, IOR_, origIOR_, piManager, argDesc,
-                    retDesc, exceptionTC);
+            return new PIArgsDowncall(orbInstance_, client, profile.value, policies_, op, resp, IOR_, origIOR_, piManager, argDesc, retDesc, exceptionTC);
         } else {
-            return new Downcall(orbInstance_, client, profile.value, policies_,
-                    op, resp);
+            return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
         }
     }
 
-    public Downcall createPIDIIDowncall(String op, boolean resp,
-            org.omg.CORBA.NVList args, org.omg.CORBA.NamedValue result,
-            org.omg.CORBA.ExceptionList exceptions) throws FailureException {
+    public Downcall createPIDIIDowncall(String op, boolean resp, NVList args, NamedValue result, ExceptionList exceptions) throws FailureException {
         org.apache.yoko.orb.OCI.ProfileInfoHolder profile = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
         Client client = getClientProfilePair(profile);
         Assert._OB_assert(client != null);
 
         if (!policies_.interceptor)
-            return new Downcall(orbInstance_, client, profile.value, policies_,
-                    op, resp);
+            return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
 
         PIManager piManager = orbInstance_.getPIManager();
         if (piManager.haveClientInterceptors()) {
-            return new PIDIIDowncall(orbInstance_, client, profile.value,
-                    policies_, op, resp, IOR_, origIOR_, piManager, args,
-                    result, exceptions);
+            return new PIDIIDowncall(orbInstance_, client, profile.value, policies_, op, resp, IOR_, origIOR_, piManager, args, result, exceptions);
         } else {
-            return new Downcall(orbInstance_, client, profile.value, policies_,
-                    op, resp);
+            return new Downcall(orbInstance_, client, profile.value, policies_, op, resp);
         }
     }
 
@@ -226,18 +248,15 @@
     // Marshalling interception points
     //
 
-    public org.apache.yoko.orb.CORBA.OutputStream preMarshal(Downcall down)
-            throws LocationForward, FailureException {
+    public org.apache.yoko.orb.CORBA.OutputStream preMarshal(Downcall down) throws LocationForward, FailureException {
         return down.preMarshal();
     }
 
-    public void marshalEx(Downcall down, org.omg.CORBA.SystemException ex)
-            throws LocationForward, FailureException {
+    public void marshalEx(Downcall down, SystemException ex) throws LocationForward, FailureException {
         down.marshalEx(ex);
     }
 
-    public void postMarshal(Downcall down) throws LocationForward,
-            FailureException {
+    public void postMarshal(Downcall down) throws LocationForward, FailureException {
         down.postMarshal();
     }
 
@@ -257,13 +276,11 @@
         down.oneway();
     }
 
-    public void deferred(Downcall down) throws LocationForward,
-            FailureException {
+    public void deferred(Downcall down) throws LocationForward, FailureException {
         down.deferred();
     }
 
-    public void response(Downcall down) throws LocationForward,
-            FailureException {
+    public void response(Downcall down) throws LocationForward, FailureException {
         down.response();
     }
 
@@ -275,26 +292,21 @@
     // Unmarshalling interception points
     //
 
-    public org.apache.yoko.orb.CORBA.InputStream preUnmarshal(Downcall down)
-            throws LocationForward, FailureException {
+    public org.apache.yoko.orb.CORBA.InputStream preUnmarshal(Downcall down) throws LocationForward, FailureException {
         return down.preUnmarshal();
     }
 
-    public org.apache.yoko.orb.CORBA.InputStream preUnmarshal(Downcall down,
-            org.omg.CORBA.BooleanHolder uex) throws LocationForward,
-            FailureException {
+    public org.apache.yoko.orb.CORBA.InputStream preUnmarshal(Downcall down, BooleanHolder uex) throws LocationForward, FailureException {
         org.apache.yoko.orb.CORBA.InputStream in = down.preUnmarshal();
         uex.value = down.userException();
         return in;
     }
 
-    public void unmarshalEx(Downcall down, org.omg.CORBA.SystemException ex)
-            throws LocationForward, FailureException {
+    public void unmarshalEx(Downcall down, SystemException ex) throws LocationForward, FailureException {
         down.unmarshalEx(ex);
     }
 
-    public void postUnmarshal(Downcall down) throws LocationForward,
-            FailureException {
+    public void postUnmarshal(Downcall down) throws LocationForward, FailureException {
         down.postUnmarshal();
     }
 
@@ -306,20 +318,18 @@
         return down.unmarshalExceptionId();
     }
 
-    public void setUserException(Downcall down, org.omg.CORBA.UserException ex,
-            String exId) {
+    public void setUserException(Downcall down, UserException ex, String exId) {
         down.setUserException(ex, exId);
     }
 
-    public void setUserException(Downcall down, org.omg.CORBA.UserException ex) {
+    public void setUserException(Downcall down, UserException ex) {
         down.setUserException(ex);
     }
 
     //
     // Handle a FailureException
     //
-    public synchronized void handleFailureException(Downcall down,
-            FailureException ex) throws FailureException {
+    public synchronized void handleFailureException(Downcall down, FailureException ex) throws FailureException {
         //
         // Only called if there is really a failure
         //
@@ -332,24 +342,21 @@
         Client client = down.client();
         org.apache.yoko.orb.OCI.ProfileInfo profile = down.profileInfo();
 
-        for (int i = 0; i < clientProfilePairs_.size(); i++) {
-            ClientProfilePair pair = (ClientProfilePair) clientProfilePairs_
-                    .elementAt(i);
-            if (pair.client == client && pair.profile == profile) {
-                ClientManager clientManager = orbInstance_.getClientManager();
-
-                //
-                // Make sure the ORB has not been destroyed
-                //
-                if (clientManager == null)
-                    throw new org.omg.CORBA.BAD_INV_ORDER(
-                            MinorCodes
-                                    .describeBadInvOrder(org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled),
+        final ClientManager clientManager = orbInstance_.getClientManager();
+        //
+        // Make sure the ORB has not been destroyed
+        //
+        if (clientManager == null)
+            throw new BAD_INV_ORDER(
+                    MinorCodes.describeBadInvOrder(
+                            org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled),
                             org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                            CompletionStatus.COMPLETED_NO);
 
-                clientManager.releaseClient(pair.client, false);
-                clientProfilePairs_.removeElementAt(i);
+        for (ClientProfilePair pair : clientProfilePairs_) {
+            if (pair.client == client && pair.profile == profile) {
+                clientManager.releaseClient(pair.client);
+                clientProfilePairs_.remove(pair);
                 break;
             }
         }
@@ -359,10 +366,8 @@
         //
         try {
             throw ex.exception;
-        } catch (org.omg.CORBA.COMM_FAILURE e) {
-        } catch (org.omg.CORBA.TRANSIENT e) {
-        } catch (org.omg.CORBA.NO_RESPONSE e) {
-        } catch (org.omg.CORBA.SystemException e) {
+        } catch (COMM_FAILURE|TRANSIENT|NO_RESPONSE forceRetry) {
+        } catch (SystemException systemException) {
             throw ex; // Not "throw e;"!
         }
 
@@ -370,8 +375,7 @@
         // We can't retry if RETRY_STRICT or RETRY_NEVER is set and the
         // completion status is not COMPLETED_NO
         //
-        if (policies_.retry.mode != RETRY_ALWAYS.value
-                && ex.exception.completed != org.omg.CORBA.CompletionStatus.COMPLETED_NO) {
+        if (policies_.retry.mode != RETRY_ALWAYS.value && ex.exception.completed != CompletionStatus.COMPLETED_NO) {
             throw ex;
         }
 
@@ -386,7 +390,6 @@
         //
         // OK, let's continue with the next profile
         //
-        CoreTraceLevels coreTraceLevels = orbInstance_.getCoreTraceLevels();
         logger.log(Level.FINE, "trying next profile", ex.exception);
     }
 
@@ -419,7 +422,7 @@
                         logger.fine("Twoway invocations not supported, returning true"); 
                         return true;
                     }
-                } catch (org.omg.CORBA.SystemException ex) {
+                } catch (SystemException ex) {
                     logger.log(Level.FINE, "Exception occurred during locate request", ex); 
                     throw new FailureException(ex);
                 }
@@ -431,7 +434,7 @@
                 postUnmarshal(down);
                 logger.fine("Object located"); 
                 return true;
-            } catch (org.omg.CORBA.OBJECT_NOT_EXIST ex) {
+            } catch (OBJECT_NOT_EXIST ex) {
                 logger.log(Level.FINE, "Object does not exist", ex); 
                 return false;
             } catch (FailureException ex) {
@@ -469,8 +472,7 @@
     // Prepare a request from a portable stub
     //
     public org.apache.yoko.orb.CORBA.OutputStream setupRequest(
-            org.omg.CORBA.Object self, String operation,
-            boolean responseExpected) throws LocationForward, FailureException {
+            org.omg.CORBA.Object self, String operation, boolean responseExpected) throws LocationForward, FailureException {
         while (true) {
             org.apache.yoko.orb.OB.Downcall downcall = createDowncall(
                     operation, responseExpected);
@@ -499,8 +501,7 @@
     //
     // public org.apache.yoko.orb.CORBA.OutputStream
     public org.apache.yoko.orb.OB.CodeConverters setupPollingRequest(
-            org.omg.IOP.ServiceContextListHolder sclHolder,
-            org.apache.yoko.orb.CORBA.OutputStreamHolder out)
+            ServiceContextListHolder sclHolder, org.apache.yoko.orb.CORBA.OutputStreamHolder out)
             throws FailureException {
         //
         // Create buffer to contain out marshalable data
@@ -513,8 +514,7 @@
         org.apache.yoko.orb.OCI.ProfileInfoHolder info = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
         Client client = getClientProfilePair(info);
 
-        out.value = new org.apache.yoko.orb.CORBA.OutputStream(buf, client
-                .codeConverters(), 258);
+        out.value = new org.apache.yoko.orb.CORBA.OutputStream(buf, client.codeConverters(), GIOP1_2);
 
         sclHolder.value = client.getAMIRouterSCL();
 
@@ -554,28 +554,23 @@
         //
         Client client = getClientProfilePair(info);
 
-        out.value = new org.apache.yoko.orb.CORBA.OutputStream(buf, client
-                .codeConverters(), 258);
-        org.omg.IOP.ServiceContext[] scl = client.getAMIRouterSCL();
+        out.value = new org.apache.yoko.orb.CORBA.OutputStream(buf, client.codeConverters(), GIOP1_2);
+        ServiceContext[] scl = client.getAMIRouterSCL();
 
-        GIOPOutgoingMessage outgoing = new GIOPOutgoingMessage(orbInstance_,
-                out.value, info.value);
+        GIOPOutgoingMessage outgoing = new GIOPOutgoingMessage(orbInstance_, out.value, info.value);
 
         //
         // Put the request header into the stream
         //
-        outgoing.writeRequestHeader(client.requestId(), operation,
-                responseExpected, scl);
+        outgoing.writeRequestHeader(client.getNewRequestID(), operation, responseExpected, scl);
 
         return outgoing;
     }
 
-    public void AMIRouterPostMarshal(GIOPOutgoingMessage outgoing,
-            org.apache.yoko.orb.CORBA.OutputStreamHolder out) {
+    public void AMIRouterPostMarshal(GIOPOutgoingMessage outgoing, org.apache.yoko.orb.CORBA.OutputStreamHolder out) {
         int pos = out.value._OB_pos();
         out.value._OB_pos(0);
-        outgoing.writeMessageHeader(org.omg.GIOP.MsgType_1_1.Request, false,
-                pos - 12);
+        outgoing.writeMessageHeader(MsgType_1_1.Request, false, pos - 12);
         out.value._OB_pos(pos);
 
         //
@@ -594,8 +589,8 @@
     public org.apache.yoko.orb.CORBA.InputStream invoke(
             org.omg.CORBA.Object self,
             org.apache.yoko.orb.CORBA.OutputStream out)
-            throws org.omg.CORBA.portable.ApplicationException,
-            org.omg.CORBA.portable.RemarshalException, LocationForward,
+            throws ApplicationException,
+            RemarshalException, LocationForward,
             FailureException {
         //
         // We should have an InvocationContext associated with the
@@ -609,7 +604,7 @@
         // If the DowncallStub has changed, then remarshal
         //
         if (ctx.downcallStub != this) {
-            throw new org.omg.CORBA.portable.RemarshalException();
+            throw new RemarshalException();
         }
 
         Downcall down = ctx.downcall;
@@ -640,7 +635,7 @@
                         // Extract the exception's repository ID
                         //
                         id = down.unmarshalExceptionId();
-                    } catch (org.omg.CORBA.SystemException ex) {
+                    } catch (SystemException ex) {
                         down.unmarshalEx(ex);
                     }
 
@@ -652,8 +647,7 @@
                     down.setUserException(id);
                     down.postUnmarshal();
 
-                    throw new org.omg.CORBA.portable.ApplicationException(id,
-                            in);
+                    throw new ApplicationException(id, in);
                 } else {
                     //
                     // We're using portable stubs, so we'll never
@@ -676,7 +670,7 @@
         //
         // If we reach this point, then we need to reinvoke
         //
-        throw new org.omg.CORBA.portable.RemarshalException();
+        throw new RemarshalException();
     }
 
     public org.omg.CORBA.Object getAMIPollTarget() {
@@ -685,15 +679,11 @@
         // generated stub, we will call this method to create the target
         // object for a polling request
         //
-        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_
-                .getObjectFactory();
+        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_.getObjectFactory();
         return objectFactory.createObject(IOR_);
     }
 
-    public org.omg.MessageRouting.PersistentRequest ami_poll_request(
-            org.omg.CORBA.portable.OutputStream out, String operation,
-            org.omg.IOP.ServiceContext[] scl)
-            throws org.omg.CORBA.portable.RemarshalException {
+    public PersistentRequest ami_poll_request(OutputStream out, String operation, ServiceContext[] scl) throws RemarshalException {
         //
         // setup the ORBInstance
         //
@@ -701,8 +691,7 @@
         Assert._OB_assert(out != null);
 
         //
-        // We should have an InvocationContext associated with the
-        // OutputStream
+        // We should have an InvocationContext associated with the OutputStream
         //
         org.apache.yoko.orb.CORBA.OutputStream o = (org.apache.yoko.orb.CORBA.OutputStream) out;
         InvocationContext ctx = (InvocationContext) o._OB_invocationContext();
@@ -712,19 +701,18 @@
         // If the DowncallStub has changed, then remarshal
         //
         if (ctx.downcallStub != this)
-            throw new org.omg.CORBA.portable.RemarshalException();
+            throw new RemarshalException();
 
         //
         // Obtain the ORB
         //
-        org.omg.CORBA.ORB orb = orbInstance_.getORB();
+        ORB orb = orbInstance_.getORB();
         Assert._OB_assert(orb != null);
 
         //
         // Obtain the PersistentRequestRouter
         //
-        org.omg.MessageRouting.PersistentRequestRouter router = org.apache.yoko.orb.OB.MessageRoutingUtil
-                .getPersistentRouterFromConfig(orbInstance_);
+        PersistentRequestRouter router = org.apache.yoko.orb.OB.MessageRoutingUtil.getPersistentRouterFromConfig(orbInstance_);
         org.apache.yoko.orb.OB.Assert._OB_assert(router != null);
 
         //
@@ -732,11 +720,10 @@
         //
         org.apache.yoko.orb.OCI.ProfileInfoHolder info = new org.apache.yoko.orb.OCI.ProfileInfoHolder();
         info.value = null;
-        Client client = null;
         try {
-            client = getClientProfilePair(info);
+            getClientProfilePair(info);
         } catch (org.apache.yoko.orb.OB.FailureException ex) {
-            throw new org.omg.CORBA.portable.RemarshalException();
+            throw new RemarshalException();
         }
 
         //
@@ -747,23 +734,21 @@
         //
         // Create the router to_visit list
         //
-        org.omg.MessageRouting.RouterListHolder to_visit = new org.omg.MessageRouting.RouterListHolder();
-        to_visit.value = new org.omg.MessageRouting.Router[0];
-        org.apache.yoko.orb.OB.MessageRoutingUtil.getRouterListFromComponents(
-                orbInstance_, info.value, to_visit);
+        RouterListHolder to_visit = new RouterListHolder();
+        to_visit.value = new Router[0];
+        org.apache.yoko.orb.OB.MessageRoutingUtil.getRouterListFromComponents(orbInstance_, info.value, to_visit);
 
         //
         // Obtain the target objects
         //
-        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_
-                .getObjectFactory();
+        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_.getObjectFactory();
         org.omg.CORBA.Object target = objectFactory.createObject(IOR_);
 
         //
         // Populate the RequestMessage payload
         //
-        org.omg.MessageRouting.RequestMessage payload = new org.omg.MessageRouting.RequestMessage();
-        // payload.service_contexts = new org.omg.IOP.ServiceContext[0];
+        RequestMessage payload = new RequestMessage();
+        // payload.service_contexts = new ServiceContext[0];
         //
         // XXX
         //
@@ -778,29 +763,25 @@
         payload.reserved[2] = 0;
         payload.operation = operation;
         payload.object_key = new byte[info.value.key.length];
-        System.arraycopy(info.value.key, 0, payload.object_key, 0,
-                info.value.key.length);
+        System.arraycopy(info.value.key, 0, payload.object_key, 0, info.value.key.length);
 
         o._OB_pos(0);
         org.apache.yoko.orb.OCI.Buffer buf = o._OB_buffer();
-        org.omg.MessageRouting.MessageBody messageBody = new org.omg.MessageRouting.MessageBody();
+        MessageBody messageBody = new MessageBody();
         messageBody.byte_order = false; // Java is always false
         messageBody.body = new byte[buf.rest_length()];
-        System.arraycopy(buf.data(), buf.pos(), messageBody.body, 0, buf
-                .rest_length());
+        System.arraycopy(buf.data(), buf.pos(), messageBody.body, 0, buf.rest_length());
         payload.body = messageBody;
 
         //
         // Empty QoS list
         //
-        org.omg.CORBA.Policy[] qosList = new org.omg.CORBA.Policy[0];
+        Policy[] qosList = new Policy[0];
 
         //
         // Create a new Persistent request
         //
-        org.omg.MessageRouting.PersistentRequest request = router
-                .create_persistent_request(index, to_visit.value, target,
-                        qosList, payload);
+        PersistentRequest request = router.create_persistent_request(index, to_visit.value, target, qosList, payload);
 
         //
         // Return the persistent request back to the stub
@@ -808,11 +789,7 @@
         return request;
     }
 
-    public boolean ami_callback_request(
-            org.omg.CORBA.portable.OutputStream out,
-            org.omg.Messaging.ReplyHandler reply,
-            org.apache.yoko.orb.OCI.ProfileInfo info)
-            throws org.omg.CORBA.portable.RemarshalException {
+    public boolean ami_callback_request(OutputStream out, ReplyHandler reply, org.apache.yoko.orb.OCI.ProfileInfo info) throws RemarshalException {
         //
         // We should have an InvocationContext associated with the
         // OutputStream
@@ -825,16 +802,14 @@
         // If the DowncallStub has changed, then remarshal
         //
         if (ctx.downcallStub != this)
-            throw new org.omg.CORBA.portable.RemarshalException();
+            throw new RemarshalException();
 
-        org.apache.yoko.orb.CORBA.InputStream tmpIn = (org.apache.yoko.orb.CORBA.InputStream) out
-                .create_input_stream();
+        org.apache.yoko.orb.CORBA.InputStream tmpIn = (org.apache.yoko.orb.CORBA.InputStream) out.create_input_stream();
 
         //
         // Unmarshal the message header
         //
-        org.omg.GIOP.MessageHeader_1_1 msgHeader = org.omg.GIOP.MessageHeader_1_2Helper
-                .read(tmpIn);
+        MessageHeader_1_1 msgHeader = MessageHeader_1_2Helper.read(tmpIn);
 
         //
         // Check the GIOP version
@@ -849,7 +824,7 @@
         //
         // Check the message type
         //
-        if (msgHeader.message_type != (byte) org.omg.GIOP.MsgType_1_1._Request) {
+        if (msgHeader.message_type != (byte) MsgType_1_1._Request) {
             //
             // Report error - throw exception
             //
@@ -859,35 +834,32 @@
         //
         // Create and populate a RequestInfo to send to the router
         //
-        org.omg.MessageRouting.RequestInfo requestInfo = new org.omg.MessageRouting.RequestInfo();
+        RequestInfo requestInfo = new RequestInfo();
 
         //
         // Unmarshal the request header
         // 
-        org.omg.GIOP.RequestHeader_1_2 requestHeader = org.omg.GIOP.RequestHeader_1_2Helper
-                .read(tmpIn);
+        RequestHeader_1_2 requestHeader = RequestHeader_1_2Helper.read(tmpIn);
 
         //
         // Create and populate a RequestInfo structure to send to the
         // Router
         //
-        org.omg.MessageRouting.RouterListHolder configRouterList = new org.omg.MessageRouting.RouterListHolder();
-        configRouterList.value = new org.omg.MessageRouting.Router[0];
+        RouterListHolder configRouterList = new RouterListHolder();
+        configRouterList.value = new Router[0];
 
         //
         // Populate the configRouterList
         //
-        org.apache.yoko.orb.OB.MessageRoutingUtil.getRouterListFromComponents(
-                orbInstance_, info, configRouterList);
+        org.apache.yoko.orb.OB.MessageRoutingUtil.getRouterListFromComponents(orbInstance_, info, configRouterList);
 
-        requestInfo.visited = new org.omg.MessageRouting.Router[0];
-        requestInfo.to_visit = new org.omg.MessageRouting.Router[0];
+        requestInfo.visited = new Router[0];
+        requestInfo.to_visit = new Router[0];
 
         //
         // Get the target for this request
         //
-        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_
-                .getObjectFactory();
+        org.apache.yoko.orb.OB.ObjectFactory objectFactory = orbInstance_.getObjectFactory();
         //
         // REVISIT: Should we be using IOR_ or origIOR_?
         //
@@ -901,24 +873,23 @@
         //
         // Get the reply destination for this request
         //
-        org.omg.MessageRouting.ReplyDestination replyDest = new org.omg.MessageRouting.ReplyDestination();
-        replyDest.handler_type = org.omg.MessageRouting.ReplyDisposition.TYPED;
+        ReplyDestination replyDest = new ReplyDestination();
+        replyDest.handler_type = ReplyDisposition.TYPED;
         replyDest.handler = reply;
         requestInfo.reply_destination = replyDest;
 
         //
         // Get the selected qos for this request
         //
-        org.omg.Messaging.PolicyValueSeqHolder invocPoliciesHolder = new org.omg.Messaging.PolicyValueSeqHolder();
-        invocPoliciesHolder.value = new org.omg.Messaging.PolicyValue[0];
-        org.apache.yoko.orb.OB.MessageRoutingUtil.getInvocationPolicyValues(
-                policies_, invocPoliciesHolder);
+        PolicyValueSeqHolder invocPoliciesHolder = new PolicyValueSeqHolder();
+        invocPoliciesHolder.value = new PolicyValue[0];
+        org.apache.yoko.orb.OB.MessageRoutingUtil.getInvocationPolicyValues(policies_, invocPoliciesHolder);
         requestInfo.selected_qos = invocPoliciesHolder.value;
 
         //
         // Create payload (RequestMessage) for this request
         //
-        org.omg.MessageRouting.RequestMessage requestMessage = new org.omg.MessageRouting.RequestMessage();
+        RequestMessage requestMessage = new RequestMessage();
         requestMessage.giop_version = new org.omg.GIOP.Version();
         requestMessage.giop_version.major = info.major;
         requestMessage.giop_version.minor = info.minor;
@@ -932,8 +903,8 @@
         // Add the invocation policies service context for this request.
         // Note that this can change from request to request
         //
-        org.omg.IOP.ServiceContext invocPoliciesSC = new org.omg.IOP.ServiceContext();
-        invocPoliciesSC.context_id = org.omg.IOP.INVOCATION_POLICIES.value;
+        ServiceContext invocPoliciesSC = new ServiceContext();
+        invocPoliciesSC.context_id = INVOCATION_POLICIES.value;
 
         //
         // Create an output stream an write the PolicyValueSeq
@@ -943,20 +914,17 @@
             org.apache.yoko.orb.CORBA.OutputStream scOut = new org.apache.yoko.orb.CORBA.OutputStream(
                     scBuf);
             scOut._OB_writeEndian();
-            org.omg.Messaging.PolicyValueSeqHelper.write(scOut,
-                    invocPoliciesHolder.value);
+            PolicyValueSeqHelper.write(scOut, invocPoliciesHolder.value);
             invocPoliciesSC.context_data = new byte[scOut._OB_pos()];
-            System.arraycopy(invocPoliciesSC.context_data, 0, scBuf.data(), 0,
-                    scBuf.length());
+            System.arraycopy(invocPoliciesSC.context_data, 0, scBuf.data(), 0, scBuf.length());
         }
 
         //
         // Add the service context to the list of current service contexts
         //
         int scLength = requestMessage.service_contexts.length;
-        org.omg.IOP.ServiceContext[] scList = new org.omg.IOP.ServiceContext[scLength + 1];
-        System.arraycopy(requestMessage.service_contexts, 0, scList, 0,
-                scLength);
+        ServiceContext[] scList = new ServiceContext[scLength + 1];
+        System.arraycopy(requestMessage.service_contexts, 0, scList, 0, scLength);
         scList[scLength] = invocPoliciesSC;
 
         //
@@ -987,7 +955,7 @@
         //
         // Get the body of the request message
         //
-        org.omg.MessageRouting.MessageBody messageBody = new org.omg.MessageRouting.MessageBody();
+        MessageBody messageBody = new MessageBody();
 
         //
         // Java is always big endian
@@ -1022,7 +990,7 @@
         int numRouters = configRouterList.value.length;
 
         for (int i = numRouters - 1; (delivered == false) && (i >= 0); --i) {
-            org.omg.MessageRouting.Router curRouter = configRouterList.value[i];
+            Router curRouter = configRouterList.value[i];
 
             //
             // We only add the routers that we have attempted to contact to
@@ -1030,7 +998,7 @@
             // the request, then the lower priority routers are not added
             //
             int curLength = requestInfo.to_visit.length;
-            org.omg.MessageRouting.Router[] toVisit = new org.omg.MessageRouting.Router[curLength + 1];
+            Router[] toVisit = new Router[curLength + 1];
             if (curLength > 0) {
                 System.arraycopy(requestInfo.to_visit, 0, toVisit, 1, curLength);
             }
@@ -1044,7 +1012,7 @@
                 // Success: stop processing
                 //
                 delivered = true;
-            } catch (org.omg.CORBA.SystemException ex) {
+            } catch (SystemException ex) {
                 logger.log(Level.FINE, "Failed to contact router: " + ex.getMessage(), ex); 
                 //
                 // Failure: try the next router in the list
@@ -1058,10 +1026,6 @@
         return delivered;
     }
 
-    public void _OB_closeConnection(boolean terminate) {
-        destroy(terminate);
-    }
-
     //
     // Need to be able to access the ORB instance from a stub for AMI
     // polling
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPClient.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPClient.java
index 82190d3..25c3e60 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPClient.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPClient.java
@@ -17,106 +17,71 @@
 
 package org.apache.yoko.orb.OB;
 
+import org.apache.yoko.orb.CORBA.OutputStream;
+import org.apache.yoko.orb.CORBA.OutputStreamHolder;
+import org.apache.yoko.orb.OBPortableServer.POAManager_impl;
+import org.apache.yoko.orb.OCI.Buffer;
+import org.apache.yoko.orb.OCI.Connector;
+import org.apache.yoko.orb.OCI.ConnectorInfo;
+import org.apache.yoko.orb.OCI.GiopVersion;
+import org.apache.yoko.orb.OCI.ProfileInfo;
+import org.apache.yoko.orb.OCI.Transport;
+import org.apache.yoko.util.Cache;
+import org.apache.yoko.util.Factory;
+import org.apache.yoko.util.Reference;
+import org.omg.CONV_FRAME.CodeSetContext;
+import org.omg.CONV_FRAME.CodeSetContextHelper;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.INITIALIZE;
+import org.omg.CORBA.NO_RESPONSE;
+import org.omg.CORBA.Policy;
+import org.omg.IOP.CodeSets;
+import org.omg.IOP.IOR;
+import org.omg.IOP.ServiceContext;
+import org.omg.PortableServer.POAManager;
+import org.omg.SendingContext.CodeBase;
+import org.omg.SendingContext.CodeBaseHelper;
+
+import javax.rmi.CORBA.ValueHandler;
+import java.util.ArrayList;
+import java.util.List;
+
+import static javax.rmi.CORBA.Util.*;
+import static org.apache.yoko.orb.OB.MinorCodes.*;
+
 final class GIOPClient extends Client {
     protected ORBInstance orbInstance_; // The ORB instance
 
-    protected int nextRequestId_; // The next request ID
+    protected Connector connector_; // The connector
 
-    protected java.lang.Object nextRequestIdMutex_ = new java.lang.Object(); // The
-                                                                                // next
-                                                                                // request
-                                                                                // ID
-                                                                                // mutex
+    private GIOPConnection connection_;
+    private Reference<GIOPConnection> connectionRef;
 
-    protected org.apache.yoko.orb.OCI.Connector connector_; // The connector
+    /** Codesets SC */
+    protected ServiceContext codeSetSC_;
 
-    protected GIOPConnection connection_;
-
-    //
-    // Codesets SC
-    // 
-    protected org.omg.IOP.ServiceContext codeSetSC_;
-
-    protected org.omg.IOP.ServiceContext codeBaseSC_;
+    protected ServiceContext codeBaseSC_;
 
     protected boolean bidirWorker_; // is the worker bidir?
 
-    protected boolean ownsWorker_; // does 'this' own the worker?
-
-    protected boolean destroy_; // True if destroy() was called
+    protected volatile boolean destroy_; // True if destroy() was called
 
     // ----------------------------------------------------------------------
     // GIOPClient private and protected member implementations
     // ----------------------------------------------------------------------
 
-    protected void finalize() throws Throwable {
-        Assert._OB_assert(destroy_);
-        Assert._OB_assert(connection_ == null);
-
-        super.finalize();
-    }
-
-    // 
     // uses the prepopulated connector_ (not connected) to do a lookup,
     // checking if a bidir connection alias exists... it returns it if
     // it does and returns null otherwise
-    //
     protected GIOPConnection find_bidir_worker() {
         try {
-            //
-            // Any transport that we want to query should exist when the
-            // server first receives a request from the client-side. This
-            // transport will have the ListenPointList populated inside of
-            // its TransportInfo. So we query the list of
-            // GIOPServerStarters for the correct transport and hopefully
-            // find a match if we want to use bidir
-            //
-            org.apache.yoko.orb.OBPortableServer.POAManagerFactory pmFactoryImpl = orbInstance_
-                    .getPOAManagerFactory();
-
-            //
-            // Obtain a list of POAs for this POAManager
-            // 
-            org.omg.PortableServer.POAManager[] pmSeq = pmFactoryImpl.list();
-
-            for (int i = 0; i < pmSeq.length; i++) {
-                org.apache.yoko.orb.OBPortableServer.POAManager_impl poaImpl = (org.apache.yoko.orb.OBPortableServer.POAManager_impl) pmSeq[i];
-
-                // 
-                // Get the server manager from the POA
-                // 
-                org.apache.yoko.orb.OB.ServerManager sm = poaImpl
-                        ._OB_getServerManager();
-
-                //
-                // get the list of servers from the server manager
-                //
-                org.apache.yoko.orb.OB.Server[] servSeq = sm.getServers();
-
-                // 
-                // iterate these servers obtaining the GIOPServerStarter
-                //
-                for (int j = 0; j < servSeq.length; j++) {
-                    org.apache.yoko.orb.OB.GIOPServer giopServer = (org.apache.yoko.orb.OB.GIOPServer) servSeq[j];
-
-                    org.apache.yoko.orb.OB.GIOPServerStarter servStarter = giopServer
-                            ._OB_getGIOPServerStarter();
-
-                    //
-                    // get the matching worker from the GIOPServerStarter
-                    //
-                    GIOPConnection gw = servStarter.getWorker(connectorInfo());
-
-                    if (gw != null)
-                        return gw;
+            for (POAManager poaManager : orbInstance_.getPOAManagerFactory().list()) {
+                for (Server aServSeq : ((POAManager_impl) poaManager)._OB_getServerManager().getServers()) {
+                    GIOPConnection conn = ((GIOPServer) aServSeq)._OB_getGIOPServerStarter().getMatchingConnection(connectorInfo());
+                    if (conn != null) return conn;
                 }
             }
-        } catch (ClassCastException ex) {
-        }
-
-        //
-        // nothing was found to return
-        // 
+        } catch (ClassCastException ignored) {}
         return null;
     }
 
@@ -125,108 +90,20 @@
     // a new worker is created, with the timeout specified as second
     // parameter.
     //
-    protected synchronized GIOPConnection getWorker(boolean create, int t) {
+    protected synchronized GIOPConnection getWorker(boolean create, final int timeout) {
         if (destroy_)
-            throw new org.omg.CORBA.INITIALIZE(org.apache.yoko.orb.OB.MinorCodes
-                    .describeInitialize(org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            throw new INITIALIZE(describeInitialize(MinorORBDestroyed), MinorORBDestroyed, CompletionStatus.COMPLETED_NO);
 
-        // 
-        // first attempt to locate a reusable bidir connection
+        if (connection_ == null)
+            reuseInboundConnection();
+
+
         //
-        if (connection_ == null) {
-            connection_ = find_bidir_worker();
-
-            if (connection_ != null) {
-                //
-                // adjust the requestID to match the spec (even for
-                // clients, odd for servers)
-                // 
-                if ((nextRequestId_ & 1) == 0)
-                    nextRequestId_++;
-                ownsWorker_ = false;
-                connection_.activateClientSide(this);
-
-                // 
-                // log the reusing of the connection
-                //
-                CoreTraceLevels coreTraceLevels = orbInstance_
-                        .getCoreTraceLevels();
-                if (coreTraceLevels.traceConnections() > 0) {
-                    org.apache.yoko.orb.OCI.TransportInfo info = connection_
-                            .transport().get_info();
-                    String msg = "reusing established bidir connection\n";
-                    msg += info.describe();
-                    orbInstance_.getLogger().trace("outgoing", msg);
-                }
-            }
-        }
-
-        // 
-        // no bidir connection resolved so create one if the request
-        // calls for it
-        // 
-        if (connection_ == null && create) {
-            //
-            // Trace connection attempt
-            //
-            CoreTraceLevels coreTraceLevels = orbInstance_.getCoreTraceLevels();
-            if (coreTraceLevels.traceConnections() > 0) {
-                org.apache.yoko.orb.OCI.ConnectorInfo info = connector_
-                        .get_info();
-                String msg = "trying to establish connection\n";
-                msg += "timeout: ";
-                if (t >= 0) {
-                    msg += t;
-                    msg += "ms\n";
-                } else
-                    msg += "none\n";
-                msg += info.describe();
-                orbInstance_.getLogger().trace("outgoing", msg);
-            }
-
-            //
-            // Create new transport, using the connector
-            //
-            // For symetry reasons, GIOPClientStarterThreaded should also be
-            // added, even though these classes only have a trivial
-            // functionality. Or perhaps the GIOPClientStarterThreaded tries to
-            // connect() in the backgound? Just an idea...
-            //
-
-            org.apache.yoko.orb.OCI.Transport transport;
-
-            if (t >= 0) {
-                transport = connector_.connect_timeout(t);
-
-                //
-                // Was there a timeout?
-                //
-                if (transport == null)
-                    throw new org.omg.CORBA.NO_RESPONSE("Connection timeout",
-                            0, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-            } else {
-                transport = connector_.connect();
-                Assert._OB_assert(transport != null);
-            }
-
-            //
-            // Create new worker
-            //
-            Assert._OB_assert(concModel_ == Threaded);
-            connection_ = new GIOPConnectionThreaded(orbInstance_, transport,
-                    this);
-            ownsWorker_ = true;
-
-            //
-            // bidirWorker_ means that this connection may be used to
-            // service requests so we need to set ourselves up as a
-            // server (to correct map the OAInterfaces)
-            //
-            if (bidirWorker_)
-                connection_.activateServerSide();
-        }
+        // no inbound bidir connection resolved so lookup an existing outbound connection
+        // or create one if the request calls for it
+        //
+        if (connection_ == null)
+            reuseOrCreateOutboundConnection(create, timeout);
 
         //
         // Lazy initialization of codeSetSC_. We don't want to
@@ -239,14 +116,101 @@
         return connection_;
     }
 
-    //
+    private synchronized void reuseOrCreateOutboundConnection(boolean create, final int timeout) {
+        Cache<ConnectorInfo, GIOPConnection> connCache = orbInstance_.getOutboundConnectionCache();
+        if (create) {
+            connectionRef = connCache.getOrCreate(connector_.get_info(), new Factory<GIOPConnection>() {
+                @Override
+                public GIOPConnection create() {
+                    return createOutboundConnection(timeout);
+                }
+            });
+        } else {
+            connectionRef = connCache.get(connector_.get_info());
+        }
+        connCache.clean();
+        connection_ = connectionRef.get();
+
+        //
+        // bidirWorker_ means that this connection may be used to
+        // service requests so we need to set ourselves up as a
+        // server (to correct map the OAInterfaces)
+        //
+        if (bidirWorker_)
+            connection_.activateServerSide();
+    }
+
+    private synchronized void reuseInboundConnection() {
+        //
+        // first attempt to locate a reusable bidir connection
+        //
+        connection_ = find_bidir_worker();
+
+        if (connection_ == null) return;
+
+        connection_.activateClientSide();
+
+        //
+        // log the reusing of the connection
+        //
+        if (orbInstance_.getCoreTraceLevels().traceConnections() > 0) {
+            String msg = "reusing established bidir connection\n" + connection_.transport().get_info().describe();
+            orbInstance_.getLogger().trace("outgoing", msg);
+        }
+    }
+
+    private GIOPConnectionThreaded createOutboundConnection(int t) {
+        //
+        // Trace connection attempt
+        //
+        CoreTraceLevels coreTraceLevels = orbInstance_.getCoreTraceLevels();
+        if (coreTraceLevels.traceConnections() > 0) {
+            String msg = "trying to establish connection\n";
+            msg += "timeout: ";
+            if (t >= 0) {
+                msg += t;
+                msg += "ms\n";
+            } else
+                msg += "none\n";
+            msg += connector_.get_info().describe();
+            orbInstance_.getLogger().trace("outgoing", msg);
+        }
+
+        //
+        // Create new transport, using the connector
+        //
+        // For symetry reasons, GIOPClientStarterThreaded should also be
+        // added, even though these classes only have a trivial
+        // functionality. Or perhaps the GIOPClientStarterThreaded tries to
+        // connect() in the backgound? Just an idea...
+        //
+
+        Transport transport;
+
+        if (t >= 0) {
+            transport = connector_.connect_timeout(t);
+
+            //
+            // Was there a timeout?
+            //
+            if (transport == null)
+                throw new NO_RESPONSE("Connection timeout", 0, CompletionStatus.COMPLETED_NO);
+        } else {
+            transport = connector_.connect();
+            Assert._OB_assert(transport != null);
+        }
+
+        //
+        // Create new worker
+        //
+        Assert._OB_assert(concModel_ == Threaded);
+        return new GIOPConnectionThreaded(orbInstance_, transport, this);
+    }
+
     // initialize internal service contexts
     private void initServiceContexts() {
         if (codeSetSC_ == null) {
-            //
-            // Create CONV_FRAME::CodeSetContext
-            //
-            org.omg.CONV_FRAME.CodeSetContext ctx = new org.omg.CONV_FRAME.CodeSetContext();
+            CodeSetContext ctx = new CodeSetContext();
             CodeConverters conv = codeConverters();
 
             if (conv.outputCharConverter != null)
@@ -259,21 +223,16 @@
             else
                 ctx.wchar_data = orbInstance_.getNativeWcs();
 
-            //
             // Create encapsulation for CONV_FRAME::CodeSetContext
-            //
-            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
-            org.apache.yoko.orb.CORBA.OutputStream outCSC = new org.apache.yoko.orb.CORBA.OutputStream(
-                    buf);
+            Buffer buf = new Buffer();
+            OutputStream outCSC = new OutputStream(buf);
             outCSC._OB_writeEndian();
-            org.omg.CONV_FRAME.CodeSetContextHelper.write(outCSC, ctx);
+            CodeSetContextHelper.write(outCSC, ctx);
 
-            //
             // Create service context containing the
             // CONV_FRAME::CodeSetContext encapsulation
-            //
-            codeSetSC_ = new org.omg.IOP.ServiceContext();
-            codeSetSC_.context_id = org.omg.IOP.CodeSets.value;
+            codeSetSC_ = new ServiceContext();
+            codeSetSC_.context_id = CodeSets.value;
 
             int len = buf.length();
             byte[] data = buf.data();
@@ -282,17 +241,16 @@
         }
         if (codeBaseSC_ == null) {
 
-            javax.rmi.CORBA.ValueHandler valueHandler = javax.rmi.CORBA.Util.createValueHandler();
-            org.omg.SendingContext.CodeBase codeBase = (org.omg.SendingContext.CodeBase) valueHandler.getRunTimeCodeBase();
+            ValueHandler valueHandler = createValueHandler();
+            CodeBase codeBase = CodeBaseHelper.narrow(valueHandler.getRunTimeCodeBase());
 
 
-            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
-            org.apache.yoko.orb.CORBA.OutputStream outCBC = new org.apache.yoko.orb.CORBA.OutputStream(
-                    buf);
+            Buffer buf = new Buffer();
+            OutputStream outCBC = new OutputStream(buf);
             outCBC._OB_writeEndian();
-            org.omg.SendingContext.CodeBaseHelper.write(outCBC, codeBase);
+            CodeBaseHelper.write(outCBC, codeBase);
 
-            codeBaseSC_ = new org.omg.IOP.ServiceContext();
+            codeBaseSC_ = new ServiceContext();
             codeBaseSC_.context_id = org.omg.IOP.SendingContextRunTime.value;
 
             int len = buf.length();
@@ -313,86 +271,45 @@
     // ----------------------------------------------------------------------
 
     GIOPClient(ORBInstance orbInstance,
-            org.apache.yoko.orb.OCI.Connector connector, int concModel,
-            CodeConverters conv, boolean bidirEnable) {
+               Connector connector, int concModel,
+               CodeConverters conv, boolean bidirEnable) {
         super(concModel, conv);
         orbInstance_ = orbInstance;
-        nextRequestId_ = 0;
         connector_ = connector;
         connection_ = null;
         destroy_ = false;
         bidirWorker_ = bidirEnable;
-        ownsWorker_ = true;
     }
 
     // ----------------------------------------------------------------------
     // GIOPClient public member implementations
     // ----------------------------------------------------------------------
 
-    //
-    // Destroy the client
-    //
-    public void destroy(boolean terminate) {
-        GIOPConnection c = null;
-
-        synchronized (this) {
-            //
-            // Don't destroy twice
-            //
-            if (destroy_)
-                return;
-
-            //
-            // Set the destroy flag
-            //
-            destroy_ = true;
-
-            //
-            // Use a copy of the worker, and destroy the worker outside
-            // the synchronization, to avoid deadlocks
-            //
-            c = connection_;
-            connection_ = null;
-        }
-
-        //
-        // If there is a worker (and we exclusively own it) destroy it
-        //
-        if (c != null && ownsWorker_)
-            c.destroy(terminate);
+    /** Destroy the client */
+    public synchronized void destroy() {
+        if (destroy_) return;
+        destroy_ = true;
+        connection_ = null;
+        // release the reference if this is an outbound connection
+        if (connectionRef != null) connectionRef.close();
     }
 
-    public synchronized void removeConnection(GIOPConnection connection) {
-        if (connection_ == connection)
-            connection_ = null;
-    }
-
-    //
-    // Get a new request ID
-    //
-    public int requestId() {
-        synchronized (nextRequestIdMutex_) {
-            //
-            // In the case of BiDir connections, the client should use
-            // even numbered requestIds and the server should use odd
-            // numbered requestIds... the += 2 keeps this pattern intact
-            // assuming its correct at startup
-            // 
-            return nextRequestId_ += 2;
-        }
+    /** Get a new request ID */
+    public int getNewRequestID() {
+        return connection_.getNewRequestId();
     }
 
     //
     // get a list of ServiceContexts that have to be sent on an AMI router
     // request
     //
-    public org.omg.IOP.ServiceContext[] getAMIRouterSCL() {
+    public ServiceContext[] getAMIRouterSCL() {
         //
         // initialize the service contexts if they haven't already been
         //
         initServiceContexts();
 
-        org.omg.IOP.ServiceContext[] scl = new org.omg.IOP.ServiceContext[1];
+        ServiceContext[] scl = new ServiceContext[1];
         scl[0] = codeSetSC_;
 
         //
@@ -401,44 +318,24 @@
         return scl;
     }
 
-    //
-    // Get all profiles that are usable with this client
-    //
-    public org.apache.yoko.orb.OCI.ProfileInfo[] getUsableProfiles(
-            org.omg.IOP.IOR ior, org.omg.CORBA.Policy[] policies) {
-        //
+    /** Get all profiles that are usable with this client */
+    public ProfileInfo[] getUsableProfiles(IOR ior, Policy[] policies) {
         // Get all profiles usable for the connector
-        //
-        org.apache.yoko.orb.OCI.ProfileInfo[] all = connector_
-                .get_usable_profiles(ior, policies);
-
-        //
-        // Filter out profiles which would require a different code converter
-        //
-        java.util.Vector vec = new java.util.Vector();
-        for (int i = 0; i < all.length; i++) {
-            CodeConverters conv = CodeSetUtil.getCodeConverters(orbInstance_,
-                    all[i]);
-            if (codeConverters().equals(conv))
-                vec.addElement(all[i]);
+        List<ProfileInfo> profileInfos = new ArrayList<>();
+        for (ProfileInfo anAll : connector_.get_usable_profiles(ior, policies)) {
+            CodeConverters conv = CodeSetUtil.getCodeConverters(orbInstance_, anAll);
+            // Filter out profiles which would require a different code converter
+            if (codeConverters().equals(conv)) profileInfos.add(anAll);
         }
-
-        org.apache.yoko.orb.OCI.ProfileInfo[] result = new org.apache.yoko.orb.OCI.ProfileInfo[vec
-                .size()];
-        vec.copyInto(result);
-        return result;
+        return profileInfos.toArray(new ProfileInfo[profileInfos.size()]);
     }
 
-    //
-    // Get the OCI Connector info
-    //
+    /** Get the OCI Connector info */
     public org.apache.yoko.orb.OCI.ConnectorInfo connectorInfo() {
         return connector_.get_info();
     }
 
-    //
-    // Get the OCI Transport info
-    //
+    /** Get the OCI Transport info */
     public org.apache.yoko.orb.OCI.TransportInfo transportInfo() {
         //
         // Get the connection, but do not create a new one if there is none
@@ -449,7 +346,7 @@
         if (connection == null)
             return null;
 
-        org.apache.yoko.orb.OCI.Transport transport = connection.transport();
+        Transport transport = connection.transport();
         return transport.get_info();
     }
 
@@ -457,9 +354,8 @@
     // Start a downcall, returning a downcall emitter and an
     // OutputStream for marshalling a request
     //
-    public DowncallEmitter startDowncall(Downcall down,
-            org.apache.yoko.orb.CORBA.OutputStreamHolder out) {
-        GIOPConnection connection = null;
+    public DowncallEmitter startDowncall(Downcall down, OutputStreamHolder out) {
+        GIOPConnection connection;
         try {
             //
             // Get the worker, creating a new one if there is none
@@ -468,7 +364,7 @@
             connection = getWorker(true, down.policies().connectTimeout);
         } catch (org.omg.CORBA.SystemException ex) {
             Assert
-                    ._OB_assert(ex.completed == org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    ._OB_assert(ex.completed == CompletionStatus.COMPLETED_NO);
             down.setFailureException(ex);
             return null;
         }
@@ -488,12 +384,11 @@
                     CodeConverters conv = codeConverters();
                     String msg = "sending transmission code sets";
                     msg += "\nchar code set: ";
-                    if (conv.outputCharConverter != null)
+                    if (conv.outputCharConverter != null) {
                         msg += conv.outputCharConverter.getTo().description;
-                    else {
-                        CodeSetInfo info = CodeSetDatabase.instance()
-                                .getCodeSetInfo(orbInstance_.getNativeCs());
-                        msg += info.description;
+                    } else {
+                        CodeSetInfo info = CodeSetDatabase.instance().getCodeSetInfo(orbInstance_.getNativeCs());
+                        msg += info != null ? info.description : null;
                     }
                     msg += "\nwchar code set: ";
                     if (conv.outputWcharConverter != null)
@@ -501,7 +396,7 @@
                     else {
                         CodeSetInfo info = CodeSetDatabase.instance()
                                 .getCodeSetInfo(orbInstance_.getNativeWcs());
-                        msg += info.description;
+                        msg += info != null ? info.description : null;
                     }
                     orbInstance_.getLogger().trace("outgoing", msg);
                 }
@@ -524,22 +419,20 @@
 
             if (validGIOPVersion
                     && (down.policies().biDirMode == org.omg.BiDirPolicy.BOTH.value)) {
-                org.apache.yoko.orb.OCI.Transport t = connection.transport();
+                Transport t = connection.transport();
 
-                org.omg.IOP.ServiceContext contexts[] = t.get_info()
+                ServiceContext contexts[] = t.get_info()
                         .get_service_contexts(down.policies().value);
-                for (int i = 0; i < contexts.length; i++)
-                    down.addToRequestSCL(contexts[i]);
+                for (ServiceContext context : contexts) down.addToRequestSCL(context);
             }
 
-            org.apache.yoko.orb.OCI.ProfileInfo profileInfo = down
+            ProfileInfo profileInfo = down
                     .profileInfo();
-            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
+            Buffer buf = new Buffer(
                     12);
             buf.pos(12);
-            out.value = new org.apache.yoko.orb.CORBA.OutputStream(buf,
-                    codeConverters(), (profileInfo.major << 8)
-                            | profileInfo.minor);
+            out.value = new OutputStream(buf,
+                    codeConverters(), GiopVersion.get(profileInfo.major, profileInfo.minor));
 
             //
             // Create GIOP outgoing message
@@ -560,35 +453,21 @@
             return connection.emitterInterface();
         } catch (org.omg.CORBA.SystemException ex) {
             Assert
-                    ._OB_assert(ex.completed == org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    ._OB_assert(ex.completed == CompletionStatus.COMPLETED_NO);
             down.setFailureException(ex);
             return null;
         }
     }
 
-    //
-    // Checks whether this client is equal to another client
-    //
-    public boolean equal(Client cl) {
-        GIOPClient client = null;
-        try {
-            client = (GIOPClient) cl;
-        } catch (ClassCastException ex) {
-            return false;
-        }
+    /** Checks whether this client is equal to another client */
+    public boolean matches(Client other) {
+        if (!!!(other instanceof GIOPClient)) return false;
+        GIOPClient that = (GIOPClient) other;
 
-        if (!connector_.equal(client.connector_))
-            return false;
-
-        if (!codeConverters().equals(client.codeConverters()))
-            return false;
-
-        return true;
+        return this.connector_.equal(that.connector_) && this.codeConverters().equals(that.codeConverters());
     }
 
-    //
-    // Force connection establishment
-    //
+    /** Force connection establishment */
     public void bind(int connectTimeout) {
         //
         // Get the connection, creating a new one if there is none
@@ -597,24 +476,19 @@
         getWorker(true, connectTimeout);
     }
 
-    //
-    // Determines whether this client supports twoway invocations
-    //
+    /** Determines whether this client supports twoway invocations */
     public boolean twoway() {
         //
         // Get the connection
         //
         GIOPConnection connection = getWorker(false, -1);
         Assert._OB_assert(connection != null);
-        org.apache.yoko.orb.OCI.Transport transport = connection.transport();
+        Transport transport = connection.transport();
         return transport.mode() == org.apache.yoko.orb.OCI.SendReceiveMode.SendReceive;
     }
 
-    // 
-    // determines whether this GIOPClient exclusively owns its worker or
-    // if its shared with another Client/Server
-    //
-    public boolean sharedConnection() {
-        return !ownsWorker_;
+    @Override
+    public void prepareForDowncall(RefCountPolicyList policies) {
+        getWorker(true, policies.connectTimeout);
     }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java
index cea456e..5c296c7 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnection.java
@@ -18,18 +18,40 @@
 package org.apache.yoko.orb.OB;
 
 import org.apache.yoko.orb.CORBA.InputStream;
-import org.apache.yoko.orb.OB.Logger;
+import org.apache.yoko.orb.OBPortableServer.POAManager_impl;
+import org.apache.yoko.orb.OCI.ConnectorInfo;
+import org.apache.yoko.orb.OCI.GiopVersion;
+import org.apache.yoko.orb.OCI.Transport;
+import org.omg.CONV_FRAME.CodeSetContext;
+import org.omg.CONV_FRAME.CodeSetContextHolder;
+import org.omg.CORBA.COMM_FAILURE;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.NO_IMPLEMENT;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.SystemExceptionHelper;
+import org.omg.CORBA.TRANSIENT;
+import org.omg.CORBA.UNKNOWN;
+import org.omg.GIOP.LocateStatusType_1_2;
+import org.omg.GIOP.ReplyStatusType_1_2;
+import org.omg.IOP.CodeSets;
+import org.omg.IOP.IOR;
+import org.omg.IOP.IORHelper;
+import org.omg.IOP.IORHolder;
 import org.omg.IOP.ServiceContext;
+import org.omg.IOP.UnknownExceptionInfo;
+import org.omg.PortableServer.POAManager;
 import org.omg.SendingContext.CodeBase;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 abstract public class GIOPConnection implements DowncallEmitter, UpcallReturn {
+    static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(GIOPConnection.class.getName());
+
     // ----------------------------------------------------------------
     // Inner classes
     // ----------------------------------------------------------------
 
-    //
-    // access operations class
-    //
+    /* access operations class */
     public static final class AccessOp {
         public static final int Nil = 0;
 
@@ -42,9 +64,7 @@
         public static final int All = 7;
     }
 
-    //
-    // connection properties
-    //
+    /* connection properties */
     public static final class Property {
         public static final int RequestSent = 1;
 
@@ -61,9 +81,7 @@
         public static final int ClosingLogged = 64;
     }
 
-    //
-    // connection states
-    //
+    /* connection states */
     public static final class State {
         public static final int Active = 1;
 
@@ -76,9 +94,7 @@
         public static final int Closed = 5;
     }
 
-    //
-    // task to execute when ACM timer signal arrives
-    //
+    /* task to execute when ACM timer signal arrives */
     final class ACMTask extends java.util.TimerTask {
         GIOPConnection connection_;
 
@@ -103,75 +119,52 @@
     // Member data
     // ----------------------------------------------------------------
 
-    //
-    // the ORB instance this connection is bound with
-    //
+    /** the next request id */
+    private final AtomicInteger nextRequestId;
+
+    /** the ORB instance this connection is bound with */
     protected ORBInstance orbInstance_ = null;
 
-    //
-    // transport this connection represents
-    //
-    protected org.apache.yoko.orb.OCI.Transport transport_ = null;
+    /** transport this connection represents */
+    protected Transport transport_ = null;
 
-    //
-    // Client parent (null if server-side only)
-    //
-    protected GIOPClient client_ = null;
+    /** Client parent (null if server-side only) */
+    private final ConnectorInfo outboundConnectionKey;
 
-    //
-    // Object-adapter interface (null if client-side only)
-    //
+    /** Object-adapter interface (null if client-side only) */
     protected OAInterface oaInterface_ = null;
 
-    //
-    // storage space for unsent/pending messages
-    //
+    /** storage space for unsent/pending messages */
     protected MessageQueue messageQueue_ = new MessageQueue();
 
-    //
-    // enabled processing operations
-    //
+    /** enabled processing operations */
     protected int enabledOps_ = AccessOp.Nil;
 
-    //
-    // enabled connection property flags
-    //
+    /** enabled connection property flags */
     protected int properties_ = 0;
 
-    //
-    // state of this connection
-    //
+    /** state of this connection */
     protected int state_ = State.Holding;
 
-    //
-    // number of upcalls in progress
-    //
+    /** number of upcalls in progress */
     protected int upcallsInProgress_ = 0;
 
-    //
-    // code converters used by the connection
-    //
+    /** code converters used by the connection */
     protected CodeConverters codeConverters_ = null;
 
-    //
-    // maximum GIOP version encountered during message transactions
-    //
+    /** maximum GIOP version encountered during message transactions */
     protected org.omg.GIOP.Version giopVersion_ = new org.omg.GIOP.Version(
             (byte) 0, (byte) 0);
 
-    //
-    // ACM timeout variables
-    //
+    /** ACM timeout variables */
     protected int shutdownTimeout_ = 2;
 
     protected int idleTimeout_ = 0;
 
-    //
-    // timer used for ACM management
-    //
+    /** timer used for ACM management */
     protected java.util.Timer acmTimer_ = null;
 
-	private CodeBase serverRuntime_;
+    private CodeBase serverRuntime_;
 
     protected ACMTask acmTask_ = null;
 
@@ -203,18 +196,16 @@
         return false;
     }
 
-    //
-    // read the codeset information from the SCL
-    //
+    /** read the codeset information from the SCL */
     protected void readCodeConverters(org.omg.IOP.ServiceContext[] scl) {
         if (codeConverters_ != null)
             return;
 
-        for (int i = 0; i < scl.length; i++) {
-            if (scl[i].context_id == org.omg.IOP.CodeSets.value) {
-                org.omg.CONV_FRAME.CodeSetContextHolder codeSetContextH = new org.omg.CONV_FRAME.CodeSetContextHolder();
-                CodeSetUtil.extractCodeSetContext(scl[i], codeSetContextH);
-                org.omg.CONV_FRAME.CodeSetContext codeSetContext = codeSetContextH.value;
+        for (ServiceContext aScl : scl) {
+            if (aScl.context_id == CodeSets.value) {
+                CodeSetContextHolder codeSetContextH = new CodeSetContextHolder();
+                CodeSetUtil.extractCodeSetContext(aScl, codeSetContextH);
+                CodeSetContext codeSetContext = codeSetContextH.value;
 
                 CodeSetDatabase db = CodeSetDatabase.instance();
 
@@ -241,7 +232,7 @@
                         else {
                             CodeSetInfo info = db.getCodeSetInfo(orbInstance_
                                     .getNativeCs());
-                            msg += info.description;
+                            msg += info != null ? info.description : null;
                         }
                     }
                     msg += "\nwchar code set: ";
@@ -253,7 +244,7 @@
                         else {
                             CodeSetInfo info = db.getCodeSetInfo(orbInstance_
                                     .getNativeWcs());
-                            msg += info.description;
+                            msg += info != null ? info.description : null;
                         }
                     }
 
@@ -264,10 +255,10 @@
         }
     }
 
-    //
-    // set the OAInterface used by BiDir clients to handle requests
-    // Returns true if an OAInterface is found; false otherwise
-    //
+    /**
+     * set the OAInterface used by BiDir clients to handle requests
+     * @return true iff an OAInterface is found
+     */
     protected boolean setOAInterface(org.apache.yoko.orb.OCI.ProfileInfo pi) {
         //
         // Release the old OAInterface
@@ -289,29 +280,25 @@
 
         org.omg.PortableServer.POAManager[] poaManagers = poamanFactory.list();
 
-        for (int i = 0; i < poaManagers.length; i++) {
+        for (POAManager poaManager : poaManagers) {
             try {
-                org.apache.yoko.orb.OBPortableServer.POAManager_impl poamanImpl = (org.apache.yoko.orb.OBPortableServer.POAManager_impl) poaManagers[i];
+                POAManager_impl poamanImpl = (POAManager_impl) poaManager;
 
-                org.apache.yoko.orb.OB.OAInterface oaImpl = poamanImpl
+                OAInterface oaImpl = poamanImpl
                         ._OB_getOAInterface();
 
-                org.omg.IOP.IORHolder refIOR = new org.omg.IOP.IORHolder();
-                if (oaImpl.findByKey(pi.key, refIOR) == org.apache.yoko.orb.OB.OAInterface.OBJECT_HERE) {
+                IORHolder refIOR = new IORHolder();
+                if (oaImpl.findByKey(pi.key, refIOR) == OAInterface.OBJECT_HERE) {
                     oaInterface_ = oaImpl;
                     return true;
                 }
-            } catch (java.lang.ClassCastException ex) {
-                continue;
-            }
+            } catch (ClassCastException ignore) {}
         }
 
         return false;
     }
 
-    //
-    // log the closing of this connection
-    //
+    /** log the closing of this connection */
     synchronized protected void logClose(boolean initiatedClosure) {
         if ((properties_ & Property.ClosingLogged) != 0)
             return;
@@ -332,10 +319,7 @@
         }
     }
 
-    //
-    // main entry point into message processing
-    // This method delegates to one of the specific methods
-    //
+    /** main entry point into message processing - delegate to a specific methods */
     protected Upcall processMessage(GIOPIncomingMessage msg) {
         //
         // update the version of GIOP found
@@ -354,61 +338,58 @@
         // hand off message type processing
         //
         switch (msg.type().value()) {
-        case org.omg.GIOP.MsgType_1_1._Reply:
-            processReply(msg);
-            break;
+            case org.omg.GIOP.MsgType_1_1._Reply:
+                processReply(msg);
+                break;
 
-        case org.omg.GIOP.MsgType_1_1._Request:
-            return processRequest(msg);
+            case org.omg.GIOP.MsgType_1_1._Request:
+                return processRequest(msg);
 
-        case org.omg.GIOP.MsgType_1_1._LocateRequest:
-            processLocateRequest(msg);
-            break;
+            case org.omg.GIOP.MsgType_1_1._LocateRequest:
+                processLocateRequest(msg);
+                break;
 
-        case org.omg.GIOP.MsgType_1_1._CancelRequest:
-            break;
+            case org.omg.GIOP.MsgType_1_1._CancelRequest:
+                break;
 
-        case org.omg.GIOP.MsgType_1_1._LocateReply:
-            processLocateReply(msg);
-            break;
+            case org.omg.GIOP.MsgType_1_1._LocateReply:
+                processLocateReply(msg);
+                break;
 
-        case org.omg.GIOP.MsgType_1_1._CloseConnection:
-            processCloseConnection(msg);
-            break;
+            case org.omg.GIOP.MsgType_1_1._CloseConnection:
+                processCloseConnection(msg);
+                break;
 
-        case org.omg.GIOP.MsgType_1_1._MessageError:
-            processMessageError(msg);
-            break;
+            case org.omg.GIOP.MsgType_1_1._MessageError:
+                processMessageError(msg);
+                break;
 
-        case org.omg.GIOP.MsgType_1_1._Fragment:
-            processFragment(msg);
-            break;
+            case org.omg.GIOP.MsgType_1_1._Fragment:
+                processFragment(msg);
+                break;
 
-        default:
-            processException(
-                    State.Error,
-                    new org.omg.CORBA.COMM_FAILURE(
-                            MinorCodes
-                                    .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownMessage),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorUnknownMessage,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE),
-                    false);
-            break;
+            default:
+                processException(
+                        State.Error,
+                        new COMM_FAILURE(
+                                MinorCodes.describeCommFailure(MinorCodes.MinorUnknownMessage),
+                                MinorCodes.MinorUnknownMessage,
+                                CompletionStatus.COMPLETED_MAYBE),
+                        false);
+                break;
         }
 
         return null;
     }
 
-    //
-    // process a request message
-    //
+    /** process a request message */
     synchronized protected Upcall processRequest(GIOPIncomingMessage msg) {
         if ((properties_ & Property.ServerEnabled) == 0) {
-            processException(State.Error, new org.omg.CORBA.COMM_FAILURE(
+            processException(State.Error, new COMM_FAILURE(
                     MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+                            .describeCommFailure(MinorCodes.MinorWrongMessage),
+                    MinorCodes.MinorWrongMessage,
+                    CompletionStatus.COMPLETED_MAYBE), false);
             return null;
         }
 
@@ -426,15 +407,15 @@
             if (target.value.discriminator() != org.omg.GIOP.KeyAddr.value) {
                 processException(
                         State.Error,
-                        new org.omg.CORBA.NO_IMPLEMENT(
+                        new NO_IMPLEMENT(
                                 MinorCodes
-                                        .describeNoImplement(org.apache.yoko.orb.OB.MinorCodes.MinorNotSupportedByLocalObject),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorNotSupportedByLocalObject,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO),
+                                        .describeNoImplement(MinorCodes.MinorNotSupportedByLocalObject),
+                                MinorCodes.MinorNotSupportedByLocalObject,
+                                CompletionStatus.COMPLETED_NO),
                         false);
                 return null;
             }
-        } catch (org.omg.CORBA.SystemException ex) {
+        } catch (SystemException ex) {
             processException(State.Error, ex, false);
             return null;
         }
@@ -476,9 +457,7 @@
         // Parse the SCL, examining it for various codeset info
         //
         readCodeConverters(scl.value);
-        if (codeConverters_ != null)
-            in._OB_codeConverters(codeConverters_, (version.major << 8)
-                    | version.minor);
+        in._OB_codeConverters(codeConverters_, GiopVersion.get(version.major, version.minor));
 
         //
         // read in the peer's sending context runtime object
@@ -490,48 +469,46 @@
         //
         if (response.value)
             upcallsInProgress_++;
-        
-        orbInstance_.getLogger().debug("Processing request reqId=" + reqId + " op=" + op.value); 
+
+        orbInstance_.getLogger().debug("Processing request reqId=" + reqId + " op=" + op.value);
 
         return oaInterface_.createUpcall(
                 response.value ? upcallReturnInterface() : null, profileInfo,
                 transport_.get_info(), reqId, op.value, in, scl.value);
     }
 
-    //
-    // process a reply message
-    //
+    /** process a reply message */
     synchronized protected void processReply(GIOPIncomingMessage msg) {
         if ((properties_ & Property.ClientEnabled) == 0) {
-            processException(State.Error, new org.omg.CORBA.COMM_FAILURE(
+            processException(State.Error, new COMM_FAILURE(
                     MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+                            .describeCommFailure(MinorCodes.MinorWrongMessage),
+                    MinorCodes.MinorWrongMessage,
+                    CompletionStatus.COMPLETED_MAYBE), false);
             return;
         }
 
-        int reqId = 0;
+        int reqId;
         org.omg.GIOP.ReplyStatusType_1_2Holder status = new org.omg.GIOP.ReplyStatusType_1_2Holder();
         org.omg.IOP.ServiceContextListHolder scl = new org.omg.IOP.ServiceContextListHolder();
 
         try {
             reqId = msg.readReplyHeader(status, scl);
-        } catch (org.omg.CORBA.SystemException ex) {
+        } catch (SystemException ex) {
             processException(State.Error, ex, false);
             return;
         }
-        
+
         Downcall down = messageQueue_.findAndRemovePending(reqId);
         if (down == null) {
             //
             // Request id is unknown
             //
-            processException(State.Error, new org.omg.CORBA.COMM_FAILURE(
+            processException(State.Error, new COMM_FAILURE(
                     MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownReqId)
-                            + ": " + reqId, org.apache.yoko.orb.OB.MinorCodes.MinorUnknownReqId,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+                            .describeCommFailure(MinorCodes.MinorUnknownReqId)
+                            + ": " + reqId, MinorCodes.MinorUnknownReqId,
+                    CompletionStatus.COMPLETED_MAYBE), false);
             return;
         }
 
@@ -542,97 +519,104 @@
         // read in the peer's sendig context runtime object
         //
         assignSendingContextRuntime(in, scl.value);
-        
-        orbInstance_.getLogger().debug("Processing reply for reqId=" + reqId + " status=" + status.value.value()); 
+
+        orbInstance_.getLogger().debug("Processing reply for reqId=" + reqId + " status=" + status.value.value());
 
         switch (status.value.value()) {
-        case org.omg.GIOP.ReplyStatusType_1_2._NO_EXCEPTION:
-            down.setNoException(in);
-            break;
-
-        case org.omg.GIOP.ReplyStatusType_1_2._USER_EXCEPTION:
-            down.setUserException(in);
-            break;
-
-        case org.omg.GIOP.ReplyStatusType_1_2._SYSTEM_EXCEPTION: {
-            try {
-                org.omg.CORBA.SystemException ex = Util
-                        .unmarshalSystemException(in);
-                down.setSystemException(ex);
-            } catch (org.omg.CORBA.SystemException ex) {
-                processException(State.Error, ex, false);
-            }
-
-            break;
-        }
-
-        case org.omg.GIOP.ReplyStatusType_1_2._LOCATION_FORWARD: {
-            try {
-                org.omg.IOP.IOR ior = org.omg.IOP.IORHelper.read(in);
-                down.setLocationForward(ior, false);
-            } catch (org.omg.CORBA.SystemException ex) {
-                processException(State.Error, ex, false);
-            }
-
-            break;
-        }
-
-        case org.omg.GIOP.ReplyStatusType_1_2._LOCATION_FORWARD_PERM: {
-            try {
-                org.omg.IOP.IOR ior = org.omg.IOP.IORHelper.read(in);
-                down.setLocationForward(ior, true);
+            case ReplyStatusType_1_2._NO_EXCEPTION:
+                down.setNoException(in);
                 break;
-            } catch (org.omg.CORBA.SystemException ex) {
-                processException(State.Error, ex, false);
+
+            case ReplyStatusType_1_2._USER_EXCEPTION:
+                down.setUserException(in);
+                break;
+
+            case ReplyStatusType_1_2._SYSTEM_EXCEPTION: {
+                try {
+                    SystemException ex = Util.unmarshalSystemException(in);
+                    ex = convertToUnknownExceptionIfAppropriate(ex, in, scl.value);
+                    down.setSystemException(ex);
+                } catch (SystemException ex) {
+                    processException(State.Error, ex, false);
+                }
+
+                break;
+            }
+
+            case ReplyStatusType_1_2._LOCATION_FORWARD: {
+                try {
+                    IOR ior = IORHelper.read(in);
+                    down.setLocationForward(ior, false);
+                } catch (SystemException ex) {
+                    processException(State.Error, ex, false);
+                }
+
+                break;
+            }
+
+            case ReplyStatusType_1_2._LOCATION_FORWARD_PERM: {
+                try {
+                    IOR ior = IORHelper.read(in);
+                    down.setLocationForward(ior, true);
+                    break;
+                } catch (SystemException ex) {
+                    processException(State.Error, ex, false);
+                }
+            }
+
+            case ReplyStatusType_1_2._NEEDS_ADDRESSING_MODE:
+                //
+                // TODO: implement
+                //
+                processException(
+                        State.Error,
+                        new NO_IMPLEMENT(
+                                MinorCodes.describeNoImplement(MinorCodes.MinorNotSupportedByLocalObject),
+                                MinorCodes.MinorNotSupportedByLocalObject,
+                                CompletionStatus.COMPLETED_NO), false);
+                break;
+
+            default:
+                processException(
+                        State.Error,
+                        new COMM_FAILURE(
+                                MinorCodes.describeCommFailure(MinorCodes.MinorUnknownReplyMessage),
+                                MinorCodes.MinorUnknownReplyMessage,
+                                CompletionStatus.COMPLETED_MAYBE),
+                        false);
+                break;
+        }
+    }
+
+    private SystemException convertToUnknownExceptionIfAppropriate(SystemException ex, InputStream is,
+                                                                   ServiceContext[] scl) {
+        if (ex instanceof UNKNOWN) {
+            for (ServiceContext sc : scl) {
+                if (sc.context_id == UnknownExceptionInfo.value) {
+                    return new UnresolvedException((UNKNOWN) ex, sc.context_data, is);
+                }
             }
         }
-
-        case org.omg.GIOP.ReplyStatusType_1_2._NEEDS_ADDRESSING_MODE:
-            //
-            // TODO: implement
-            //
-            processException(
-                    State.Error,
-                    new org.omg.CORBA.NO_IMPLEMENT(
-                            MinorCodes
-                                    .describeNoImplement(org.apache.yoko.orb.OB.MinorCodes.MinorNotSupportedByLocalObject),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorNotSupportedByLocalObject,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO), false);
-            break;
-
-        default:
-            processException(
-                    State.Error,
-                    new org.omg.CORBA.COMM_FAILURE(
-                            MinorCodes
-                                    .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownReplyMessage),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorUnknownReplyMessage,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE),
-                    false);
-            break;
-        }
+        return ex;
     }
 
     private void assignSendingContextRuntime(InputStream in, ServiceContext[] scl) {
         if (serverRuntime_ == null) {
             serverRuntime_
-                = Util.getSendingContextRuntime (orbInstance_, scl);
+                    = Util.getSendingContextRuntime (orbInstance_, scl);
         }
 
         in.__setSendingContextRuntime(serverRuntime_);
 
-	}
+    }
 
-	//
-    // process a LocateRequest message
-    //
+    /** process a LocateRequest message */
     synchronized protected void processLocateRequest(GIOPIncomingMessage msg) {
         if ((properties_ & Property.ServerEnabled) == 0) {
-            processException(State.Error, new org.omg.CORBA.COMM_FAILURE(
-                    MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+            processException(State.Error, new COMM_FAILURE(
+                    MinorCodes.describeCommFailure(MinorCodes.MinorWrongMessage),
+                    MinorCodes.MinorWrongMessage,
+                    CompletionStatus.COMPLETED_MAYBE), false);
             return;
         }
         Assert._OB_assert(state_ == State.Active);
@@ -668,11 +652,10 @@
             if (target.value.discriminator() != org.omg.GIOP.KeyAddr.value) {
                 processException(
                         State.Error,
-                        new org.omg.CORBA.NO_IMPLEMENT(
-                                MinorCodes
-                                        .describeNoImplement(org.apache.yoko.orb.OB.MinorCodes.MinorNotSupportedByLocalObject),
-                                org.apache.yoko.orb.OB.MinorCodes.MinorNotSupportedByLocalObject,
-                                org.omg.CORBA.CompletionStatus.COMPLETED_NO),
+                        new NO_IMPLEMENT(
+                                MinorCodes.describeNoImplement(MinorCodes.MinorNotSupportedByLocalObject),
+                                MinorCodes.MinorNotSupportedByLocalObject,
+                                CompletionStatus.COMPLETED_NO),
                         false);
                 return;
             }
@@ -681,13 +664,13 @@
             // Get the key
             //
             byte[] key = target.value.object_key();
-            
+
             //
             // Find the IOR for the key
             //
             org.omg.IOP.IORHolder ior = new org.omg.IOP.IORHolder();
             int val = oaInterface_.findByKey(key, ior);
-            org.omg.GIOP.LocateStatusType_1_2 status = org.omg.GIOP.LocateStatusType_1_2
+            LocateStatusType_1_2 status = LocateStatusType_1_2
                     .from_int(val);
 
             //
@@ -710,9 +693,9 @@
             // OBJECT_FORWARD_PERM the IOR is appended to the end of the
             // LocateReply.
             //
-            if (status == org.omg.GIOP.LocateStatusType_1_2.OBJECT_FORWARD
-                    || status == org.omg.GIOP.LocateStatusType_1_2.OBJECT_FORWARD_PERM)
-                org.omg.IOP.IORHelper.write(out, ior.value);
+            if (status == LocateStatusType_1_2.OBJECT_FORWARD
+                    || status == LocateStatusType_1_2.OBJECT_FORWARD_PERM)
+                IORHelper.write(out, ior.value);
 
             //
             // TODO:
@@ -734,21 +717,18 @@
             // Send the locate reply
             //
             sendUpcallReply(out._OB_buffer());
-        } catch (org.omg.CORBA.SystemException ex) {
+        } catch (SystemException ex) {
             processException(State.Error, ex, false);
         }
     }
 
-    //
-    // process a LocateReply message
-    //
+    /** process a LocateReply message */
     synchronized protected void processLocateReply(GIOPIncomingMessage msg) {
         if ((properties_ & Property.ClientEnabled) == 0) {
-            processException(State.Closed, new org.omg.CORBA.COMM_FAILURE(
-                    MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+            processException(State.Closed, new COMM_FAILURE(
+                    MinorCodes.describeCommFailure(MinorCodes.MinorWrongMessage),
+                    MinorCodes.MinorWrongMessage,
+                    CompletionStatus.COMPLETED_MAYBE), false);
             return;
         }
 
@@ -757,7 +737,7 @@
 
         try {
             reqId = msg.readLocateReplyHeader(status);
-        } catch (org.omg.CORBA.SystemException ex) {
+        } catch (SystemException ex) {
             processException(State.Error, ex, false);
             return;
         }
@@ -767,11 +747,10 @@
             //
             // Request id is unknown
             //
-            processException(State.Error, new org.omg.CORBA.COMM_FAILURE(
-                    MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownReqId),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorUnknownReqId,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+            processException(State.Error, new COMM_FAILURE(
+                    MinorCodes.describeCommFailure(MinorCodes.MinorUnknownReqId),
+                    MinorCodes.MinorUnknownReqId,
+                    CompletionStatus.COMPLETED_MAYBE), false);
             return;
         }
 
@@ -780,11 +759,10 @@
         //
         String op = down.operation();
         if (!op.equals("_locate")) {
-            processException(State.Error, new org.omg.CORBA.COMM_FAILURE(
-                    MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorWrongMessage,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+            processException(State.Error, new COMM_FAILURE(
+                    MinorCodes.describeCommFailure(MinorCodes.MinorWrongMessage),
+                    MinorCodes.MinorWrongMessage,
+                    CompletionStatus.COMPLETED_MAYBE), false);
             return;
         }
 
@@ -792,78 +770,72 @@
         Logger logger = orbInstance_.getLogger();
 
         switch (status.value.value()) {
-        case org.omg.GIOP.LocateStatusType_1_2._UNKNOWN_OBJECT:
-            down.setSystemException(new org.omg.CORBA.OBJECT_NOT_EXIST());
-            break;
+            case LocateStatusType_1_2._UNKNOWN_OBJECT:
+                down.setSystemException(new org.omg.CORBA.OBJECT_NOT_EXIST());
+                break;
 
-        case org.omg.GIOP.LocateStatusType_1_2._OBJECT_HERE:
-            down.setNoException(in);
-            break;
+            case LocateStatusType_1_2._OBJECT_HERE:
+                down.setNoException(in);
+                break;
 
-        case org.omg.GIOP.LocateStatusType_1_2._OBJECT_FORWARD:
-            try {
-                org.omg.IOP.IOR ior = org.omg.IOP.IORHelper.read(in);
-                down.setLocationForward(ior, false);
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Locate request forwarded to " + IORDump.PrintObjref(orbInstance_.getORB(), ior)); 
+            case LocateStatusType_1_2._OBJECT_FORWARD:
+                try {
+                    IOR ior = IORHelper.read(in);
+                    down.setLocationForward(ior, false);
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Locate request forwarded to " + IORDump.PrintObjref(orbInstance_.getORB(), ior));
+                    }
+                } catch (SystemException ex) {
+                    logger.warning("An error occurred while reading a "
+                                    + "locate reply, possibly indicating\n"
+                                    + "an interoperability problem. You may "
+                                    + "need to set the LocateRequestPolicy\n"
+                                    + "to false.");
+                    down.setSystemException(ex);
+                    processException(State.Error, ex, false);
                 }
-            } catch (org.omg.CORBA.SystemException ex) {
-                logger
-                        .warning("An error occurred while reading a "
-                                + "locate reply, possibly indicating\n"
-                                + "an interoperability problem. You may "
-                                + "need to set the LocateRequestPolicy\n"
-                                + "to false.");
-                down.setSystemException(ex);
-                processException(State.Error, ex, false);
-            }
-            break;
+                break;
 
-        case org.omg.GIOP.LocateStatusType_1_2._OBJECT_FORWARD_PERM:
-            try {
-                org.omg.IOP.IOR ior = org.omg.IOP.IORHelper.read(in);
-                down.setLocationForward(ior, true);
-                if (logger.isDebugEnabled()) {
-                    logger.debug("Locate request forwarded to " + IORDump.PrintObjref(orbInstance_.getORB(), ior)); 
+            case LocateStatusType_1_2._OBJECT_FORWARD_PERM:
+                try {
+                    IOR ior = IORHelper.read(in);
+                    down.setLocationForward(ior, true);
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Locate request forwarded to " + IORDump.PrintObjref(orbInstance_.getORB(), ior));
+                    }
+                } catch (SystemException ex) {
+                    logger.warning("An error occurred while reading a "
+                                    + "locate reply, possibly indicating\n"
+                                    + "an interoperability problem. You may "
+                                    + "need to set the LocateRequestPolicy\n"
+                                    + "to false.");
+                    down.setSystemException(ex);
+                    processException(State.Error, ex, false);
                 }
-            } catch (org.omg.CORBA.SystemException ex) {
-                logger
-                        .warning("An error occurred while reading a "
-                                + "locate reply, possibly indicating\n"
-                                + "an interoperability problem. You may "
-                                + "need to set the LocateRequestPolicy\n"
-                                + "to false.");
-                down.setSystemException(ex);
-                processException(State.Error, ex, false);
-            }
 
-            break;
+                break;
 
-        case org.omg.GIOP.LocateStatusType_1_2._LOC_SYSTEM_EXCEPTION:
-            try {
-                org.omg.CORBA.SystemException ex = org.omg.CORBA.SystemExceptionHelper
-                        .read(in);
-                down.setSystemException(ex);
-            } catch (org.omg.CORBA.SystemException ex) {
-                down.setSystemException(ex);
-                processException(State.Error, ex, false);
-            }
+            case LocateStatusType_1_2._LOC_SYSTEM_EXCEPTION:
+                try {
+                    SystemException ex = SystemExceptionHelper.read(in);
+                    down.setSystemException(ex);
+                } catch (SystemException ex) {
+                    down.setSystemException(ex);
+                    processException(State.Error, ex, false);
+                }
 
-            break;
+                break;
 
-        case org.omg.GIOP.LocateStatusType_1_2._LOC_NEEDS_ADDRESSING_MODE:
-            // TODO: implement
-            processException(State.Error, new org.omg.CORBA.NO_IMPLEMENT(),
-                    false);
-            break;
+            case LocateStatusType_1_2._LOC_NEEDS_ADDRESSING_MODE:
+                // TODO: implement
+                processException(State.Error, new NO_IMPLEMENT(), false);
+                break;
         }
     }
 
-    //
-    // process a CloseConnection message
-    //
+    /** process a CloseConnection message */
     protected void processCloseConnection(GIOPIncomingMessage msg) {
-        orbInstance_.getLogger().debug("Close connection request received from peer"); 
+        orbInstance_.getLogger().debug("Close connection request received from peer");
         if ((properties_ & Property.ClientEnabled) != 0) {
             //
             // If the peer closes the connection, all outstanding
@@ -875,44 +847,35 @@
             //
             processException(
                     State.Closed,
-                    new org.omg.CORBA.TRANSIENT(
-                            MinorCodes
-                                    .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorCloseConnection),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorCloseConnection,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO), true);
+                    new TRANSIENT(
+                            MinorCodes.describeTransient(MinorCodes.MinorCloseConnection),
+                            MinorCodes.MinorCloseConnection,
+                            CompletionStatus.COMPLETED_NO), true);
         } else {
             setState(State.Closed);
         }
     }
 
-    //
-    // process a MessageError message
-    //
+    /** process a MessageError message */
     protected void processMessageError(GIOPIncomingMessage msg) {
-        processException(State.Error, new org.omg.CORBA.COMM_FAILURE(org.apache.yoko.orb.OB.MinorCodes
-                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorMessageError),
-                org.apache.yoko.orb.OB.MinorCodes.MinorMessageError,
-                org.omg.CORBA.CompletionStatus.COMPLETED_NO), false);
+        processException(
+                State.Error,
+                new COMM_FAILURE(
+                        MinorCodes.describeCommFailure(MinorCodes.MinorMessageError),
+                        MinorCodes.MinorMessageError,
+                        CompletionStatus.COMPLETED_NO), false);
     }
 
-    //
-    // process a Fragment message
-    //
+    /** process a Fragment message */
     protected void processFragment(GIOPIncomingMessage msg) {
-        //
-        // At this point there should be no fragments, only complete
-        // messages.
-        //
+        // At this point there should be no fragments, only complete messages.
         Assert._OB_assert(false);
     }
 
-    //
-    // process a system exception
-    //
-    protected boolean processException(int state,
-            org.omg.CORBA.SystemException ex, boolean completed) {
+    /** process a system exception */
+    protected boolean processException(int state,SystemException ex, boolean completed) {
         Assert._OB_assert(state == State.Error || state == State.Closed);
-        
+
         orbInstance_.getLogger().debug("processing an exception, state=" + state, ex);
 
         synchronized (this) {
@@ -928,24 +891,18 @@
             //
             state_ = state;
 
-            //
-            // change the enabled/disable operations and break the
-            // cyclic dependency with GIOPClient
-            //
+            // change the enabled/disable operations and break the cyclic dependency with GIOPClient
             switch (state) {
-            case State.Error:
-                enabledOps_ &= ~(AccessOp.Read | AccessOp.Write);
-                enabledOps_ |= AccessOp.Close;
-                if (client_ != null)
-                    client_.removeConnection(this);
-                break;
+                case State.Error:
+                    enabledOps_ &= ~(AccessOp.Read | AccessOp.Write);
+                    enabledOps_ |= AccessOp.Close;
+                    break;
 
-            case State.Closed:
-                enabledOps_ = AccessOp.Nil;
-                if (client_ != null)
-                    client_.removeConnection(this);
-                break;
+                case State.Closed:
+                    enabledOps_ = AccessOp.Nil;
+                    break;
             }
+            orbInstance_.getOutboundConnectionCache().remove(outboundConnectionKey, this);
 
             //
             // propogate any exceptions to the message queue
@@ -956,11 +913,14 @@
         //
         // apply the shutdown
         //
-        if (state == State.Error) {
-            abortiveShutdown();
-        } else if (state == State.Closed) {
-            logClose(true);
-            transport_.close();
+        switch (state) {
+            case State.Error:
+                abortiveShutdown();
+                break;
+            case State.Closed:
+                logClose(true);
+                transport_.close();
+                break;
         }
 
         //
@@ -968,7 +928,6 @@
         //
         synchronized (this) {
             properties_ |= Property.Destroyed;
-            client_ = null;
         }
 
         //
@@ -978,9 +937,7 @@
         return true;
     }
 
-    //
-    // transmits a reply back once the upcall completes
-    //
+    /** transmits a reply back once the upcall completes */
     protected void sendUpcallReply(org.apache.yoko.orb.OCI.Buffer buf) {
         synchronized (this) {
             //
@@ -1016,19 +973,13 @@
         }
     }
 
-    //
-    // shutdown the connection forcefully and immediately
-    //
+    /** shutdown the connection forcefully and immediately */
     abstract protected void abortiveShutdown();
 
-    //
-    // shutdown the connection gracefully
-    //
+    /** shutdown the connection gracefully */
     abstract protected void gracefulShutdown();
 
-    //
-    // turn on ACM idle connection monitoring
-    //
+    /** turn on ACM idle connection monitoring */
     synchronized protected void ACM_enableIdleMonitor() {
         if (idleTimeout_ > 0) {
             acmTimer_ = new java.util.Timer(true);
@@ -1038,9 +989,7 @@
         }
     }
 
-    //
-    // turn off ACM idle connection monitoring
-    //
+    /** turn off ACM idle connection monitoring */
     synchronized protected void ACM_disableIdleMonitor() {
         if (acmTimer_ != null) {
             acmTimer_.cancel();
@@ -1057,17 +1006,15 @@
     // Public methods
     // ----------------------------------------------------------------
 
-    //
-    // client-side constructor
-    //
-    public GIOPConnection(ORBInstance orbInstance,
-            org.apache.yoko.orb.OCI.Transport transport, GIOPClient client) {
+    /** client-side constructor */
+    public GIOPConnection(ORBInstance orbInstance, Transport transport, GIOPClient client) {
         //
         // set member properties
         //
+        nextRequestId = new AtomicInteger(0xA);
         orbInstance_ = orbInstance;
         transport_ = transport;
-        client_ = client;
+        outboundConnectionKey = client.connectorInfo();
         state_ = State.Active;
         properties_ = Property.CreatedByClient | Property.ClientEnabled;
         enabledOps_ = AccessOp.Read | AccessOp.Write;
@@ -1104,16 +1051,15 @@
         }
     }
 
-    //
-    // server-side constructor
-    //
-    public GIOPConnection(ORBInstance orbInstance,
-            org.apache.yoko.orb.OCI.Transport transport, OAInterface oa) {
+    /** server-side constructor */
+    public GIOPConnection(ORBInstance orbInstance, Transport transport, OAInterface oa) {
         //
         // set members
         //
+        nextRequestId = new AtomicInteger(0xB);
         orbInstance_ = orbInstance;
         transport_ = transport;
+        outboundConnectionKey = null;
         oaInterface_ = oa;
         properties_ = Property.ServerEnabled;
 
@@ -1138,9 +1084,26 @@
             idleTimeout_ = Integer.parseInt(value);
     }
 
-    //
-    // start populating the reply data
-    //
+    /** @return true iff this connection was initiated by the other party */
+    public final boolean isInbound() {
+        return (properties_ & Property.CreatedByClient) == 0;
+    }
+
+    /** @return true iff this connection was initiated by this party */
+    public final boolean isOutbound() {
+        return !!! isInbound();
+    }
+
+    /** @return the next request id to use */
+    public int getNewRequestId() {
+        // In the case of BiDir connections, the client should use
+        // even numbered requestIds and the server should use odd
+        // numbered requestIds... the += 2 keeps this pattern intact
+        // assuming its correct at startup
+        return nextRequestId.getAndAdd(2);
+    }
+
+    /** start populating the reply data */
     public void upcallBeginReply(Upcall upcall, org.omg.IOP.ServiceContext[] scl) {
         upcall.createOutputStream(12);
         org.apache.yoko.orb.CORBA.OutputStream out = upcall.output();
@@ -1153,9 +1116,9 @@
         try {
             synchronized (this) {
                 outgoing.writeReplyHeader(reqId,
-                        org.omg.GIOP.ReplyStatusType_1_2.NO_EXCEPTION, scl);
+                        ReplyStatusType_1_2.NO_EXCEPTION, scl);
             }
-        } catch (org.omg.CORBA.SystemException ex) {
+        } catch (SystemException ex) {
             //
             // Nothing may go wrong here, otherwise we might have a
             // recursion
@@ -1164,9 +1127,7 @@
         }
     }
 
-    //
-    // finished reply construction; ready its return
-    //
+    /** finished reply construction; ready its return */
     public void upcallEndReply(Upcall upcall) {
         //
         // Make sure the transport can send a reply
@@ -1205,7 +1166,7 @@
         try {
             outgoing.writeMessageHeader(org.omg.GIOP.MsgType_1_1.Reply, false,
                     pos - 12);
-        } catch (org.omg.CORBA.SystemException ex) {
+        } catch (SystemException ex) {
             //
             // Nothing may go wrong here, otherwise we might have a
             // recursion
@@ -1216,11 +1177,9 @@
         sendUpcallReply(out._OB_buffer());
     }
 
-    //
-    // start populating the reply with a user exception
-    //
+    /** start populating the reply with a user exception */
     public void upcallBeginUserException(Upcall upcall,
-            org.omg.IOP.ServiceContext[] scl) {
+                                         org.omg.IOP.ServiceContext[] scl) {
         upcall.createOutputStream(12);
 
         org.apache.yoko.orb.CORBA.OutputStream out = upcall.output();
@@ -1232,8 +1191,8 @@
 
         try {
             outgoing.writeReplyHeader(reqId,
-                    org.omg.GIOP.ReplyStatusType_1_2.USER_EXCEPTION, scl);
-        } catch (org.omg.CORBA.SystemException ex) {
+                    ReplyStatusType_1_2.USER_EXCEPTION, scl);
+        } catch (SystemException ex) {
             //
             // Nothing may go wrong here, otherwise we might have a
             // recursion
@@ -1242,18 +1201,14 @@
         }
     }
 
-    //
-    // finished reply construction; ready its return
-    //
+    /** finished reply construction; ready its return */
     public void upcallEndUserException(Upcall upcall) {
         upcallEndReply(upcall);
     }
 
-    //
-    // populate and send the reply with a UserException
-    //
+    /** populate and send the reply with a UserException */
     public void upcallUserException(Upcall upcall,
-            org.omg.CORBA.UserException ex, org.omg.IOP.ServiceContext[] scl) {
+                                    org.omg.CORBA.UserException ex, org.omg.IOP.ServiceContext[] scl) {
         upcall.createOutputStream(12);
 
         org.apache.yoko.orb.CORBA.OutputStream out = upcall.output();
@@ -1265,14 +1220,14 @@
 
         try {
             outgoing.writeReplyHeader(reqId,
-                    org.omg.GIOP.ReplyStatusType_1_2.USER_EXCEPTION, scl);
+                    ReplyStatusType_1_2.USER_EXCEPTION, scl);
 
             //
             // Cannot marshal the exception without the Helper
             //
             // ex._OB_marshal(out);
             Assert._OB_assert(false);
-        } catch (org.omg.CORBA.SystemException e) {
+        } catch (SystemException e) {
             //
             // Nothing may go wrong here, otherwise we might have a
             // recursion
@@ -1283,11 +1238,9 @@
         upcallEndReply(upcall);
     }
 
-    //
-    // populate and end the reply with a system exception
-    //
+    /** populate and end the reply with a system exception */
     public void upcallSystemException(Upcall upcall,
-            org.omg.CORBA.SystemException ex, org.omg.IOP.ServiceContext[] scl) {
+                                      SystemException ex, org.omg.IOP.ServiceContext[] scl) {
         upcall.createOutputStream(12);
 
         org.apache.yoko.orb.CORBA.OutputStream out = upcall.output();
@@ -1299,12 +1252,12 @@
         try {
             // print this exception out here so applications have at stack trace to work 
             // cwith for problem determination.
-            
+
             orbInstance_.getLogger().debug("upcall exception", ex);
             outgoing.writeReplyHeader(reqId,
-                    org.omg.GIOP.ReplyStatusType_1_2.SYSTEM_EXCEPTION, scl);
+                    ReplyStatusType_1_2.SYSTEM_EXCEPTION, scl);
             Util.marshalSystemException(out, ex);
-        } catch (org.omg.CORBA.SystemException e) {
+        } catch (SystemException e) {
             //
             // Nothing may go wrong here, otherwise we might have a
             // recursion
@@ -1315,11 +1268,9 @@
         upcallEndReply(upcall);
     }
 
-    //
-    // prepare the reply for location forwarding
-    //
-    public void upcallForward(Upcall upcall, org.omg.IOP.IOR ior, boolean perm,
-            org.omg.IOP.ServiceContext[] scl) {
+    /** prepare the reply for location forwarding */
+    public void upcallForward(Upcall upcall, IOR ior, boolean perm,
+                              org.omg.IOP.ServiceContext[] scl) {
         upcall.createOutputStream(12);
 
         org.apache.yoko.orb.CORBA.OutputStream out = upcall.output();
@@ -1328,18 +1279,18 @@
                 out, profileInfo);
 
         int reqId = upcall.requestId();
-        org.omg.GIOP.ReplyStatusType_1_2 status = perm ? org.omg.GIOP.ReplyStatusType_1_2.LOCATION_FORWARD_PERM
-                : org.omg.GIOP.ReplyStatusType_1_2.LOCATION_FORWARD;
+        ReplyStatusType_1_2 status = perm ? ReplyStatusType_1_2.LOCATION_FORWARD_PERM
+                : ReplyStatusType_1_2.LOCATION_FORWARD;
         try {
             outgoing.writeReplyHeader(reqId, status, scl);
-            Logger logger = orbInstance_.getLogger(); 
-            
+            Logger logger = orbInstance_.getLogger();
+
             if (logger.isDebugEnabled()) {
-                logger.debug("Sending forward reply to " + IORDump.PrintObjref(orbInstance_.getORB(), ior)); 
+                logger.debug("Sending forward reply to " + IORDump.PrintObjref(orbInstance_.getORB(), ior));
             }
-            
-            org.omg.IOP.IORHelper.write(out, ior);
-        } catch (org.omg.CORBA.SystemException ex) {
+
+            IORHelper.write(out, ior);
+        } catch (SystemException ex) {
             //
             // Nothing may go wrong here, otherwise we might have a
             // recursion
@@ -1350,20 +1301,13 @@
         upcallEndReply(upcall);
     }
 
-    //
-    // enable this connection for processing as a client
-    //
-    synchronized public void activateClientSide(GIOPClient client) {
-        Assert._OB_assert(client_ == null);
-
-        client_ = client;
+    /** enable this connection for processing as a client */
+    synchronized public void activateClientSide() {
         properties_ |= Property.ClientEnabled;
         enableConnectionModes(true, true);
     }
 
-    //
-    // enable this connection for processing as a server
-    //
+    /** enable this connection for processing as a server */
     synchronized public void activateServerSide() {
         Assert._OB_assert((properties_ & Property.CreatedByClient) != 0);
 
@@ -1373,75 +1317,52 @@
         }
     }
 
-    //
-    // return a reference to the DowncallEmitter interface
-    //
+    /** @return a reference to the DowncallEmitter interface */
     public DowncallEmitter emitterInterface() {
         Assert._OB_assert((properties_ & Property.ClientEnabled) != 0);
         return this;
     }
 
-    //
-    // return a reference to the UpcallReturn interface
-    //
+    /** @return a reference to the UpcallReturn interface */
     public UpcallReturn upcallReturnInterface() {
         Assert._OB_assert((properties_ & Property.ServerEnabled) != 0);
         return this;
     }
 
-    //
-    // return the transport we represent
-    //
-    public org.apache.yoko.orb.OCI.Transport transport() {
+    /** return the transport we represent */
+    public Transport transport() {
         return transport_;
     }
 
-    //
-    // get the state of this connection
-    //
+    /** get the state of this connection */
     synchronized public int state() {
         Assert._OB_assert(state_ >= State.Active && state_ <= State.Closed);
         return state_;
     }
 
-    //
-    // check if a request has been sent yet
-    //
+    /** check if a request has been sent yet */
     synchronized public boolean requestSent() {
         return (properties_ & Property.RequestSent) != 0;
     }
 
-    //
-    // check if a reply has been sent yet
-    //
+    /** check if a reply has been sent yet */
     synchronized public boolean replySent() {
         return (properties_ & Property.ReplySent) != 0;
     }
 
-    //
-    // check if this connection was already destroyed
-    //
+    /** check if this connection was already destroyed */
     synchronized public boolean destroyed() {
         return (properties_ & Property.Destroyed) != 0;
     }
 
-    //
-    // check if this connection is enabled for BiDir communication
-    //
-    synchronized public boolean bidirConnection() {
-        if (client_ == null)
-            return false;
-        return client_.sharedConnection();
-    }
-
-    //
-    // change the state of this connection
-    //
+    /** change the state of this connection */
     public void setState(int newState) {
         synchronized (this) {
             if (state_ == newState
-                    || (state_ != State.Holding && newState < state_))
+                    || (state_ != State.Holding && newState < state_)) {
+                logger.fine("No state change from " +state_  + " to "  + newState);
                 return;
+            }
 
             //
             // make sure to update the state since some of the actions
@@ -1451,162 +1372,141 @@
         }
 
         switch (newState) {
-        case State.Active:
+            case State.Active:
 
-            //
-            // set the new accessable operations
-            //
-            synchronized (this) {
-                enabledOps_ = AccessOp.Read | AccessOp.Write;
-            }
+                //
+                // set the new accessable operations
+                //
+                synchronized (this) {
+                    enabledOps_ = AccessOp.Read | AccessOp.Write;
+                }
 
-            //
-            // start and refresh the connection
-            start();
-            refresh();
-            break;
+                //
+                // start and refresh the connection
+                start();
+                refresh();
+                break;
 
-        case State.Holding:
+            case State.Holding:
 
-            //
-            // holding connections can't read new messages but can write
-            // pending messages
-            //
-            synchronized (this) {
-                enabledOps_ &= ~AccessOp.Read;
-            }
+                //
+                // holding connections can't read new messages but can write
+                // pending messages
+                //
+                synchronized (this) {
+                    enabledOps_ &= ~AccessOp.Read;
+                }
 
-            //
-            // pause the connection
-            //
-            pause();
-            break;
+                //
+                // pause the connection
+                //
+                pause();
+                break;
 
-        case State.Closing:
+            case State.Closing:
 
-            //
-            // during the closing, the connection can read/write/close
-            //
-            synchronized (this) {
-                enabledOps_ = AccessOp.All;
-            }
+                //
+                // during the closing, the connection can read/write/close
+                //
+                synchronized (this) {
+                    enabledOps_ = AccessOp.All;
+                }
 
-            //
-            // gracefully shutdown by sending off pending messages,
-            // reading any messages left on the wire and then closing
-            //
-            gracefulShutdown();
+                //
+                // gracefully shutdown by sending off pending messages,
+                // reading any messages left on the wire and then closing
+                //
+                gracefulShutdown();
 
-            //
-            // refresh this status
-            //
-            refresh();
-            break;
+                //
+                // refresh this status
+                //
+                refresh();
+                break;
 
-        case State.Error:
+            case State.Error:
 
-            //
-            // we can't read or write in the error state but we can
-            // close ourself down
-            //
-            synchronized (this) {
-                enabledOps_ = AccessOp.Close;
-            }
+                //
+                // we can't read or write in the error state but we can
+                // close ourself down
+                //
+                synchronized (this) {
+                    enabledOps_ = AccessOp.Close;
+                }
 
-            //
-            // there is an error so shutdown abortively
-            //
-            abortiveShutdown();
+                //
+                // there is an error so shutdown abortively
+                //
+                abortiveShutdown();
 
-            //
-            // mark the connection as destroyed now
-            //
-            synchronized (this) {
-                properties_ |= Property.Destroyed;
-            }
+                //
+                // mark the connection as destroyed now
+                //
+                synchronized (this) {
+                    properties_ |= Property.Destroyed;
+                }
 
-            //
-            // refresh the connection status
-            //
-            refresh();
-            break;
+                //
+                // refresh the connection status
+                //
+                refresh();
+                break;
 
-        case State.Closed:
+            case State.Closed:
 
-            //
-            // once closed, nothing else can take place
-            //
-            synchronized (this) {
-                enabledOps_ = AccessOp.Nil;
-            }
+                //
+                // once closed, nothing else can take place
+                //
+                synchronized (this) {
+                    enabledOps_ = AccessOp.Nil;
+                }
 
-            //
-            // log the connection closure
-            //
-            logClose(true);
+                //
+                // log the connection closure
+                //
+                logClose(true);
 
-            //
-            // close the transport
-            //
-            transport_.close();
+                //
+                // close the transport
+                //
+                transport_.close();
 
-            //
-            // mark the connection as destroyed
-            //
-            synchronized (this) {
-                properties_ |= Property.Destroyed;
-            }
+                //
+                // mark the connection as destroyed
+                //
+                synchronized (this) {
+                    properties_ |= Property.Destroyed;
+                }
 
-            //
-            // and refresh the connection
-            //
-            refresh();
-            break;
+                //
+                // and refresh the connection
+                //
+                refresh();
+                break;
 
-        default:
-            Assert._OB_assert(false);
-            break;
+            default:
+                Assert._OB_assert(false);
+                break;
         }
     }
 
-    //
-    // destroy this connection
-    //
-    public void destroy(boolean terminateNow) {
-        if (!terminateNow)
-            setState(State.Closing);
-        else
-            processException(State.Closed, new org.omg.CORBA.TRANSIENT(
-                    MinorCodes
-                            .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+    /** destroy this connection */
+    public void destroy() {
+        setState(State.Closing);
     }
 
-    //
-    // callback method when the ACM signals a timeout
-    //
+    /** callback method when the ACM signals a timeout */
     abstract public void ACM_callback();
 
-    //
-    // activate the connection
-    //
+    /** activate the connection */
     abstract public void start();
 
-    //
-    // refresh the connection status after a change in internal state
-    //
+    /** refresh the connection status after a change in internal state */
     abstract public void refresh();
 
-    //
-    // tell the connection to stop processing; resumable with a
-    // refresh()
-    //
+    /** tell the connection to stop processing; resumable with a refresh() */
     abstract public void pause();
 
-    //
-    // change the connection mode to [client, server, both]
-    //
-    abstract public void enableConnectionModes(boolean enableClient,
-            boolean enableServer);
+    /** change the connection mode to [client, server, both] */
+    abstract public void enableConnectionModes(boolean enableClient, boolean enableServer);
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java
index 4f70cf2..92aef1e 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPConnectionThreaded.java
@@ -17,81 +17,55 @@
 
 package org.apache.yoko.orb.OB;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 public final class GIOPConnectionThreaded extends GIOPConnection {
     static final Logger logger = Logger.getLogger(GIOPConnectionThreaded.class.getName());
+    
     // ----------------------------------------------------------------
     // Inner helper classes
     // ----------------------------------------------------------------
 
-    //
-    // thread to handle connection shutdown
-    // 
-    public final class ShutdownThread extends Thread {
-        private GIOPConnectionThreaded parent_;
 
-        ShutdownThread(ThreadGroup group, GIOPConnectionThreaded parent) {
-            super(group, "Yoko:GIOPConnectionThreaded:ShutdownThread");
-            parent_ = parent;
-        }
+    public final class Shutdown implements Runnable {
 
         public void run() {
             try {
-                parent_.execShutdown();
+                execShutdown();
             } catch (RuntimeException ex) {
                 Assert._OB_assert(ex);
             }
-
-            //
-            // break cyclic dependency with parent
-            //
-            parent_ = null;
         }
     }
 
-    //
-    // thread to handle reception of messages
-    // 
-    public final class ReceiverThread extends Thread {
-        private GIOPConnectionThreaded parent_;
-
-        ReceiverThread(ThreadGroup group, GIOPConnectionThreaded parent) {
-            super(group, "Yoko:GIOPConnectionThreaded:ReceiverThread");
-            parent_ = parent;
+    public final class Receiver implements Runnable {
+        Receiver() {
+            receiverLock.readLock().lock();
         }
-
+        
         public void run() {
             try {
-                parent_.execReceive();
+                execReceive();
             } catch (RuntimeException ex) {
                 Assert._OB_assert(ex);
+            } finally {
+                receiverLock.readLock().unlock();
             }
-
-            //
-            // break cyclic dependency with parent
-            //
-            parent_ = null;
         }
     }
-
     // ----------------------------------------------------------------
     // Member data
     // ----------------------------------------------------------------
     // 
 
     //
-    // the shutdown thread handle
-    //
-    protected Thread shutdownThread_ = null;
-
-    //
-    // the list of receiver threads
-    //
-    protected java.util.LinkedList receiverThreads_ = new java.util.LinkedList();
-
-    //
     // the holding monitor to pause the receiver threads
     //
     protected java.lang.Object holdingMonitor_ = new java.lang.Object();
@@ -105,6 +79,9 @@
     // sending mutex to prevent multiple threads from sending at once
     //
     protected java.lang.Object sendMutex_ = new java.lang.Object();
+    
+    private boolean shuttingDown;
+    private final ReentrantReadWriteLock receiverLock = new ReentrantReadWriteLock(true);
 
     // ----------------------------------------------------------------
     // Protected Methods
@@ -115,45 +92,9 @@
     // Assumes 'this' is synchronized on entry
     //
     protected void addReceiverThread() {
-        //
-        // Retrieve the thread group
-        //
-        ThreadGroup group;
-        if ((properties_ & Property.CreatedByClient) != 0) {
-            group = orbInstance_.getClientWorkerGroup();
-        }
-        else {
-            group = orbInstance_.getServerWorkerGroup();
-        }
-
-        //
-        // Start receiver thread
-        //
-        Thread thr = new ReceiverThread(group, this);
-        thr.setDaemon(true); 
-        thr.start();
-
-        //
-        // add the thread to our list of threads
-        //
-        receiverThreads_.addLast(thr);
+        getExecutor().submit(new Receiver());
     }
 
-    //
-    // clean up any dead receiver threads
-    // assumes 'this' is synchronized on entry
-    //
-    protected void cleanupDeadReceiverThreads() {
-        java.util.ListIterator i = receiverThreads_.listIterator(0);
-
-        while (i.hasNext()) {
-            Thread thr = (Thread) i.next();
-
-            if (!thr.isAlive()) {
-                i.remove();
-            }
-        }
-    }
 
     //
     // pause a thread on a holding monitor if turned on
@@ -229,6 +170,7 @@
                 .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown),
                 org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown,
                 org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+        arrive();
 
     }
 
@@ -244,8 +186,11 @@
         //
         // don't shutdown if there are pending upcalls
         // 
-        if (upcallsInProgress_ > 0 || state_ != State.Closing)
+        if (upcallsInProgress_ > 0 || state_ != State.Closing) {
+            logger.fine("pending upcalls: " + upcallsInProgress_ + " state: " + state_);
+         
             return;
+        }
 
         //
         // send a CloseConnection if we can
@@ -266,38 +211,44 @@
                     org.omg.GIOP.MsgType_1_1.CloseConnection, false, 0);
 
             messageQueue_.add(orbInstance_, out._OB_buffer());
+        } else {
+            logger.fine("could not send close connection message");
         }
 
         //
-        // now create the startup thread
+        // now create the shutdown thread
         //
         try {
-            if (shutdownThread_ != null)
+            if (shuttingDown)
                 return;
 
-            //
-            // Retrieve the thread group
-            //
-            ThreadGroup group;
-            if ((properties_ & Property.CreatedByClient) != 0)
-                group = orbInstance_.getClientWorkerGroup();
-            else
-                group = orbInstance_.getServerWorkerGroup();
-
+            shuttingDown = true;
             //
             // start the shutdown thread
             //
-            shutdownThread_ = new ShutdownThread(group, this);
-            shutdownThread_.setDaemon(true);
-            shutdownThread_.start();
+            try {
+                getExecutor().submit(new Shutdown());
+            } catch (RejectedExecutionException ree) {
+                logger.log(Level.WARNING, "Could not submit shutdown task", ree);
+            }
         } catch (OutOfMemoryError ex) {
             processException(State.Closed, new org.omg.CORBA.IMP_LIMIT(
                     org.apache.yoko.orb.OB.MinorCodes.describeImpLimit(org.apache.yoko.orb.OB.MinorCodes.MinorThreadLimit),
                     org.apache.yoko.orb.OB.MinorCodes.MinorThreadLimit,
                     org.omg.CORBA.CompletionStatus.COMPLETED_NO), false);
+        } finally {
+            arrive();
         }
     }
 
+
+    private void arrive() {
+        if ((properties_ & Property.CreatedByClient) != 0)
+            orbInstance_.getClientPhaser().arriveAndDeregister();
+        else
+            orbInstance_.getServerPhaser().arriveAndDeregister();
+    }
+
     // ----------------------------------------------------------------
     // Public Methods
     // ----------------------------------------------------------------
@@ -308,6 +259,7 @@
     public GIOPConnectionThreaded(ORBInstance orbInstance,
             org.apache.yoko.orb.OCI.Transport transport, GIOPClient client) {
         super(orbInstance, transport, client);
+        orbInstance.getClientPhaser().register();
         start();
     }
 
@@ -317,6 +269,14 @@
     public GIOPConnectionThreaded(ORBInstance orbInstance,
             org.apache.yoko.orb.OCI.Transport transport, OAInterface oa) {
         super(orbInstance, transport, oa);
+        orbInstance.getServerPhaser().register();
+    }
+    
+    private ExecutorService getExecutor() {
+        if ((properties_ & Property.CreatedByClient) != 0)
+            return orbInstance_.getClientExecutor();
+        else
+            return orbInstance_.getServerExecutor();
     }
 
     //
@@ -351,49 +311,38 @@
 
         // 
         // shutdown the transport
+        // synchronization on sendMutex_ is needed to avoid a deadlock in some oracle and ibm jdks between send and shutdown
+        // https://bugs.openjdk.java.net/browse/JDK-8013809 deadlock in SSLSocketImpl between between write and close 
         // 
-        transport_.shutdown();
+        synchronized (sendMutex_) {
+            transport_.shutdown();
+        }
 
         //
         // Shutdown the receiver threads. There may not be a receiver
         // thread if the transport is SendOnly.
         //
-        if (transport_.mode() == org.apache.yoko.orb.OCI.SendReceiveMode.SendReceive
-                || transport_.mode() == org.apache.yoko.orb.OCI.SendReceiveMode.ReceiveOnly) {
-            int timeout = shutdownTimeout_ * 1000;
-
-            synchronized (this) {
-                java.util.ListIterator i = receiverThreads_.listIterator();
-
-                while (i.hasNext()) {
-                    Thread t = (Thread) i.next();
-
-                    try {
-                        if (timeout > 0) {
-                            t.join(timeout);
-                        }
-                        else {
-                            t.join();
-                        }
-                    } catch (InterruptedException ex) {
-                        continue;
-                    }
-
-                    i.remove();
-                }
-            }
+        try {
+            receiverLock.writeLock().tryLock(shutdownTimeout_, SECONDS);
+        } catch (InterruptedException e) {
         }
 
-        //
-        // We now close the connection actively, since it may still be
-        // open under certain circumstances. For example, the reciver
-        // thread may not have terminated yet or the receive thread might
-        // set the state to GIOPState::Error before termination.
-        //
-        processException(State.Closed, new org.omg.CORBA.TRANSIENT(org.apache.yoko.orb.OB.MinorCodes
-                .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown),
-                org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown,
-                org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+        try {
+            //
+            // We now close the connection actively, since it may still be
+            // open under certain circumstances. For example, the receiver
+            // thread may not have terminated yet or the receive thread might
+            // set the state to GIOPState::Error before termination.
+            //
+            processException(State.Closed, new org.omg.CORBA.TRANSIENT(org.apache.yoko.orb.OB.MinorCodes
+                    .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorForcedShutdown,
+                    org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE), false);
+        } finally {
+            if (receiverLock.isWriteLockedByCurrentThread()) {
+                receiverLock.writeLock().unlock();
+            }
+        }
     }
 
     //
@@ -429,7 +378,7 @@
             //
             try {
                 inMsg.extractHeader(buf);
-                logger.fine("Header received for message of size " + inMsg.size()); 
+                logger.fine("Header received for message of size " + inMsg.size());
                 buf.realloc(12 + inMsg.size());
             } catch (org.omg.CORBA.SystemException ex) {
                 processException(State.Error, ex, false);
@@ -448,13 +397,13 @@
                     processException(State.Closed, ex, false);
                     break;
                 }
-                if (logger.isLoggable(Level.FINE)) {
-                    logger.fine("Message body received ");
-                    int currentpos = buf.pos_;
-                    buf.pos_ = 0;
-                    logger.fine("Received message are: \n" + buf.dumpData());
-                    buf.pos_ = currentpos;
-                }
+            }
+            if (logger.isLoggable(Level.FINE)) {
+                logger.fine("Message body received ");
+                int currentpos = buf.pos_;
+                buf.pos_ = 0;
+                logger.fine("Received message are: \n" + buf.dumpData());
+                buf.pos_ = currentpos;
             }
 
             //
@@ -514,9 +463,7 @@
                 // case)
                 // 
                 if (haveBidirSCL) {
-                    synchronized (this) {
-                        addReceiverThread();
-                    }
+                    addReceiverThread();
                 }
 
                 upcall.invoke();
@@ -592,7 +539,7 @@
             // make the downcall thread-safe
             //
             if (down.responseExpected()) {
-                down.initStateMonitor();
+                down.allowWaiting();
             }
 
             // 
@@ -771,7 +718,7 @@
         //
         try {
             boolean result = down.waitUntilCompleted(block);
-            logger.fine("Completed eceiving response with Downcall of type " + down.getClass().getName()); 
+            logger.fine("Completed receiving response with Downcall of type " + down.getClass().getName());
             return result; 
         } catch (org.omg.CORBA.SystemException ex) {
             processException(State.Closed, ex, false);
@@ -814,12 +761,15 @@
         //
         if (transport_.mode() != org.apache.yoko.orb.OCI.SendReceiveMode.SendOnly) {
             try {
-                synchronized (this) {
-                    if (receiverThreads_.size() > 0) {
-                        return;
+                // If the write lock is obtainable there are no receivers outstanding.
+                // We can then add a receiver, which implicitly obtains a read lock.
+                // ReentrantReadWriteLock explicitly allows downgrading a write lock to a read lock.
+                if(receiverLock.writeLock().tryLock()) {
+                    try {
+                        addReceiverThread();
+                    } finally {
+                        receiverLock.writeLock().unlock();
                     }
-
-                    addReceiverThread();
                 }
             } catch (OutOfMemoryError ex) {
                 synchronized (this) {
@@ -851,10 +801,6 @@
         }
 
         synchronized (this) {
-            //
-            // cleanup any defunct receiver threads now
-            // 
-            cleanupDeadReceiverThreads();
 
             //
             // if we can't write messages then don't bother to proceed
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPIncomingMessage.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPIncomingMessage.java
index 1c5157e..bd5cc94 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPIncomingMessage.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPIncomingMessage.java
@@ -232,8 +232,7 @@
                     org.apache.yoko.orb.OB.MinorCodes.MinorVersion,
                     org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
 
-        org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
-                buf, 0, false);
+        org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(buf, 0, false);
 
         switch (version_.minor) {
         case 0: {
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServer.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServer.java
index 13e827a..35eea22 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServer.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServer.java
@@ -17,7 +17,6 @@
 
 package org.apache.yoko.orb.OB;
 
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
 final class GIOPServer extends Server {
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarter.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarter.java
index c54a153..ccbe630 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarter.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarter.java
@@ -17,21 +17,21 @@
 
 package org.apache.yoko.orb.OB;
 
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import org.apache.yoko.orb.OCI.Acceptor;
 
-import org.apache.yoko.orb.PortableServer.*;
+import java.util.Vector;
+import java.util.logging.Logger;
 
 abstract class GIOPServerStarter {
     static final Logger logger = Logger.getLogger(GIOPServerStarter.class.getName());
     
-    protected ORBInstance orbInstance_; // The ORBInstance
+    protected final ORBInstance orbInstance_; // The ORBInstance
 
-    protected org.apache.yoko.orb.OCI.Acceptor acceptor_; // The acceptor
+    protected final Acceptor acceptor_; // The acceptor
 
-    protected OAInterface oaInterface_; // The OA interface
+    protected final OAInterface oaInterface_; // The OA interface
 
-    protected java.util.Vector connections_ = new java.util.Vector(); // Workers
+    protected final Vector connections_ = new java.util.Vector(); // Workers
 
     public static final int StateActive = 0;
 
@@ -66,8 +66,7 @@
 
     protected void reapWorkers() {
         for (int i = 0; i < connections_.size();) {
-            GIOPConnection connection = (GIOPConnection) connections_
-                    .elementAt(i);
+            GIOPConnection connection = (GIOPConnection) connections_.elementAt(i);
             if (connection.destroyed())
                 connections_.removeElementAt(i);
             else
@@ -113,11 +112,11 @@
 
     //
     // given a host/port this will search the workers of this
-    // GIOPServerStarter for a transport which matches the specific
-    // connection information. It returns null if not found.
+    // GIOPServerStarter for an inbound connection transport
+    // which matches the specific connection information.
+    // It returns null if not found.
     //
-    public synchronized GIOPConnection getWorker(
-            org.apache.yoko.orb.OCI.ConnectorInfo connInfo) {
+    public synchronized GIOPConnection getMatchingConnection(org.apache.yoko.orb.OCI.ConnectorInfo connInfo) {
         //
         // reap the workers first since we don't want to return a
         // destroyed transport
@@ -130,11 +129,14 @@
         for (int i = 0; i < connections_.size(); i++) {
             GIOPConnection worker = (GIOPConnection) connections_.elementAt(i);
 
+            // we only want to find inbound connections
+            if (worker.isOutbound())
+                continue;
+
             org.apache.yoko.orb.OCI.Transport transport = worker.transport();
 
-            if (transport != null)
-                if (transport.get_info().endpoint_alias_match(connInfo))
-                    return worker;
+            if (transport != null && transport.get_info().endpoint_alias_match(connInfo))
+                return worker;
         }
 
         // 
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarterThreaded.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarterThreaded.java
index ad6e9b7..ec4cebf 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarterThreaded.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/GIOPServerStarterThreaded.java
@@ -17,21 +17,21 @@
 
 package org.apache.yoko.orb.OB;
 
+import org.apache.yoko.orb.OCI.Acceptor;
+import org.apache.yoko.orb.OCI.Transport;
+
+import java.util.concurrent.ExecutorService;
+import java.util.logging.Level;
+
 final class GIOPServerStarterThreaded extends GIOPServerStarter {
     //
     // The starter thread
     //
-    protected final class StarterThread extends Thread {
-        private GIOPServerStarterThreaded starter_;
-
-        StarterThread(ThreadGroup group, GIOPServerStarterThreaded starter) {
-            super(group, "Yoko:Server:StarterThread");
-            starter_ = starter;
-        }
+    protected final class Starter implements Runnable {
 
         public void run() {
             try {
-                starter_.starterRun();
+                starterRun();
             } catch (RuntimeException ex) {
                 Assert._OB_assert(ex);
             }
@@ -41,71 +41,54 @@
             // Shutdown the acceptor so that no further connections are
             // accepted
             //
-            starter_.logCloseAcceptor();
-            starter_.acceptor_.shutdown();
+            logCloseAcceptor();
+            acceptor_.shutdown();
 
             //
             // Accept all connections which might have queued up in the
             // listen() backlog
-            while (true) {
-                org.apache.yoko.orb.OCI.Transport transport = null;
+            do {
 
                 try {
-                    transport = starter_.acceptor_.accept(false);
-                } catch (org.omg.CORBA.SystemException ex) {
-                }
-
-                if (transport == null) {
-                    logger.fine("Null transport received from a connect"); 
-                    break;
-                }
-
-                try {
-                    GIOPConnection connection = new GIOPConnectionThreaded(
-                            starter_.orbInstance_, transport,
-                            starter_.oaInterface_);
-
+                    Transport t = acceptor_.accept(false);
+                    if (t == null) {
+                        logger.fine("Null transport received from a connect");
+                        break;
+                    }
+                    GIOPConnection connection = new GIOPConnectionThreaded(orbInstance_, t, oaInterface_);
                     connection.setState(GIOPConnection.State.Closing);
                 } catch (org.omg.CORBA.SystemException ex) {
-                    // Ignore SystemExceptions
                 }
-            }
+            } while (true);
 
             //
             // Close the acceptor
             //
-            starter_.acceptor_.close();
+            acceptor_.close();
+            orbInstance_.getServerPhaser().arriveAndDeregister();
 
-            //
-            // Break cyclic object dependency
-            //
-            starter_ = null;
         }
     }
 
-    protected Thread starterThread_;
-
     // ----------------------------------------------------------------------
     // GIOPServerStarterThreaded package member implementation
     // ----------------------------------------------------------------------
 
-    GIOPServerStarterThreaded(ORBInstance orbInstance,
-            org.apache.yoko.orb.OCI.Acceptor acceptor, OAInterface oaInterface) {
+    GIOPServerStarterThreaded(ORBInstance orbInstance, Acceptor acceptor, OAInterface oaInterface) {
         super(orbInstance, acceptor, oaInterface);
 
         logger.fine("GIOPServer thread started " + this + " using acceptor " + acceptor); 
         try {
+            orbInstance_.getServerPhaser().register();
             //
             // Retrieve the thread group for the servers
             //
-            ThreadGroup group = orbInstance_.getServerWorkerGroup();
+            ExecutorService executor = orbInstance_.getServerExecutor();
 
             //
             // Start starter thread
             //
-            starterThread_ = new StarterThread(group, this);
-            starterThread_.setDaemon(true); 
-            starterThread_.start();
+            executor.submit(new Starter());
         } catch (OutOfMemoryError ex) {
             acceptor_.close();
             state_ = StateClosed;
@@ -192,7 +175,7 @@
     //
     // Run method for starter thread
     //
-    public void starterRun() {
+    private void starterRun() {
         while (true) {
             //
             // Get new transport, blocking
@@ -249,11 +232,13 @@
                             // StateClosing for proper connection shutdown
                             //
                             Assert._OB_assert(state_ == StateClosed);
-
+                            logger.fine("Processing an inbound connection because state is closed"); 
                             GIOPConnection connection = new GIOPConnectionThreaded(
                                     orbInstance_, transport, oaInterface_);
+                            logger.fine("Created connection " + connection); 
 
                             connection.setState(GIOPConnection.State.Closing);
+                            logger.fine("set connection state to closing"); 
                         }
                     } catch (org.omg.CORBA.SystemException ex) {
                         String msg = "can't accept connection\n" + ex.getMessage();
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORDump.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORDump.java
index 471290b..7d6a4e6 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORDump.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORDump.java
@@ -19,22 +19,21 @@
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
+import java.io.PrintWriter;
 import java.util.Properties;
 
 public class IORDump {
 
     public static String PrintObjref(org.omg.CORBA.ORB orb,
             org.omg.IOP.IOR ior) {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        PrintStream ps = new PrintStream(baos);
-        PrintObjref(orb, ps, ior);
-        ps.flush();
-        return baos.toString();
+        StringBuilder sb = new StringBuilder();
+        PrintObjref(orb, sb, ior);
+        return sb.toString();
     }
 
-    static public void PrintObjref(org.omg.CORBA.ORB orb, java.io.PrintStream out,
+    static public void PrintObjref(org.omg.CORBA.ORB orb, StringBuilder sb,
             org.omg.IOP.IOR ior) {
-        out.println("type_id: " + ior.type_id);
+        sb.append("type_id: ").append(ior.type_id).append('\n');
 
         org.apache.yoko.orb.OCI.ConFactoryRegistry conFactoryRegistry = null;
         try {
@@ -49,9 +48,9 @@
                 .get_factories();
 
         for (int i = 0; i < ior.profiles.length; i++) {
-            out.print("Profile #" + (i + 1) + ": ");
+            sb.append("Profile #" + (i + 1) + ": ");
             if (ior.profiles[i].tag == org.omg.IOP.TAG_MULTIPLE_COMPONENTS.value) {
-                out.print("multiple components");
+                sb.append("multiple components");
 
                 byte[] data = ior.profiles[i].profile_data;
                 org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
@@ -62,55 +61,55 @@
 
                 int cnt = in.read_ulong();
                 if (cnt == 0)
-                    out.println();
+                    sb.append('\n');
                 else {
                     for (int j = 0; j < cnt; j++) {
                         org.omg.IOP.TaggedComponent comp = org.omg.IOP.TaggedComponentHelper
                                 .read(in);
 
-                        String desc = IORUtil.describe_component(comp);
-                        out.println(desc);
+                        IORUtil.describe_component(comp, sb);
                     }
                 }
             } else {
                 int j;
                 for (j = 0; j < factories.length; j++) {
                     if (factories[j].tag() == ior.profiles[i].tag) {
-                        out.println(factories[j].id());
+                        sb.append(factories[j].id()).append('\n');
                         String desc = factories[j]
                                 .describe_profile(ior.profiles[i]);
-                        out.print(desc);
+                        sb.append(desc);
                         break;
                     }
                 }
 
                 if (j >= factories.length) {
-                    out.println("unknown profile tag " + ior.profiles[i].tag);
-                    out.println("profile_data: ("
-                            + ior.profiles[i].profile_data.length + ")");
-                    String data = IORUtil.dump_octets(
-                            ior.profiles[i].profile_data, 0,
-                            ior.profiles[i].profile_data.length);
-                    out.print(data); // No newline
+                    sb.append("unknown profile tag ").append(ior.profiles[i].tag).append('\n');
+                    sb.append("profile_data: (")
+                            .append(ior.profiles[i].profile_data.length ).append(")\n");
+                    IORUtil.dump_octets(
+                            ior.profiles[i].profile_data, sb);
                 }
             }
         }
     }
 
     static public void DumpIOR(org.omg.CORBA.ORB orb, String ref, boolean hasEndian) {
-        DumpIOR(orb, ref, hasEndian, System.out);
+        StringBuilder sb = new StringBuilder();
+        DumpIOR(orb, ref, hasEndian, sb);
+        PrintWriter pw = new PrintWriter(System.out);
+        pw.write(sb.toString());
+        pw.flush();
     }
 
     static public String DumpIORToString(org.omg.CORBA.ORB orb, String ref, boolean hasEndian) {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        PrintStream ps = new PrintStream(baos);
-        DumpIOR(orb, ref, hasEndian, ps);
-        return baos.toString();
+        StringBuilder sb = new StringBuilder();
+        DumpIOR(orb, ref, hasEndian, sb);
+        return sb.toString();
     }
 
-    static public void DumpIOR(org.omg.CORBA.ORB orb, String ref, boolean hasEndian, PrintStream ps) {
+    static public void DumpIOR(org.omg.CORBA.ORB orb, String ref, boolean hasEndian, StringBuilder sb) {
         if (!ref.startsWith("IOR:")) {
-            ps.println("IOR is invalid");
+            sb.append("IOR is invalid\n");
             return;
         }
 
@@ -125,15 +124,14 @@
 
         org.omg.IOP.IOR ior = org.omg.IOP.IORHelper.read(in);
 
-        ps.print("byteorder: ");
+        sb.append("byteorder: ");
         if (hasEndian)
-            ps.println((endian ? "little" : "big") + " endian");
+            sb.append((endian ? "little" : "big") + " endian\n");
         else
-            ps.println("n/a");
+            sb.append("n/a\n");
 
-        PrintObjref(orb, ps, ior);
+        PrintObjref(orb, sb, ior);
 
-        ps.flush();
     }
 
     static void usage() {
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORURLScheme_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORURLScheme_impl.java
index 54eebc4..7a88772 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORURLScheme_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORURLScheme_impl.java
@@ -72,7 +72,7 @@
             // 
             throw new org.omg.CORBA.BAD_PARAM(org.apache.yoko.orb.OB.MinorCodes
                     .describeBadParam(org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart)
-                    + ": invalid IOR", org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart,
+                    + ": invalid IOR \"" + url + "\"", org.apache.yoko.orb.OB.MinorCodes.MinorBadSchemeSpecificPart,
                     org.omg.CORBA.CompletionStatus.COMPLETED_NO);
         }
     }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORUtil.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORUtil.java
index 93f7864..9a75036 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORUtil.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/IORUtil.java
@@ -16,11 +16,28 @@
  */
 
 package org.apache.yoko.orb.OB;
+import org.omg.CSIIOP.TransportAddress;
 import org.omg.IOP.TaggedComponent;
 
 public final class IORUtil {
-    private static String describeCSISecMechList(org.omg.IOP.TaggedComponent component) {
-        String result = "";
+    public static void main(String...args) {
+        final byte[] ba = { 
+                0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+                0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+                0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f
+                };
+        
+        System.out.println("----");
+        StringBuilder sb = new StringBuilder(200);
+        for (int i = 0; i < 0x10; i++) {
+            IORUtil.dump_octets(ba, i, 0x20, sb);
+            System.out.println(sb.toString());
+            System.out.println("----");
+            sb.setLength(0);
+        }
+    }
+    
+    private static void describeCSISecMechList(org.omg.IOP.TaggedComponent component, StringBuilder sb) {
         byte[] coct = component.component_data;
         int len = component.component_data.length;
         org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
@@ -30,121 +47,114 @@
         in._OB_readEndian();
         org.omg.CSIIOP.CompoundSecMechList info = org.omg.CSIIOP.CompoundSecMechListHelper.read(in);
         
-        result += "CSI Security Mechanism List Components:\n"; 
-        result += "    stateful: " + info.stateful + "\n"; 
-        result += "    mechanism_list:\n"; 
-        for (int i = 0; i < info.mechanism_list.length; i++) {
-            org.omg.CSIIOP.CompoundSecMech mech = info.mechanism_list[i]; 
-            result += "        target_requires: " + describeTransportFlags(mech.target_requires) + "\n"; 
+        sb.append("CSI Security Mechanism List Components:\n"); 
+        sb.append("    stateful: " + info.stateful + "\n"); 
+        sb.append("    mechanism_list:\n"); 
+        for (org.omg.CSIIOP.CompoundSecMech mech: info.mechanism_list) {
+            sb.append("        target_requires: "); describeTransportFlags(mech.target_requires, sb); sb.append("\n"); 
             if (mech.transport_mech != null) {
                 if (mech.transport_mech.tag == org.omg.CSIIOP.TAG_NULL_TAG.value) {
-                    result += "            Null Transport\n"; 
+                    sb.append("            Null Transport\n"); 
                 } else if (mech.transport_mech.tag == org.omg.CSIIOP.TAG_TLS_SEC_TRANS.value) {
-                    result += describeTLS_SEC_TRANS(mech.transport_mech); 
+                    describeTLS_SEC_TRANS(mech.transport_mech, sb); 
                 } else if (mech.transport_mech.tag == org.omg.CSIIOP.TAG_SECIOP_SEC_TRANS.value) {
-                    result += describeSECIOP_SEC_TRANS(mech.transport_mech); 
+                    describeSECIOP_SEC_TRANS(mech.transport_mech, sb); 
                 }
             }
             
             if (mech.as_context_mech != null) {
-                result += "            as_context_mech:\n"; 
-                result += "                supports: " + describeTransportFlags(mech.as_context_mech.target_supports) + "\n"; 
-                result += "                requires: " + describeTransportFlags(mech.as_context_mech.target_requires) + "\n"; 
-                result += "                client_authentication_mech: " + format_octets(mech.as_context_mech.client_authentication_mech) + "\n"; 
-                result += "                target_name: " + format_octets(mech.as_context_mech.target_name) + "\n"; 
+                sb.append("            as_context_mech:\n"); 
+                sb.append("                supports: "); describeTransportFlags(mech.as_context_mech.target_supports, sb); sb.append("\n"); 
+                sb.append("                requires: "); describeTransportFlags(mech.as_context_mech.target_requires, sb); sb.append("\n"); 
+                sb.append("                client_authentication_mech: "); format_octets(mech.as_context_mech.client_authentication_mech, sb); sb.append("\n"); 
+                sb.append("                target_name: "); format_octets(mech.as_context_mech.target_name, sb); sb.append("\n"); 
             }
             
             if (mech.sas_context_mech != null) {
-                result += "            sas_context_mech:\n"; 
-                result += "                supports: " + describeTransportFlags(mech.sas_context_mech.target_supports) + "\n"; 
-                result += "                requires: " + describeTransportFlags(mech.sas_context_mech.target_requires) + "\n"; 
-                result += "                privilege_authorities:\n";
-                for (i = 0; i < mech.sas_context_mech.privilege_authorities.length; i++) {
-                    org.omg.CSIIOP.ServiceConfiguration auth = mech.sas_context_mech.privilege_authorities[i];
-                    result += "                    syntax: " + auth.syntax + "\n"; 
-                    result += "                    name: " + format_octets(auth.name) + "\n"; 
+                sb.append("            sas_context_mech:\n"); 
+                sb.append("                supports: "); describeTransportFlags(mech.sas_context_mech.target_supports, sb); sb.append("\n"); 
+                sb.append("                requires: "); describeTransportFlags(mech.sas_context_mech.target_requires, sb); sb.append("\n"); 
+                sb.append("                privilege_authorities:\n");
+                for (org.omg.CSIIOP.ServiceConfiguration auth: mech.sas_context_mech.privilege_authorities) {
+                    sb.append("                    syntax: " + auth.syntax + "\n"); 
+                    sb.append("                    name: "); format_octets(auth.name, sb); sb.append("\n"); 
                 }
-                result += "                supported_naming_mechanisms:\n";
-                for (i = 0; i < mech.sas_context_mech.supported_naming_mechanisms.length; i++) {
-                    result += "                    " + format_octets(mech.sas_context_mech.supported_naming_mechanisms[i]) + "\n"; 
+                sb.append("                supported_naming_mechanisms:\n");
+                for (byte[] namingMech: mech.sas_context_mech.supported_naming_mechanisms) {
+                    sb.append("                    "); format_octets(namingMech, sb); sb.append("\n"); 
                 }
-                result += "                supported_identity_type: " + describeIdentityToken(mech.sas_context_mech.supported_identity_types) + "\n";
+                sb.append("                supported_identity_type: "); describeIdentityToken(mech.sas_context_mech.supported_identity_types, sb); sb.append("\n");
             }
         }
-        return result; 
     }
     
     
-    private static String describeTransportFlags(int flag) {
-        String result = "";
+    private static void describeTransportFlags(int flag, StringBuilder sb) {
 
         if ((org.omg.CSIIOP.NoProtection.value & flag) != 0) {
-            result += "NoProtection ";
+            sb.append("NoProtection ");
         }
         if ((org.omg.CSIIOP.Integrity.value & flag) != 0) {
-            result += "Integrity ";
+            sb.append("Integrity ");
         }
         if ((org.omg.CSIIOP.Confidentiality.value & flag) != 0) {
-            result += "Confidentiality ";
+            sb.append("Confidentiality ");
         }
         if ((org.omg.CSIIOP.DetectReplay.value & flag) != 0) {
-            result += "DetectReplay ";
+            sb.append("DetectReplay ");
         }
         if ((org.omg.CSIIOP.DetectMisordering.value & flag) != 0) {
-            result += "DetectMisordering ";
+            sb.append("DetectMisordering ");
         }
         if ((org.omg.CSIIOP.EstablishTrustInTarget.value & flag) != 0) {
-            result += "EstablishTrustInTarget ";
+            sb.append("EstablishTrustInTarget ");
         }
         if ((org.omg.CSIIOP.EstablishTrustInClient.value & flag) != 0) {
-            result += "EstablishTrustInClient ";
+            sb.append("EstablishTrustInClient ");
         }
         if ((org.omg.CSIIOP.NoDelegation.value & flag) != 0) {
-            result += "NoDelegation ";
+            sb.append("NoDelegation ");
         }
         if ((org.omg.CSIIOP.SimpleDelegation.value & flag) != 0) {
-            result += "SimpleDelegation ";
+            sb.append("SimpleDelegation ");
         }
         if ((org.omg.CSIIOP.CompositeDelegation.value & flag) != 0) {
-            result += "CompositeDelegation ";
+            sb.append("CompositeDelegation ");
         }
         if ((org.omg.CSIIOP.IdentityAssertion.value & flag) != 0) {
-            result += "IdentityAssertion ";
+            sb.append("IdentityAssertion ");
         }
         if ((org.omg.CSIIOP.DelegationByClient.value & flag) != 0) {
-            result += "DelegationByClient ";
+            sb.append("DelegationByClient ");
         }
         
-        return result; 
     }
     
     
-    private static String describeIdentityToken(int flag) {
+    private static void describeIdentityToken(int flag, StringBuilder sb) {
         
         if (flag == org.omg.CSI.ITTAbsent.value) {
-            return "Absent"; 
+            sb.append("Absent"); 
+            return;
         }
         
-        String result = "";
 
         if ((org.omg.CSI.ITTAnonymous.value & flag) != 0) {
-            result += "Anonymous ";
+            sb.append("Anonymous ");
         }
         if ((org.omg.CSI.ITTPrincipalName.value & flag) != 0) {
-            result += "PrincipalName ";
+            sb.append("PrincipalName ");
         }
         if ((org.omg.CSI.ITTX509CertChain.value & flag) != 0) {
-            result += "X509CertChain ";
+            sb.append("X509CertChain ");
         }
         if ((org.omg.CSI.ITTDistinguishedName.value & flag) != 0) {
-            result += "DistinguishedName ";
+            sb.append("DistinguishedName ");
         }
         
-        return result; 
     }
     
-    private static String describeTLS_SEC_TRANS(org.omg.IOP.TaggedComponent component) {
-        String result = "";
+    private static void describeTLS_SEC_TRANS(org.omg.IOP.TaggedComponent component, StringBuilder sb) {
         byte[] coct = component.component_data;
         int len = component.component_data.length;
         org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
@@ -154,20 +164,18 @@
         in._OB_readEndian();
         org.omg.CSIIOP.TLS_SEC_TRANS info = org.omg.CSIIOP.TLS_SEC_TRANSHelper.read(in);
         
-        result += "        TLS_SEC_TRANS component:\n"; 
-        result += "            target_supports: " + describeTransportFlags(info.target_supports) + "\n"; 
-        result += "            target_requires: " + describeTransportFlags(info.target_requires) + "\n"; 
-        result += "            addresses:\n"; 
-        for (int i = 0; i < info.addresses.length; i++) {
-            result += "                host_name: " + info.addresses[i].host_name + "\n"; 
-            result += "                port: " + info.addresses[i].port + "\n"; 
+        sb.append("        TLS_SEC_TRANS component:\n"); 
+        sb.append("            target_supports: "); describeTransportFlags(info.target_supports, sb); sb.append("\n"); 
+        sb.append("            target_requires: "); describeTransportFlags(info.target_requires, sb); sb.append("\n"); 
+        sb.append("            addresses:\n"); 
+        for (TransportAddress address: info.addresses) {
+            sb.append("                host_name: ").append(address.host_name).append("\n"); 
+            sb.append("                port: ").append(address.port).append("\n"); 
         }
         
-        return result; 
     }
     
-    private static String describeSECIOP_SEC_TRANS(org.omg.IOP.TaggedComponent component) {
-        String result = "";
+    private static void describeSECIOP_SEC_TRANS(org.omg.IOP.TaggedComponent component, StringBuilder sb) {
         byte[] coct = component.component_data;
         int len = component.component_data.length;
         org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
@@ -177,24 +185,22 @@
         in._OB_readEndian();
         org.omg.CSIIOP.SECIOP_SEC_TRANS info = org.omg.CSIIOP.SECIOP_SEC_TRANSHelper.read(in);
         
-        result += "        SECIOP_SEC_TRANS component:\n"; 
-        result += "            target_supports: " + describeTransportFlags(info.target_supports) + "\n"; 
-        result += "            target_requires: " + describeTransportFlags(info.target_requires) + "\n"; 
-        result += "            mech_oid: " + format_octets(info.mech_oid) + "\n"; 
-        result += "            target_name: " + format_octets(info.target_name) + "\n"; 
-        result += "            addresses:\n"; 
-        for (int i = 0; i < info.addresses.length; i++) {
-            result += "                host_name: " + info.addresses[i].host_name + "\n"; 
-            result += "                port: " + info.addresses[i].port + "\n"; 
+        sb.append("        SECIOP_SEC_TRANS component:\n"); 
+        sb.append("            target_supports: "); describeTransportFlags(info.target_supports, sb); sb.append("\n"); 
+        sb.append("            target_requires: "); describeTransportFlags(info.target_requires, sb); sb.append("\n"); 
+        sb.append("            mech_oid: "); format_octets(info.mech_oid, sb); sb.append("\n"); 
+        sb.append("            target_name: "); format_octets(info.target_name, sb); sb.append("\n"); 
+        sb.append("            addresses:\n"); 
+        for (TransportAddress address: info.addresses) {
+            sb.append("                host_name: ").append(address.host_name).append("\n"); 
+            sb.append("                port: ").append(address.port).append("\n"); 
         }
         
-        return result; 
     }
     
     
     
-    private static String describeCodeSets(org.omg.IOP.TaggedComponent component) {
-        String result = "";
+    private static void describeCodeSets(org.omg.IOP.TaggedComponent component, StringBuilder sb) {
         byte[] coct = component.component_data;
         int len = component.component_data.length;
         org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
@@ -211,177 +217,217 @@
         //
         // Print char codeset information
         //
-        result += "Native char codeset: \n";
+        sb.append("Native char codeset: \n");
         charInfo = db.getCodeSetInfo(info.ForCharData.native_code_set);
         if (charInfo != null) {
-            result += "  \"";
-            result += charInfo.description;
-            result += "\"\n";
+            sb.append("  \"");
+            sb.append(charInfo.description);
+            sb.append("\"\n");
         } else if (info.ForCharData.native_code_set == 0)
-            result += "  [No codeset information]\n";
+            sb.append("  [No codeset information]\n");
         else {
-            result += "  [Unknown codeset id: ";
-            result += info.ForCharData.native_code_set;
-            result += "]\n";
+            sb.append("  [Unknown codeset id: ");
+            sb.append(info.ForCharData.native_code_set);
+            sb.append("]\n");
         }
 
         for (int i = 0; i < info.ForCharData.conversion_code_sets.length; i++) {
             if (i == 0)
-                result += "Char conversion codesets:\n";
+                sb.append("Char conversion codesets:\n");
 
             charInfo = db
                     .getCodeSetInfo(info.ForCharData.conversion_code_sets[i]);
             if (charInfo != null) {
-                result += "  \"";
-                result += charInfo.description;
-                result += "\"\n";
+                sb.append("  \"");
+                sb.append(charInfo.description);
+                sb.append("\"\n");
             } else {
-                result += "  [Unknown codeset id: ";
-                result += info.ForCharData.conversion_code_sets[i];
-                result += "]\n";
+                sb.append("  [Unknown codeset id: ");
+                sb.append(info.ForCharData.conversion_code_sets[i]);
+                sb.append("]\n");
             }
         }
 
         //
         // Print wchar codeset information
         //
-        result += "Native wchar codeset: \n";
+        sb.append("Native wchar codeset: \n");
         charInfo = db.getCodeSetInfo(info.ForWcharData.native_code_set);
         if (charInfo != null) {
-            result += "  \"";
-            result += charInfo.description;
-            result += "\"\n";
+            sb.append("  \"");
+            sb.append(charInfo.description);
+            sb.append("\"\n");
         } else if (info.ForWcharData.native_code_set == 0)
-            result += "  [No codeset information]\n";
+            sb.append("  [No codeset information]\n");
         else {
-            result += "  [Unknown codeset id: ";
-            result += info.ForWcharData.native_code_set;
-            result += "]\n";
+            sb.append("  [Unknown codeset id: ");
+            sb.append(info.ForWcharData.native_code_set);
+            sb.append("]\n");
         }
 
         for (int i = 0; i < info.ForWcharData.conversion_code_sets.length; i++) {
             if (i == 0)
-                result += "Wchar conversion codesets:\n";
+                sb.append("Wchar conversion codesets:\n");
 
             charInfo = db
                     .getCodeSetInfo(info.ForWcharData.conversion_code_sets[i]);
             if (charInfo != null) {
-                result += "  \"";
-                result += charInfo.description;
-                result += "\"\n";
+                sb.append("  \"");
+                sb.append(charInfo.description);
+                sb.append("\"\n");
             } else {
-                result += "  [Unknown codeset id: ";
-                result += info.ForWcharData.conversion_code_sets[i];
-                result += "]\n";
+                sb.append("  [Unknown codeset id: ");
+                sb.append(info.ForWcharData.conversion_code_sets[i]);
+                sb.append("]\n");
             }
         }
 
-        return result;
     }
 
-    private static String describeGenericComponent(
-            org.omg.IOP.TaggedComponent component, String name) {
-        String result = "Component: ";
-        result += name;
-        result += '\n';
-        result += "Component data: (";
-        result += component.component_data.length;
-        result += ")\n";
-        String data = dump_octets(component.component_data, 0,
-                component.component_data.length);
-        result += data;
-        return result;
+    private static void describeGenericComponent(
+            org.omg.IOP.TaggedComponent component, String name, StringBuilder sb) {
+        sb.append("Component: ");
+        sb.append(name);
+        sb.append('\n');
+        sb.append("Component data: (");
+        sb.append(component.component_data.length);
+        sb.append(")\n");
+        dump_octets(component.component_data, 0,
+                component.component_data.length, sb);
     }
 
     //
     // Convert an octet buffer into human-friendly data dump
     //
     public static String dump_octets(byte[] oct) {
-        return dump_octets(oct, 0, oct.length); 
+        StringBuilder sb = new StringBuilder();
+        dump_octets(oct, 0, oct.length, sb); 
+        return sb.toString();
+    }
+     
+    public static void dump_octets(byte[] oct, StringBuilder sb) {
+         dump_octets(oct, 0, oct.length, sb); 
     }
 
+    private static final char[] HEX_DIGIT = "0123456789abcdef".toCharArray();
+    private static final int PRINTABLE_CHAR_LOW = 31;
+    private static final int PRINTABLE_CHAR_HIGH = 127;
     //
     // Convert an octet buffer into human-friendly data dump
     //
-    public static String dump_octets(byte[] oct, int offset, int count) {
-        final int inc = 16;
+    public static void dump_octets(final byte[] oct, final int offset, final int count, final StringBuilder sb) {
+        if (count <= 0) {
+            return; 
+        }
+
+        final StringBuilder ascii = new StringBuilder(18);
+        switch (offset%0x10) {
+            case 0:
+                break;
+            case 0xf: sb.append("  ");  ascii.append(" ");
+            case 0xe: sb.append("  ");  ascii.append(" ");
+            case 0xd: sb.append("  ");  ascii.append(" ");
+            case 0xc: sb.append("   "); ascii.append(" ");
+            case 0xb: sb.append("  ");  ascii.append(" ");
+            case 0xa: sb.append("  ");  ascii.append(" ");
+            case 0x9: sb.append("  ");  ascii.append(" ");
+            case 0x8: sb.append("   "); ascii.append(" ");
+            case 0x7: sb.append("  ");  ascii.append(" ");
+            case 0x6: sb.append("  ");  ascii.append(" ");
+            case 0x5: sb.append("  ");  ascii.append(" ");
+            case 0x4: sb.append("   "); ascii.append(" ");
+            case 0x3: sb.append("  ");  ascii.append(" ");
+            case 0x2: sb.append("  ");  ascii.append(" ");
+            case 0x1: sb.append("  ");  ascii.append(" ");
+        }
         
-        if (count <= 0) {
-            return ""; 
-        }
-
-        StringBuffer result = new StringBuffer(count * 8);
-
-        for (int i = offset; i < offset + count; i += inc) {
-            for (int j = i; j - i < inc; j++) {
-                if (j < offset + count) {
-                    int n = ((int) oct[j]) & 0xff;
-                    String hex = Integer.toHexString(n); 
-                    if (hex.length() == 1) {
-                        result.append('0'); 
+        ascii.append(" \"");
+        
+        for (int i = offset; i < (offset + count); i++) {
+            final int b = oct[i] & 0xff;
+            
+            // build up the ascii string for the end of the line
+            ascii.append((PRINTABLE_CHAR_LOW < b && b < PRINTABLE_CHAR_HIGH)? (char)b : '.');
+            
+            // print the high hex nybble
+            sb.append(HEX_DIGIT[b>>4]);
+            // and the low hex nybble
+            sb.append(HEX_DIGIT[b&0xf]);
+            
+            if (i%0x4 == (0x4-1)) {
+                // space the columns on every 4-byte boundary
+                sb.append(' ');
+                if (i%0x10 == (0x10-1)) {
+                    // write the ascii interpretation on the end of every line
+                    sb.append(ascii).append("\"\n");
+                    ascii.setLength(0);
+                    ascii.append(" \"");
+                    if (i%0x100 == (0x100-1)) {
+                        // separating line every 0x100 bytes
+                        //         00000000 00000000 00000000 00000000  "................"
+                        sb.append("-----------------------------------\n");
                     }
-                    result.append(hex); 
-                    result.append(' ');
-                } else {
-                    result.append("   ");
                 }
             }
-
-            result.append('"');
-
-            for (int j = i; j < offset + count && j - i < inc; j++) {
-                if (oct[j] >= (byte) 32 && oct[j] < (byte) 127) {
-                    result.append((char) oct[j]);
-                }
-                else {
-                    result.append('.');
-                }
-            }
-            result.append('"');
-            result.append('\n');
         }
-        return result.toString();
+        
+        switch ((offset+count)%0x10) {
+            case 0:
+                break;
+            case 0x1: sb.append("  ");
+            case 0x2: sb.append("  ");
+            case 0x3: sb.append("   ");
+            case 0x4: sb.append("  ");
+            case 0x5: sb.append("  ");
+            case 0x6: sb.append("  ");
+            case 0x7: sb.append("   ");
+            case 0x8: sb.append("  ");
+            case 0x9: sb.append("  ");
+            case 0xa: sb.append("  ");
+            case 0xb: sb.append("   ");
+            case 0xc: sb.append("  ");
+            case 0xd: sb.append("  ");
+            case 0xe: sb.append("  ");
+            case 0xf: sb.append("   ").append(ascii).append("\"\n");
+        }
     }
 
     //
     // Convert an octet buffer into a single-line readable data dump. 
     //
-    public static String format_octets(byte[] oct) {
-        return format_octets(oct, 0, oct.length); 
+    public static void format_octets(byte[] oct, StringBuilder sb) {
+        format_octets(oct, 0, oct.length, sb); 
     }
 
     //
     // Convert an octet buffer into a single-line readable data dump. 
     //
-    public static String format_octets(byte[] oct, int offset, int count) {
+    public static void format_octets(byte[] oct, int offset, int count, StringBuilder sb) {
         if (count <= 0) {
-            return ""; 
+            return; 
         }
 
-        StringBuffer result = new StringBuffer(count * 8);
-        result.append('"'); 
+        sb.append('"'); 
 
         for (int i = offset; i < offset + count; i++) {
             int n = (int) oct[i] & 0xff;
             if (n >= 32 && n <= 127) {
-                result.append((char)n); 
+                sb.append((char)n); 
             }
             else {
-                result.append('?'); 
+                sb.append('?'); 
             }
         }
 
-        result.append('"'); 
+        sb.append('"'); 
 
-        return result.toString();
     }
 
     //
     // Produce a human-friendly description of an IOR tagged component
     //
-    public static String describe_component(
-            org.omg.IOP.TaggedComponent component) {
-        String result;
+    public static void describe_component(
+            org.omg.IOP.TaggedComponent component, StringBuilder sb) {
 
         switch (component.tag) {
         case org.omg.IOP.TAG_ORB_TYPE.value: {
@@ -393,19 +439,19 @@
                     buf, 0, false);
             in._OB_readEndian();
             int id = in.read_ulong();
-            result = "Component: TAG_ORB_TYPE = ";
-            result += "0x";
-            result += Integer.toHexString(id);
-            result += '\n';
+            sb.append("Component: TAG_ORB_TYPE = ");
+            sb.append("0x");
+            sb.append(Integer.toHexString(id));
+            sb.append('\n');
             break;
         }
 
         case org.omg.IOP.TAG_CODE_SETS.value:
-            result = describeCodeSets(component);
+            describeCodeSets(component, sb);
             break;
 
         case org.omg.IOP.TAG_POLICIES.value:
-            result = describeGenericComponent(component, "TAG_POLICIES");
+            describeGenericComponent(component, "TAG_POLICIES", sb);
             break;
 
         case org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS.value: {
@@ -418,88 +464,88 @@
             in._OB_readEndian();
             String host = in.read_string();
             short port = in.read_ushort();
-            result = "Alternate IIOP address:\n";
-            result += "  host: ";
-            result += host;
-            result += '\n';
-            result += "  port: ";
-            result += (port < 0 ? 0xffff + (int) port + 1 : port);
-            result += '\n';
+            sb.append("Alternate IIOP address:\n");
+            sb.append("  host: ");
+            sb.append(host);
+            sb.append('\n');
+            sb.append("  port: ");
+            sb.append(port < 0 ? 0xffff + (int) port + 1 : port);
+            sb.append('\n');
             break;
         }
 
         case org.omg.IOP.TAG_ASSOCIATION_OPTIONS.value:
-            result = describeGenericComponent(component,
-                    "TAG_ASSOCIATION_OPTIONS");
+            describeGenericComponent(component,
+                    "TAG_ASSOCIATION_OPTIONS", sb);
             break;
 
         case org.omg.IOP.TAG_SEC_NAME.value:
-            result = describeGenericComponent(component, "TAG_SEC_NAME");
+            describeGenericComponent(component, "TAG_SEC_NAME", sb);
             break;
 
         case org.omg.IOP.TAG_SPKM_1_SEC_MECH.value:
-            result = describeGenericComponent(component, "TAG_SPKM_1_SEC_MECH");
+            describeGenericComponent(component, "TAG_SPKM_1_SEC_MECH", sb);
             break;
 
         case org.omg.IOP.TAG_SPKM_2_SEC_MECH.value:
-            result = describeGenericComponent(component, "TAG_SPKM_2_SEC_MECH");
+            describeGenericComponent(component, "TAG_SPKM_2_SEC_MECH", sb);
             break;
 
         case org.omg.IOP.TAG_KerberosV5_SEC_MECH.value:
-            result = describeGenericComponent(component,
-                    "TAG_KerberosV5_SEC_MECH");
+            describeGenericComponent(component,
+                    "TAG_KerberosV5_SEC_MECH", sb);
             break;
 
         case org.omg.IOP.TAG_CSI_ECMA_Secret_SEC_MECH.value:
-            result = describeGenericComponent(component,
-                    "TAG_CSI_ECMA_Secret_SEC_MECH");
+            describeGenericComponent(component,
+                    "TAG_CSI_ECMA_Secret_SEC_MECH", sb);
             break;
 
         case org.omg.IOP.TAG_CSI_ECMA_Hybrid_SEC_MECH.value:
-            result = describeGenericComponent(component,
-                    "TAG_CSI_ECMA_Hybrid_SEC_MECH");
+            describeGenericComponent(component,
+                    "TAG_CSI_ECMA_Hybrid_SEC_MECH", sb);
             break;
 
         case org.omg.IOP.TAG_CSI_SEC_MECH_LIST.value:
-            result = describeCSISecMechList(component);
+            describeCSISecMechList(component, sb);
             break;
 
         case org.omg.IOP.TAG_OTS_POLICY.value:
-            result = describeGenericComponent(component,
-                    "TAG_OTS_POLICY");
+            describeGenericComponent(component,
+                    "TAG_OTS_POLICY", sb);
             break;
 
         case org.omg.CosTSInteroperation.TAG_INV_POLICY.value:
-            result = describeGenericComponent(component,
-                    "TAG_INV_POLICY");
+            describeGenericComponent(component,
+                    "TAG_INV_POLICY", sb);
             break;
 
         case org.omg.CSIIOP.TAG_SECIOP_SEC_TRANS.value:
-            result = describeGenericComponent(component,
-                    "TAG_SECIOP_SEC_TRANS");
+            describeGenericComponent(component,
+                    "TAG_SECIOP_SEC_TRANS", sb);
             break;
 
         case org.omg.CSIIOP.TAG_NULL_TAG.value:
-            result = describeGenericComponent(component,
-                    "TAG_NULL_TAG");
+            describeGenericComponent(component,
+                    "TAG_NULL_TAG", sb);
             break;
 
         case org.omg.CSIIOP.TAG_TLS_SEC_TRANS.value:
-            result = describeGenericComponent(component,
-                    "TAG_TLS_SEC_TRANS");
+            describeGenericComponent(component,
+                    "TAG_TLS_SEC_TRANS", sb);
             break;
 
         case org.omg.IOP.TAG_SSL_SEC_TRANS.value:
-            result = describeGenericComponent(component, "TAG_SSL_SEC_TRANS");
+            describeGenericComponent(component, "TAG_SSL_SEC_TRANS", sb);
             break;
 
         case org.omg.IOP.TAG_CSI_ECMA_Public_SEC_MECH.value:
-            result = describeGenericComponent(component,
-                    "TAG_CSI_ECMA_Public_SEC_MECH");
+            describeGenericComponent(component,
+                    "TAG_CSI_ECMA_Public_SEC_MECH", sb);
             break;
 
         case org.omg.IOP.TAG_GENERIC_SEC_MECH.value:
-            result = describeGenericComponent(component, "TAG_GENERIC_SEC_MECH");
+            describeGenericComponent(component, "TAG_GENERIC_SEC_MECH", sb);
             break;
 
         case org.omg.IOP.TAG_JAVA_CODEBASE.value: {
@@ -511,52 +557,51 @@
                     buf, 0, false);
             in._OB_readEndian();
             String codebase = in.read_string();
-            result = "Component: TAG_JAVA_CODEBASE = `";
-            result += codebase;
-            result += "'\n";
+            sb.append("Component: TAG_JAVA_CODEBASE = `");
+            sb.append(codebase);
+            sb.append("'\n");
             break;
         }
 
         case org.omg.IOP.TAG_COMPLETE_OBJECT_KEY.value:
-            result = describeGenericComponent(component,
-                    "TAG_COMPLETE_OBJECT_KEY");
+            describeGenericComponent(component,
+                    "TAG_COMPLETE_OBJECT_KEY", sb);
             break;
 
         case org.omg.IOP.TAG_ENDPOINT_ID_POSITION.value:
-            result = describeGenericComponent(component,
-                    "TAG_ENDPOINT_ID_POSITION");
+            describeGenericComponent(component,
+                    "TAG_ENDPOINT_ID_POSITION", sb);
             break;
 
         case org.omg.IOP.TAG_LOCATION_POLICY.value:
-            result = describeGenericComponent(component, "TAG_LOCATION_POLICY");
+            describeGenericComponent(component, "TAG_LOCATION_POLICY", sb);
             break;
 
         case org.omg.IOP.TAG_DCE_STRING_BINDING.value:
-            result = describeGenericComponent(component,
-                    "TAG_DCE_STRING_BINDING");
+            describeGenericComponent(component,
+                    "TAG_DCE_STRING_BINDING", sb);
             break;
 
         case org.omg.IOP.TAG_DCE_BINDING_NAME.value:
-            result = describeGenericComponent(component, "TAG_DCE_BINDING_NAME");
+            describeGenericComponent(component, "TAG_DCE_BINDING_NAME", sb);
             break;
 
         case org.omg.IOP.TAG_DCE_NO_PIPES.value:
-            result = describeGenericComponent(component, "TAG_DCE_NO_PIPES");
+            describeGenericComponent(component, "TAG_DCE_NO_PIPES", sb);
             break;
 
         case org.omg.IOP.TAG_DCE_SEC_MECH.value:
-            result = describeGenericComponent(component, "TAG_DCE_SEC_MECH");
+            describeGenericComponent(component, "TAG_DCE_SEC_MECH", sb);
             break;
 
         default: {
             String name = "unknown (tag = ";
             name += component.tag;
             name += ")";
-            result = describeGenericComponent(component, name);
+            describeGenericComponent(component, name, sb);
             break;
         }
         }
 
-        return result;
     }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/OB_Extras.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/OB_Extras.java
index 76d5bcb..478196d 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/OB_Extras.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/OB_Extras.java
@@ -17,6 +17,10 @@
 
 package org.apache.yoko.orb.OB;
 
+import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_0;
+
+import org.apache.yoko.orb.OCI.GiopVersion;
+
 public interface OB_Extras {
     //
     // Whether or not we are building a server capable of the
@@ -27,5 +31,5 @@
     //
     // the default GIOP Version to set for the streams
     //
-    public final int DEFAULT_GIOP_VERSION = 0x0100;
+    public final GiopVersion DEFAULT_GIOP_VERSION = GIOP1_0;
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBControl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBControl.java
index fedc7a3..3a0ae1a 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBControl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBControl.java
@@ -1,10 +1,10 @@
 /*
  *  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
+ *  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
  *
@@ -17,7 +17,28 @@
 
 package org.apache.yoko.orb.OB;
 
-import org.apache.yoko.orb.OB.DispatchStrategyFactory;
+import static org.apache.yoko.orb.OB.MinorCodes.MinorDestroyWouldBlock;
+import static org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed;
+import static org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled;
+import static org.apache.yoko.orb.OB.MinorCodes.describeBadInvOrder;
+import static org.apache.yoko.orb.OB.MinorCodes.describeInitialize;
+import static org.omg.CORBA.CompletionStatus.COMPLETED_NO;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Phaser;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.ReadWriteLock;
+
+import org.apache.yoko.orb.OBPortableServer.POAManagerFactory_impl;
+import org.apache.yoko.orb.OBPortableServer.POA_impl;
+import org.apache.yoko.orb.PortableServer.Current_impl;
+import org.omg.CORBA.BAD_INV_ORDER;
+import org.omg.CORBA.INITIALIZE;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.CurrentPackage.NoContext;
 
 public final class ORBControl {
     //
@@ -28,38 +49,27 @@
     //
     // The ORBControl state
     //
-    private final static int StateNotRunning = 0;
-
-    private final static int StateRunning = 1;
-
-    private final static int StateServerShutdown = 2;
-
-    private final static int StateClientShutdown = 3;
-
-    private final static int StateDestroyed = 4;
-
-    private int state_; // State of the ORB
+    private enum State { NOT_RUNNING, RUNNING, SERVER_SHUTDOWN, CLIENT_SHUTDOWN, DESTROYED };
+    private volatile State state; // State of the ORB
 
     //
     // Has shutdown been called?
     //
-    private boolean shutdown_;
-
-    //
-    // Condition variable used to block until the server has been shutdown
-    //
-    private java.lang.Object shutdownCond_ = new java.lang.Object();
+    private final CountDownLatch shutdown = new CountDownLatch(1);
 
     //
     // The Root POA
     //
-    private org.omg.PortableServer.POA rootPOA_; // The Root POA
+    private POA rootPOA_; // The Root POA
 
     //
     // The thread id of the main thread (that is the first thread that
     // calls run, perform_work or work_pending)
     //
-    private Thread mainThread_;
+    private volatile Thread mainThread_;
+
+    private long shutdownTimeout_ = 2;//seconds
+
 
     // ----------------------------------------------------------------------
     // ORBControl private and protected member implementations
@@ -73,26 +83,21 @@
         // If the shutdown_ is false, or the server side has already
         // shutdown then do nothing
         //
-        if (!shutdown_ || state_ == StateServerShutdown)
+        if (shutdown.getCount() != 0 || state == State.SERVER_SHUTDOWN)
             return;
 
-        Assert._OB_assert(state_ != StateClientShutdown
-                && state_ != StateDestroyed);
+        Assert._OB_assert(state != State.CLIENT_SHUTDOWN && state != State.DESTROYED);
 
         //
         // If run was called then only the main thread may complete the
         // shutdown
         //
-        Assert._OB_assert(state_ == StateNotRunning
-                || mainThread_ == Thread.currentThread());
+        Assert._OB_assert(state == State.NOT_RUNNING || mainThread_ == Thread.currentThread());
 
         //
         // Get the POAManagerFactory implementation
         //
-        org.apache.yoko.orb.OBPortableServer.POAManagerFactory pmFactory = orbInstance_
-                .getPOAManagerFactory();
-
-        org.apache.yoko.orb.OBPortableServer.POAManagerFactory_impl factory = (org.apache.yoko.orb.OBPortableServer.POAManagerFactory_impl) pmFactory;
+        POAManagerFactory_impl factory = (POAManagerFactory_impl) orbInstance_.getPOAManagerFactory();
 
         //
         // Deactivate all of the POAManagers
@@ -103,68 +108,39 @@
         // Wait for all the threads in the server worker group to
         // terminate
         //
-        ThreadGroup group = orbInstance_.getServerWorkerGroup();
-        synchronized (group) {
-            int timeOuts = 0; 
+        waitForServerThreads();
+        notifyAll();
+    }
 
-            // it's possible that a thread will get stalled in a read(), which seems 
-            // to happen most often with SSLSockets.  We'll do some retry loops here 
-            // and interrupt any threads that seem to be taking an excessively long time 
-            // to clean up. 
-            int count = group.activeCount();
-            while (count > 0) {
-                try {
-                    group.wait(200);
-                } catch (InterruptedException ex) {
-                }
-                int newCount = group.activeCount();
-                // we woke up because of a timeout.  
-                if (newCount == count) {
-                    timeOuts++; 
-                    // after 2 timeouts, interrupt any remaining threads in the 
-                    // group. 
-                    if (timeOuts == 2) {
-                        group.interrupt(); 
-                    }
-                    // we've waited a full second, and we still have active threads. 
-                    // time to give up waiting. 
-                    if (timeOuts >= 5) {
-                        break;
-                    }
-                }
-                count = newCount; 
-            }
+    private void waitForServerThreads() {
+        shutdownExecutor(orbInstance_.getServerPhaser(), orbInstance_.getServerExecutor());
 
-            //
-            // Get the DispatchStrategyFactory implementation and
-            // destroy it. It must be destroyed here so that the
-            // thread pools get destroyed before OCI::Current_impl
-            // gets destroyed by the destruction of the Root
-            // POA. Otherwise, thread specific data for the thread
-            // pool threads will not get released.
-            //
-            DispatchStrategyFactory dsFactory = orbInstance_
-                    .getDispatchStrategyFactory();
+        //
+        // Get the DispatchStrategyFactory implementation and
+        // destroy it. It must be destroyed here so that the
+        // thread pools get destroyed before OCI::Current_impl
+        // gets destroyed by the destruction of the Root
+        // POA. Otherwise, thread specific data for the thread
+        // pool threads will not get released.
+        //
+        DispatchStrategyFactory dsFactory = orbInstance_.getDispatchStrategyFactory();
 
-            DispatchStrategyFactory_impl dsFactoryImpl = (DispatchStrategyFactory_impl) dsFactory;
+        DispatchStrategyFactory_impl dsFactoryImpl = (DispatchStrategyFactory_impl) dsFactory;
 
-            dsFactoryImpl._OB_destroy();
+        dsFactoryImpl._OB_destroy();
 
-            //
-            // Mark the server side state as shutdown and notify any
-            // waiting threads
-            //
-            state_ = StateServerShutdown;
+        //
+        // Mark the server side state as shutdown and notify any
+        // waiting threads
+        //
+        state = State.SERVER_SHUTDOWN;
 
-            //
-            // Destroy the root POA
-            //
-            if (rootPOA_ != null) {
-                rootPOA_.destroy(true, true);
-                rootPOA_ = null;
-            }
-
-            notifyAll();
+        //
+        // Destroy the root POA
+        //
+        if (rootPOA_ != null) {
+            rootPOA_.destroy(true, true);
+            rootPOA_ = null;
         }
     }
 
@@ -176,28 +152,26 @@
         // The ORB destroys this object, so it's an initialization
         // error if the this operation is called after ORB destruction
         //
-        if (state_ == StateDestroyed)
-            throw new org.omg.CORBA.INITIALIZE(org.apache.yoko.orb.OB.MinorCodes
-                    .describeInitialize(org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+        if (state == State.DESTROYED)
+            throw new org.omg.CORBA.INITIALIZE(
+                    org.apache.yoko.orb.OB.MinorCodes.describeInitialize(org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-        if (state_ == StateServerShutdown || state_ == StateClientShutdown)
-            throw new org.omg.CORBA.BAD_INV_ORDER(org.apache.yoko.orb.OB.MinorCodes
-                    .describeBadInvOrder(org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+        if (state == State.SERVER_SHUTDOWN || state == State.CLIENT_SHUTDOWN)
+            throw new org.omg.CORBA.BAD_INV_ORDER(
+                    org.apache.yoko.orb.OB.MinorCodes.describeBadInvOrder(org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
-        if (state_ == StateNotRunning) {
+        if (state == State.NOT_RUNNING) {
             //
             // Remember the main thread id
             //
             mainThread_ = Thread.currentThread();
 
             //
-            // Set the state to StateRunning
+            // Set the state to State.RUNNING
             //
-            state_ = StateRunning;
+            state = State.RUNNING;
         }
     }
 
@@ -207,7 +181,7 @@
         // side shutting down or the state being destroyed also
         // implies that the server side has shutdown
         //
-        while (state_ == StateRunning) {
+        while (state == State.RUNNING) {
             try {
                 wait();
             } catch (InterruptedException ex) {
@@ -220,8 +194,7 @@
     // ----------------------------------------------------------------------
 
     public ORBControl() {
-        state_ = StateNotRunning;
-        shutdown_ = false;
+        state = State.NOT_RUNNING;
     }
 
     //
@@ -232,8 +205,8 @@
         // destroy() may not be called unless the client side has been
         // shutdown
         //
-        Assert._OB_assert(state_ == StateClientShutdown);
-        state_ = StateDestroyed;
+        Assert._OB_assert(state == State.CLIENT_SHUTDOWN);
+        state = State.DESTROYED;
 
         //
         // Set the ORBInstance object to nil
@@ -266,10 +239,7 @@
         // ServerShutdown, ClientShutdown or Destroyed. Therefore if
         // shutdown_ is true, then a server side shutdown is pending.
         //
-        if (shutdown_)
-            return true;
-
-        return false;
+        return (shutdown.getCount() == 0);
     }
 
     //
@@ -308,7 +278,7 @@
         // shutdown_ is true, then a server side shutdown is pending
         // so complete it now.
         //
-        if (shutdown_) {
+        if (shutdown.getCount() == 0) {
             completeServerShutdown();
             return;
         }
@@ -319,11 +289,9 @@
         // implies that the server side has shutdown
         //
         do {
-            synchronized (shutdownCond_) {
-                try {
-                    shutdownCond_.wait();
-                } catch (InterruptedException ex) {
-                }
+            try {
+                shutdown.await();
+            } catch (InterruptedException ignored) {
             }
 
             //
@@ -331,7 +299,7 @@
             // Running
             //
             completeServerShutdown();
-        } while (state_ == StateRunning);
+        } while (state == State.RUNNING);
     }
 
     //
@@ -344,17 +312,11 @@
         // The ORB destroys this object, so it's an initialization error
         // if the this operation is called after ORB destruction
         //
-        if (state_ == StateDestroyed)
-            throw new org.omg.CORBA.INITIALIZE(org.apache.yoko.orb.OB.MinorCodes
-                    .describeInitialize(org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+        if (state == State.DESTROYED)
+            throw new INITIALIZE(describeInitialize(MinorORBDestroyed), MinorORBDestroyed, COMPLETED_NO);
 
-        if (state_ == StateServerShutdown || state_ == StateClientShutdown)
-            throw new org.omg.CORBA.BAD_INV_ORDER(org.apache.yoko.orb.OB.MinorCodes
-                    .describeBadInvOrder(org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorShutdownCalled,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+        if (state == State.SERVER_SHUTDOWN || state == State.CLIENT_SHUTDOWN)
+            throw new BAD_INV_ORDER(describeBadInvOrder(MinorShutdownCalled), MinorShutdownCalled, COMPLETED_NO);
 
         //
         // If waitForCompletion is true then find out whether we're inside
@@ -363,11 +325,9 @@
         if (waitForCompletion) {
             boolean inInvocation = false;
             try {
-                InitialServiceManager initialServiceManager = orbInstance_
-                        .getInitialServiceManager();
-                org.omg.CORBA.Object o = initialServiceManager
-                        .resolveInitialReferences("POACurrent");
-                org.apache.yoko.orb.PortableServer.Current_impl current = (org.apache.yoko.orb.PortableServer.Current_impl) o;
+                InitialServiceManager initialServiceManager = orbInstance_.getInitialServiceManager();
+                org.omg.CORBA.Object o = initialServiceManager.resolveInitialReferences("POACurrent");
+                Current_impl current = (Current_impl) o;
                 inInvocation = current._OB_inUpcall();
                 if (inInvocation) {
                     //
@@ -375,35 +335,26 @@
                     // POAManager's ORB or another ORB.
                     //
                     try {
-                        org.apache.yoko.orb.OBPortableServer.POA_impl p = (org.apache.yoko.orb.OBPortableServer.POA_impl) current
-                                .get_POA();
+                        POA_impl p = (POA_impl) current.get_POA();
                         inInvocation = (p._OB_ORBInstance() == orbInstance_);
-                    } catch (org.omg.PortableServer.CurrentPackage.NoContext ex) {
+                    } catch (NoContext ex) {
                     }
                 }
             } catch (ClassCastException ex) {
-            } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
+            } catch (InvalidName ex) {
             }
 
             if (inInvocation)
-                throw new org.omg.CORBA.BAD_INV_ORDER(
-                        MinorCodes
-                                .describeBadInvOrder(org.apache.yoko.orb.OB.MinorCodes.MinorDestroyWouldBlock),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorDestroyWouldBlock,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                throw new BAD_INV_ORDER(describeBadInvOrder(MinorDestroyWouldBlock), MinorDestroyWouldBlock, COMPLETED_NO);
         }
 
-        shutdown_ = true;
-
         //
         // Unblock run(). This should be done immediately before
         // the return since this can cause the main loop to wake and
         // complete the shutdown (thus, for instance, destroying the
         // POAManagerFactory).
         //
-        synchronized (shutdownCond_) {
-            shutdownCond_.notifyAll();
-        }
+        shutdown.countDown();
 
         //
         // waitForCompletion false? We're done.
@@ -416,7 +367,7 @@
         // waitForCompletion is true then wait for the shutdown to
         // complete.
         //
-        if (state_ == StateRunning && mainThread_ != Thread.currentThread()) {
+        if (state == State.RUNNING && mainThread_ != Thread.currentThread()) {
             blockServerShutdownComplete();
             return;
         }
@@ -435,29 +386,28 @@
         // The ORB destroys this object, so it's an initialization
         // error if the this operation is called after ORB destruction
         //
-        if (state_ == StateDestroyed)
-            throw new org.omg.CORBA.INITIALIZE(org.apache.yoko.orb.OB.MinorCodes
-                    .describeInitialize(org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+        if (state == State.DESTROYED)
+            throw new org.omg.CORBA.INITIALIZE(
+                    org.apache.yoko.orb.OB.MinorCodes.describeInitialize(org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed),
+                    org.apache.yoko.orb.OB.MinorCodes.MinorORBDestroyed, org.omg.CORBA.CompletionStatus.COMPLETED_NO);
 
         //
         // If the ORB client side is already shutdown, then we're done
         //
-        if (state_ == StateClientShutdown)
+        if (state == State.CLIENT_SHUTDOWN)
             return;
 
         if (orbInstance_ != null) {
             //
             // First shutdown the server side, if necessary
             //
-            if (state_ != StateServerShutdown)
+            if (state != State.SERVER_SHUTDOWN)
                 shutdownServer(true);
 
             //
             // The server shutdown must have completed
             //
-            Assert._OB_assert(state_ == StateServerShutdown);
+            Assert._OB_assert(state == State.SERVER_SHUTDOWN);
 
             //
             // Shutdown the client side. Continue to dispatch events until all
@@ -470,25 +420,31 @@
             // Wait for all the threads in the client worker group to
             // terminate
             //
-            ThreadGroup group = orbInstance_.getClientWorkerGroup();
-            synchronized (group) {
-                while (group.activeCount() > 0) {
-                    try {
-                        group.wait();
-                    } catch (InterruptedException ex) {
-                    }
-                }
-            }
+            shutdownExecutor(orbInstance_.getClientPhaser(), orbInstance_.getClientExecutor());
         }
 
         //
         // Mark the ORB's client side as shutdown and notify any
         // waiters
         //
-        state_ = StateClientShutdown;
+        state = State.CLIENT_SHUTDOWN;
         notifyAll();
     }
 
+    private void shutdownExecutor(Phaser phaser, ExecutorService executor) {
+        int phase = phaser.arrive();//release the system's "lock"
+        //phaser advances after all GIOPConnectionThreaded have shut down (gracefully or abort)
+        try {
+            phaser.awaitAdvanceInterruptibly(phase, shutdownTimeout_, TimeUnit.SECONDS);
+        } catch (InterruptedException e1) {
+            Thread.currentThread().interrupt();
+        } catch (TimeoutException e) {
+        } finally {
+            phaser.forceTermination();
+        }
+        executor.shutdownNow();
+    }
+
     //
     // Initialize the Root POA
     //
@@ -511,8 +467,7 @@
         //
         org.apache.yoko.orb.OBPortableServer.POAManagerFactory factory = null;
         try {
-            factory = org.apache.yoko.orb.OBPortableServer.POAManagerFactoryHelper
-                    .narrow(ism.resolveInitialReferences("POAManagerFactory"));
+            factory = org.apache.yoko.orb.OBPortableServer.POAManagerFactoryHelper.narrow(ism.resolveInitialReferences("POAManagerFactory"));
         } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
             Assert._OB_assert(ex);
         }
@@ -536,8 +491,7 @@
         if (manager == null) {
             try {
                 org.omg.CORBA.Policy[] emptyPl = new org.omg.CORBA.Policy[0];
-                manager = (org.apache.yoko.orb.OBPortableServer.POAManager) (factory
-                        .create_POAManager("RootPOAManager", emptyPl));
+                manager = (org.apache.yoko.orb.OBPortableServer.POAManager) (factory.create_POAManager("RootPOAManager", emptyPl));
             } catch (org.omg.PortableServer.POAManagerFactoryPackage.ManagerAlreadyExists ex) {
                 Assert._OB_assert(ex);
             }
@@ -558,8 +512,7 @@
         //
         // Create the Root POA
         //
-        org.apache.yoko.orb.OBPortableServer.POA_impl root = new org.apache.yoko.orb.OBPortableServer.POA_impl(
-                orb, orbInstance_, serverId, manager);
+        org.apache.yoko.orb.OBPortableServer.POA_impl root = new org.apache.yoko.orb.OBPortableServer.POA_impl(orb, orbInstance_, serverId, manager);
         root._OB_addPolicyFactory();
         rootPOA_ = root;
 
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBInstance.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBInstance.java
index 9842688..c2d94ec 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBInstance.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ORBInstance.java
@@ -17,18 +17,27 @@
 
 package org.apache.yoko.orb.OB;
 
-import org.apache.yoko.orb.OB.BootManager;
-import org.apache.yoko.orb.OB.DispatchStrategyFactory;
-import org.apache.yoko.orb.OB.Logger;
-import org.apache.yoko.orb.OB.URLRegistry;
-import org.apache.yoko.orb.OB.UnknownExceptionStrategy;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Phaser;
+
+import org.apache.yoko.orb.OCI.ConnectorInfo;
+import org.apache.yoko.util.Cache;
+import org.apache.yoko.util.concurrent.ReferenceCountedCache;
+import org.apache.yoko.util.concurrent.WeakCountedCache;
 
 public final class ORBInstance {
     private boolean destroy_; // True if destroy() was called
 
-    //
-    // Reference to ORB is needed in Java
-    //
+    private static final Cache.Cleaner<GIOPConnection> CLEANER = new Cache.Cleaner<GIOPConnection>() {
+        @Override
+        public void clean(GIOPConnection conn) {
+            conn.destroy();
+        }
+    };
+
+    private final Cache<ConnectorInfo, GIOPConnection> outboundConnectionCache = new WeakCountedCache<>(CLEANER, 0, 100);
+
     private org.omg.CORBA.ORB orb_;
 
     //
@@ -88,9 +97,11 @@
 
     private RecursiveMutex orbSyncMutex_ = new RecursiveMutex();
 
-    private ThreadGroup serverWorkerGroup_;
+    private ExecutorService serverExecutor_;
+    private Phaser serverPhaser = new Phaser(1);
 
-    private ThreadGroup clientWorkerGroup_;
+    private ExecutorService clientExecutor_;
+    private Phaser clientPhaser = new Phaser(1);
 
     private org.apache.yoko.orb.OCI.ConFactoryRegistry conFactoryRegistry_;
 
@@ -171,10 +182,11 @@
         defaultWcs_ = defaultWcs;
 
         //
-        // Create the server and client worker groups
+        // Create the server and client executors
+        // TODO why are these separate?
         //
-        clientWorkerGroup_ = new ThreadGroup("ClientWorkers");
-        serverWorkerGroup_ = new ThreadGroup("ServerWorkers");
+        clientExecutor_ = Executors.newCachedThreadPool();
+        serverExecutor_ = Executors.newCachedThreadPool();
 
         //
         // Use the TypeCode cache?
@@ -303,23 +315,8 @@
         // coreTraceLevels_.destroy();
         // coreTraceLevels_ = null;
 
-        try {
-            //
-            // Destroy the client and server worker groups
-            //
-            serverWorkerGroup_.destroy();
-        } catch (IllegalThreadStateException ex) {
-            // we ignore this...occasionally, it is necessary 
-            // to kick the threads to force them to shutdown. 
-        }
-
-        try {
-            clientWorkerGroup_.destroy();
-        } catch (IllegalThreadStateException ex) {
-            // we ignore this...occasionally, it is necessary 
-            // to kick the threads to force them to shutdown. 
-        }
-
+        // Client and server executors shut down in the ORBControl
+        
         //
         // Destroy the ConFactoryRegistry
         //
@@ -424,12 +421,20 @@
         return orbSyncMutex_;
     }
 
-    public ThreadGroup getServerWorkerGroup() {
-        return serverWorkerGroup_;
+    public ExecutorService getServerExecutor() {
+        return serverExecutor_;
     }
 
-    public ThreadGroup getClientWorkerGroup() {
-        return clientWorkerGroup_;
+    public Phaser getServerPhaser() {
+        return serverPhaser;
+    }
+    
+    public ExecutorService getClientExecutor() {
+        return clientExecutor_;
+    }
+    
+    public Phaser getClientPhaser() {
+        return clientPhaser;
     }
 
     public org.apache.yoko.orb.OCI.ConFactoryRegistry getConFactoryRegistry() {
@@ -478,4 +483,6 @@
     public OrbAsyncHandler getAsyncHandler() {
         return asyncHandler_;
     }
+
+    public Cache<ConnectorInfo, GIOPConnection> getOutboundConnectionCache() {return outboundConnectionCache;}
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ObjectKeyData.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ObjectKeyData.java
index 27e6b72..4857f02 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ObjectKeyData.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ObjectKeyData.java
@@ -44,7 +44,7 @@
     }
     
     public String toString() {
-        StringBuffer buf = new StringBuffer(); 
+        StringBuilder buf = new StringBuilder(); 
         buf.append(serverId); 
         buf.append(':'); 
         if (poaId != null) {
@@ -55,7 +55,7 @@
         }
         buf.append(':'); 
         if (oid != null) {
-            buf.append(IORUtil.format_octets(oid)); 
+            IORUtil.format_octets(oid, buf); 
         }
         return buf.toString(); 
     }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/PIDowncall.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/PIDowncall.java
index ac094c5..6aa738b 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/PIDowncall.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/PIDowncall.java
@@ -17,6 +17,8 @@
 
 package org.apache.yoko.orb.OB;
 
+import org.apache.yoko.orb.util.AutoLock;
+
 public class PIDowncall extends Downcall {
     //
     // The IOR and the original IOR
@@ -48,74 +50,76 @@
     // ----------------------------------------------------------------------
 
     void checkForException() throws LocationForward, FailureException {
-        //
-        // If ex_ is set, but exId_ is not, then set it now
-        //
-        // TODO: Postpone this in Java?
-        //
-        if (ex_ != null && exId_ == null)
-            exId_ = Util.getExceptionId(ex_);
+        try (AutoLock lock = stateLock.getReadLock()) {
+            //
+            // If ex_ is set, but exId_ is not, then set it now
+            //
+            // TODO: Postpone this in Java?
+            //
+            if (ex_ != null && exId_ == null)
+                exId_ = Util.getExceptionId(ex_);
 
-        switch (state_) {
-        case DowncallStateUserException:
-            //
-            // For Java portable stubs, we'll have the repository ID
-            // but not the exception instance, so we pass UNKNOWN to
-            // the interceptors but DO NOT modify the Downcall state.
-            //
-            if (ex_ == null && exId_ != null) {
-                org.omg.CORBA.Any any = new org.apache.yoko.orb.CORBA.Any(
-                        orbInstance_);
-                org.omg.CORBA.UNKNOWN sys = new org.omg.CORBA.UNKNOWN(
-                        MinorCodes
+            switch (state) {
+                case USER_EXCEPTION:
+                    //
+                    // For Java portable stubs, we'll have the repository ID
+                    // but not the exception instance, so we pass UNKNOWN to
+                    // the interceptors but DO NOT modify the Downcall state.
+                    //
+                    if (ex_ == null && exId_ != null) {
+                        org.omg.CORBA.Any any = new org.apache.yoko.orb.CORBA.Any(
+                                orbInstance_);
+                        org.omg.CORBA.UNKNOWN sys = new org.omg.CORBA.UNKNOWN(
+                                MinorCodes
                                 .describeUnknown(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException)
                                 + ": " + exId_,
-                        org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_YES);
-                org.omg.CORBA.UNKNOWNHelper.insert(any, sys);
-                org.omg.CORBA.UnknownUserException unk = new org.omg.CORBA.UnknownUserException(
-                        any);
-                piManager_.clientReceiveException(requestInfo_, false, unk,
-                        exId_);
+                                org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException,
+                                org.omg.CORBA.CompletionStatus.COMPLETED_YES);
+                        org.omg.CORBA.UNKNOWNHelper.insert(any, sys);
+                        org.omg.CORBA.UnknownUserException unk = new org.omg.CORBA.UnknownUserException(
+                                any);
+                        piManager_.clientReceiveException(requestInfo_, false, unk,
+                                exId_);
+                    }
+                    //
+                    // Only invoke interceptor if a user exception has been
+                    // set
+                    //
+                    if (ex_ != null)
+                        piManager_.clientReceiveException(requestInfo_, false, ex_,
+                                exId_);
+                    break;
+
+                case SYSTEM_EXCEPTION:
+                    Assert._OB_assert(ex_ != null);
+                    piManager_.clientReceiveException(requestInfo_, true, ex_, exId_);
+                    break;
+
+                case FAILURE_EXCEPTION:
+                    try {
+                        Assert._OB_assert(ex_ != null);
+                        piManager_.clientReceiveException(requestInfo_, true, ex_,
+                                exId_);
+                    } catch (org.omg.CORBA.SystemException ex) {
+                        //
+                        // Ignore any exception translations for failure
+                        // exceptions
+                        //
+                    }
+                    break;
+
+                case FORWARD:
+                case FORWARD_PERM:
+                    Assert._OB_assert(forwardIOR_ != null);
+                    piManager_.clientReceiveLocationForward(requestInfo_, forwardIOR_);
+                    break;
+
+                default:
+                    break;
             }
-            //
-            // Only invoke interceptor if a user exception has been
-            // set
-            //
-            if (ex_ != null)
-                piManager_.clientReceiveException(requestInfo_, false, ex_,
-                        exId_);
-            break;
 
-        case DowncallStateSystemException:
-            Assert._OB_assert(ex_ != null);
-            piManager_.clientReceiveException(requestInfo_, true, ex_, exId_);
-            break;
-
-        case DowncallStateFailureException:
-            try {
-                Assert._OB_assert(ex_ != null);
-                piManager_.clientReceiveException(requestInfo_, true, ex_,
-                        exId_);
-            } catch (org.omg.CORBA.SystemException ex) {
-                //
-                // Ignore any exception translations for failure
-                // exceptions
-                //
-            }
-            break;
-
-        case DowncallStateForward:
-        case DowncallStateForwardPerm:
-            Assert._OB_assert(forwardIOR_ != null);
-            piManager_.clientReceiveLocationForward(requestInfo_, forwardIOR_);
-            break;
-
-        default:
-            break;
+            super.checkForException();
         }
-
-        super.checkForException();
     }
 
     // ----------------------------------------------------------------------
@@ -143,52 +147,45 @@
     }
 
     public void postUnmarshal() throws LocationForward, FailureException {
-        //
-        // If the result of this downcall is a user exception, but no user
-        // exception could be unmarshalled, then use the system exception
-        // UNKNOWN, but keep the original exception ID
-        //
-        // In Java, the portable stubs only provide the repository ID of
-        // the user exception, not the exception instance. We want to
-        // report UNKNOWN to the interceptors, but do not want to change
-        // the downcall status if we have the repository ID.
-        //
-        if (state_ == DowncallStateUserException && ex_ == null
-                && exId_ == null) {
-            String id = unmarshalExceptionId();
-            setSystemException(new org.omg.CORBA.UNKNOWN(org.apache.yoko.orb.OB.MinorCodes
-                    .describeUnknown(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException)
-                    + ": " + id, org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_YES));
-            exId_ = id;
+        try (AutoLock lock = stateLock.getReadLock()) {
+            //
+            // If the result of this downcall is a user exception, but no user
+            // exception could be unmarshalled, then use the system exception
+            // UNKNOWN, but keep the original exception ID
+            //
+            // In Java, the portable stubs only provide the repository ID of
+            // the user exception, not the exception instance. We want to
+            // report UNKNOWN to the interceptors, but do not want to change
+            // the downcall status if we have the repository ID.
+            //
+            if (state == State.USER_EXCEPTION && ex_ == null && exId_ == null) {
+                String id = unmarshalExceptionId();
+                setSystemException(new org.omg.CORBA.UNKNOWN(org.apache.yoko.orb.OB.MinorCodes
+                        .describeUnknown(org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException)
+                        + ": " + id, org.apache.yoko.orb.OB.MinorCodes.MinorUnknownUserException,
+                        org.omg.CORBA.CompletionStatus.COMPLETED_YES));
+                exId_ = id;
+            }
+    
+            super.postUnmarshal();
+    
+            //
+            // Java only - Downcall.checkForException() does not raise
+            // UserExceptions, so we return now and let the stub handle it
+            //
+            if (state == State.USER_EXCEPTION)
+                return;
+    
+            if (responseExpected_)
+                Assert._OB_assert(state == State.NO_EXCEPTION);
+            else
+                Assert._OB_assert(state == State.UNSENT || state == State.NO_EXCEPTION);
+            piManager_.clientReceiveReply(requestInfo_);
         }
-
-        super.postUnmarshal();
-
-        //
-        // Java only - Downcall.checkForException() does not raise
-        // UserExceptions, so we return now and let the stub handle it
-        //
-        if (state_ == DowncallStateUserException)
-            return;
-
-        if (responseExpected_)
-            Assert._OB_assert(state_ == DowncallStateNoException);
-        else
-            Assert._OB_assert(state_ == DowncallStateUnsent
-                    || state_ == DowncallStateNoException);
-        piManager_.clientReceiveReply(requestInfo_);
     }
 
     public void setUserException(org.omg.CORBA.UserException ex, String exId) {
         super.setUserException(ex, exId);
         exId_ = exId;
     }
-
-    public void setUserException(org.omg.CORBA.UserException ex) {
-        Assert._OB_assert(responseExpected_);
-        Assert._OB_assert(ex_ == null);
-        state_ = DowncallStateUserException;
-        ex_ = ex;
-    }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/TypeCodeFactory.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/TypeCodeFactory.java
index 71392ba..d045684 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/TypeCodeFactory.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/TypeCodeFactory.java
@@ -48,7 +48,10 @@
         return true;
     }
 
+    private static final boolean CHECK_IDL_NAMES = false;
+
     private static boolean checkName(String name) {
+        if (!CHECK_IDL_NAMES) return true;
         //
         // Check for a valid IDL name
         //
@@ -663,6 +666,7 @@
                         + ": " + members[i].name,
                         org.apache.yoko.orb.OB.MinorCodes.MinorInvalidMemberType,
                         org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            if (!CHECK_IDL_NAMES) continue;
             for (int j = i + 1; j < members.length; j++)
                 if (members[i].name.length() > 0
                         && members[i].name.equalsIgnoreCase(members[j].name)) {
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/UnresolvedException.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/UnresolvedException.java
new file mode 100644
index 0000000..8d0aaf5
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/UnresolvedException.java
@@ -0,0 +1,82 @@
+package org.apache.yoko.orb.OB;
+
+import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_2;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.yoko.orb.CORBA.InputStream;
+import org.apache.yoko.orb.OCI.Buffer;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.UNKNOWN;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.SendingContext.CodeBase;
+
+public class UnresolvedException extends UnknownException {
+    private static final Logger LOGGER = Logger.getLogger(UnresolvedException.class.getName());
+    private final UNKNOWN ex;
+    private final byte[] data;
+    private final CodeConverters converters;
+    private final CodeBase sendingContextRuntime;
+    private final String codebase;
+
+    UnresolvedException(UNKNOWN ex, byte[] data, InputStream is) {
+        super(ex);
+        super.completed = ex.completed;
+        super.minor = ex.minor;
+        this.ex = ex;
+        this.data = data;
+        this.converters = is._OB_codeConverters();
+        this.sendingContextRuntime = is.__getSendingContextRuntime();
+        this.codebase = is.__getCodeBase();
+    }
+
+    public SystemException resolve() {
+        Buffer buf = new Buffer(data, data.length);
+        try (org.apache.yoko.orb.CORBA.InputStream in =
+                new org.apache.yoko.orb.CORBA.InputStream(buf, 0, false, converters, GIOP1_2)) {
+            if (LOGGER.isLoggable(Level.FINE))
+                LOGGER.fine(String.format("Unpacking Unknown Exception Info%n%s", in.dumpData()));
+            try {
+                in.__setSendingContextRuntime(sendingContextRuntime);
+                in.__setCodeBase(codebase);
+                in._OB_readEndian();
+                Throwable t = (Throwable) in.read_value();
+                UnknownException x = new UnknownException(t);
+                x.completed = ex.completed;
+                x.minor = ex.minor;
+                return x;
+            } catch (Exception e) {
+                final String dump = in.dumpData();
+                final int curPos = in.buf_.pos();
+                in.buf_.pos(0);
+                final String fullDump = in.dumpData();
+                in.buf_.pos(curPos);
+                try (StringWriter sw = new StringWriter();
+                        PrintWriter pw = new PrintWriter(sw)) {
+                    e.printStackTrace(pw);
+                    LOGGER.severe(String.format("%s:%n%s:%n%s%n%s:%n%s%n%s:%n%s",
+                            "Exception reading UnknownExceptionInfo service context",
+                            "Remaining data", dump, "Full data", fullDump,
+                            "Exception thrown", sw.toString()));
+                }
+            }
+        } catch (IOException e) {
+            //ignore IOException from AutoCloseable.close()
+        }
+        return ex;
+    }
+
+    private void readObject(ObjectInputStream ois) throws IOException {
+        throw new NotSerializableException();
+    }
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        throw new NotSerializableException();
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Upcall.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Upcall.java
index 9ffb3a7..c77629f 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Upcall.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Upcall.java
@@ -17,11 +17,25 @@
 
 package org.apache.yoko.orb.OB;
 
+import static org.apache.yoko.orb.OB.CodeSetDatabase.UTF16;
+import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_2;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Vector;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.apache.yoko.orb.OB.DispatchRequest;
-import org.apache.yoko.orb.OB.DispatchStrategy;
+import org.apache.yoko.orb.CORBA.OutputStream;
+import org.apache.yoko.orb.OCI.Buffer;
+import org.apache.yoko.orb.OCI.GiopVersion;
+import org.apache.yoko.util.cmsf.CmsfThreadLocal;
+import org.apache.yoko.util.cmsf.CmsfThreadLocal.CmsfOverride;
+import org.omg.CORBA.INTERNAL;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.IOP.ExceptionDetailMessage;
+import org.omg.IOP.ServiceContext;
+import org.omg.IOP.UnknownExceptionInfo;
 
 public class Upcall {
     static final Logger logger = Logger.getLogger(Upcall.class.getName());
@@ -76,7 +90,7 @@
     // The reply service context list
     // (Must be a Vector because it can be modified by interceptors)
     //
-    protected java.util.Vector replySCL_ = new java.util.Vector();
+    protected Vector<ServiceContext> replySCL_ = new Vector<>();
 
     //
     // The dispatch request
@@ -188,8 +202,7 @@
                 offset);
         buf.pos(offset);
         out_ = new org.apache.yoko.orb.CORBA.OutputStream(buf, in_
-                ._OB_codeConverters(), (profileInfo_.major << 8)
-                | profileInfo_.minor);
+                ._OB_codeConverters(), GiopVersion.get(profileInfo_.major, profileInfo_.minor));
     }
 
     public org.apache.yoko.orb.CORBA.InputStream preUnmarshal()
@@ -294,8 +307,23 @@
         // OutputStream to make the skeleton happy and avoid a crash.
         //
         if (upcallReturn_ != null) {
-            if (!upcallReturn_.replySent() && (profileInfo_.major > 1 || profileInfo_.minor >= 1)) {
-                initServiceContexts();
+            addUnsentConnectionServiceContexts();
+            org.omg.IOP.ServiceContext[] scl = new org.omg.IOP.ServiceContext[replySCL_
+                    .size()];
+            replySCL_.copyInto(scl);
+            upcallReturn_.upcallBeginReply(this, scl);
+        } else {
+            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
+            out_ = new org.apache.yoko.orb.CORBA.OutputStream(buf, in_
+                    ._OB_codeConverters(), GiopVersion.get(profileInfo_.major, profileInfo_.minor));
+        }
+        out_._OB_ORBInstance(this.orbInstance());
+        return out_;
+    }
+
+    private void addUnsentConnectionServiceContexts() {
+        if (!upcallReturn_.replySent() && (profileInfo_.major > 1 || profileInfo_.minor >= 1)) {
+            initServiceContexts();
 //                CoreTraceLevels coreTraceLevels = orbInstance_
 //                        .getCoreTraceLevels();
 //                if (coreTraceLevels.traceConnections() >= 2) {
@@ -323,21 +351,9 @@
 //                Assert._OB_assert(codeSetSC_ != null);
 //                replySCL_.add(codeSetSC_);
 
-                Assert._OB_assert(codeBaseSC_ != null);
-                replySCL_.add(codeBaseSC_);
-            }
-            org.omg.IOP.ServiceContext[] scl = new org.omg.IOP.ServiceContext[replySCL_
-                    .size()];
-            replySCL_.copyInto(scl);
-            upcallReturn_.upcallBeginReply(this, scl);
-        } else {
-            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
-            out_ = new org.apache.yoko.orb.CORBA.OutputStream(buf, in_
-                    ._OB_codeConverters(), (profileInfo_.major << 8)
-                    | profileInfo_.minor);
+            Assert._OB_assert(codeBaseSC_ != null);
+            replySCL_.add(codeBaseSC_);
         }
-        out_._OB_ORBInstance(this.orbInstance());
-        return out_;
     }
 
     public void marshalEx(org.omg.CORBA.SystemException ex)
@@ -423,14 +439,35 @@
 
     public void setSystemException(org.omg.CORBA.SystemException ex) {
         if (upcallReturn_ != null) {
-            userEx_ = false; // Java only
-            org.omg.IOP.ServiceContext[] scl = new org.omg.IOP.ServiceContext[replySCL_
-                    .size()];
+            addUnsentConnectionServiceContexts();
+            userEx_ = false;
+            if (ex instanceof UnknownException) {
+                // need to create service contexts for underlying exception
+                createUnknownExceptionServiceContexts((UnknownException)ex, replySCL_);
+            }
+            ServiceContext[] scl = new ServiceContext[replySCL_.size()];
             replySCL_.copyInto(scl);
             upcallReturn_.upcallSystemException(this, ex, scl);
         }
     }
 
+    private static void createUnknownExceptionServiceContexts(UnknownException ex, Vector<ServiceContext> scl) {
+        final Throwable t = ex.originalEx;
+        try (CmsfOverride o = CmsfThreadLocal.override()) {
+            CodeConverters codeConverters = new CodeConverters();
+            codeConverters.outputWcharConverter = CodeSetDatabase.instance().getConverter(UTF16, UTF16);
+            Buffer buf = new Buffer();
+            try (OutputStream os = new OutputStream(buf, codeConverters, GIOP1_2)) {
+                os._OB_writeEndian();
+                os.write_value(t, Throwable.class);
+                ServiceContext sc = new ServiceContext(UnknownExceptionInfo.value, Arrays.copyOf(buf.data(), buf.length()));
+                scl.add(sc);
+            }
+        } catch (IOException e) {
+            throw (INTERNAL)(new INTERNAL(e.getMessage())).initCause(e);
+        }
+    }
+
     public void setLocationForward(org.omg.IOP.IOR ior, boolean perm) {
         if (upcallReturn_ != null) {
             userEx_ = false; // Java only
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Util.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Util.java
index 2073555..19bbdd5 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/Util.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/Util.java
@@ -337,253 +337,6 @@
         }
     }
 
-    //
-    // Convert a repository ID into a class name.
-    // See the IDL-to-Java mapping, section 1.13.8.
-    //
-    public static String idToClassName(String id, String suffix) {
-        String result = null;
-
-        if (id.startsWith("IDL:")) {
-            try {
-                StringBuffer buf = new StringBuffer();
-
-                int end = id.lastIndexOf(':');
-                String s;
-                if (end < 0)
-                    s = id.substring(4);
-                else
-                    s = id.substring(4, end);
-
-                //
-                // If the ID contains a prefix, then fix each of the 
-                // dotted components of the prefix
-                //
-                int slash = s.indexOf('/');
-                if (slash > 0) {
-                    String prefix = s.substring(0, slash);
-                    String rest = s.substring(slash + 1);
-                    java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(
-                            prefix, ".");
-                    while (tokenizer.hasMoreTokens()) {
-                        String tok = tokenizer.nextToken();
-                        buf.append(fixName(tok));
-                        buf.append('.');
-                    }
-                    s = rest;
-                }
-
-                //
-                // "Fix" the remainder of the ID
-                //
-                java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(
-                        s, "/");
-                while (tokenizer.hasMoreTokens()) {
-                    String tok = tokenizer.nextToken();
-                    buf.append(fixName(tok));
-                    if (tokenizer.hasMoreTokens())
-                        buf.append('.');
-                }
-
-                result = buf.toString() + suffix;
-            } catch (IndexOutOfBoundsException ex) // if id has bad format
-            {
-                result = null;
-            }
-        }
-        else if (id.startsWith ("RMI:")) {
-            int end = id.indexOf (':', 4);
-            result = end < 0
-                ? id.substring (4)
-                : id.substring (4, end);
-        }
-        if (result != null) {
-            result = removeUnicodeEscapes(result); 
-        }
-        return result;
-    }
-    
-    
-    /**
-     * Remove Unicode \Uxxxx escape sequences from a string 
-     * received from the client ORB.
-     * 
-     * @param in     The input string.
-     * 
-     * @return The string with any unicode escape sequences converted 
-     *         into the appropriate character values.
-     */
-    public static String removeUnicodeEscapes(String in) {
-        // if no escape sequences are in the string, this is easy
-        int escape = in.indexOf("\\U"); 
-        if (escape < 0) {
-            return in;
-        }
-        
-        // get a string buffer at least as long as the input string 
-        StringBuffer out = new StringBuffer(in.length()); 
-        int start = 0; 
-        
-        while (escape >= 0) {
-            // add the next real segment to the buffer
-            out.append(in.substring(start, escape));
-            // step over the escape sequence 
-            escape += 2; 
-            
-            int value = 0; 
-            for (int i=0; i<4; i++) {
-                char ch = in.charAt(escape++);
-                switch (ch) {
-                  case '0': 
-                  case '1': 
-                  case '2': 
-                  case '3': 
-                  case '4':
-                  case '5': 
-                  case '6': 
-                  case '7': 
-                  case '8': 
-                  case '9':
-                     value = (value << 4) + ch - '0';
-                     break;
-                  case 'a': 
-                  case 'b': 
-                  case 'c':
-                  case 'd': 
-                  case 'e': 
-                  case 'f':
-                     value = (value << 4) + 10 + ch - 'a';
-                     break;
-                  case 'A': 
-                  case 'B': 
-                  case 'C':
-                  case 'D': 
-                  case 'E': 
-                  case 'F':
-                     value = (value << 4) + 10 + ch - 'A';
-                     break;
-                  default:
-                      // not sure what to do here.  Just treat it as a 0 nibble      
-                      value = (value << 4);
-                }
-            }
-            // now append this as a char value 
-            out.append((char)value); 
-            // now step and find the next one 
-            start = escape; 
-            escape = in.indexOf("\\U", escape); 
-        }
-        // don't forget the trailing segment 
-        if (start < in.length()) {
-            out.append(in.substring(start));
-        }
-        return out.toString(); 
-    }
-
-    //
-    // Convert a repository ID into a class.
-    // See the IDL-to-Java mapping, section 1.13.8.
-    //
-    public static Class idToClass(String id, String suffix) {
-        logger.fine("Searching for class from " + id + " using suffix " + suffix); 
-        Class result = null;
-        String className = idToClassName(id, suffix);
-
-        logger.fine("Converted class name is " + className); 
-        
-        if (className != null) {
-            try {
-                // get the appropriate class for the loading.
-                ClassLoader loader = Thread.currentThread().getContextClassLoader();
-                result = javax.rmi.CORBA.Util.loadClass(className, null, loader); 
-            } catch (ClassNotFoundException ex) {
-                logger.fine("Converted class name not found"); 
-                // ignore
-            }
-        }
-
-        return result;
-    }
-
-    //
-    // Check the given name against Java keywords and reserved suffixes
-    //
-    public static String fixName(String name) {
-        Assert._OB_assert(name.indexOf('.') == -1); // Not for absolute names
-
-        int nameLen = name.length();
-        if (nameLen == 0)
-            return name;
-
-        final String[] kwds = {
-        //
-                // Note: This list must be sorted alphabetically
-                //
-                "abstract", "assert", "boolean", "break", "byte", "case",
-                "catch", "char", "class", "clone", "const", "continue",
-                "default", "do", "double", "else", "equals", "extends",
-                "false", "final", "finalize", "finally", "float", "for",
-                "getClass", "goto", "hashCode", "if", "implements", "import",
-                "instanceof", "int", "interface", "long", "native", "new",
-                "notify", "notifyAll", "null", "package", "private",
-                "protected", "public", "return", "short", "static", "super",
-                "switch", "synchronized", "this", "throw", "throws",
-                "toString", "transient", "true", "try", "void", "volatile",
-                "wait", "while" };
-
-        int l = 0;
-        int r = kwds.length;
-
-        while (l < r) {
-            int m = (l + r) / 2;
-            int res = kwds[m].compareTo(name);
-            if (res == 0)
-                return "_" + name;
-            else if (res > 0)
-                r = m;
-            else
-                l = m + 1;
-        }
-
-        //
-        // Prepend an underscore for each of the reserved suffixes below
-        //
-        final String[] reserved = { "Helper", "Holder", "Operations", "POA",
-                "POATie", "Package", "ValueFactory" };
-
-        String result = name;
-        String curr = name;
-
-        boolean match;
-        do {
-            int currLen = curr.length();
-
-            match = false;
-            for (int i = 0; i < reserved.length; i++) {
-                if (curr.endsWith(reserved[i])) {
-                    //
-                    // Prepend an underscore to result
-                    //
-                    result = "_" + result;
-
-                    //
-                    // Remove suffix from curr
-                    //
-                    int resLen = reserved[i].length();
-                    if (currLen > resLen)
-                        curr = curr.substring(0, currLen - resLen);
-                    else
-                        curr = "";
-
-                    match = true;
-                    break;
-                }
-            }
-        } while (match);
-
-        return result;
-    }
-
     public static void insertException(org.omg.CORBA.Any any,
             java.lang.Exception ex) {
         //
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueFactoryManager.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueFactoryManager.java
index c1b9840..6f6ed0d 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueFactoryManager.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueFactoryManager.java
@@ -20,6 +20,8 @@
 import java.util.logging.Logger;
 import java.util.logging.Level;
 
+import org.apache.yoko.util.cmsf.RepIds;
+
 public final class ValueFactoryManager {
     static final Logger logger = Logger.getLogger(ValueFactoryManager.class.getName());
     //
@@ -176,7 +178,7 @@
         //
         // Try to convert the repository ID into a class name.
         //
-        Class c = Util.idToClass(id, "DefaultFactory");
+        Class c = RepIds.query(id).suffix("DefaultFactory").toClass();
         if (c != null) {
             try {
                 logger.finer("Attempting to create value factory from class " + c.getName());
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueReader.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueReader.java
index 0b03204..8796418 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueReader.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueReader.java
@@ -19,23 +19,44 @@
 
 import java.io.Serializable;
 import java.lang.reflect.Array;
+import java.util.Hashtable;
+import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import javax.rmi.CORBA.ValueHandler;
 
+import org.apache.yoko.orb.CORBA.InputStream;
+import org.apache.yoko.orb.CORBA.OutputStream;
+import org.apache.yoko.orb.OCI.Buffer;
+import org.apache.yoko.util.cmsf.RepIds;
+import org.omg.CORBA.Any;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.CustomMarshal;
+import org.omg.CORBA.DataInputStream;
+import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.StringHolder;
+import org.omg.CORBA.SystemException;
 import org.omg.CORBA.TCKind;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.TypeCodePackage.BadKind;
+import org.omg.CORBA.TypeCodePackage.Bounds;
+import org.omg.CORBA.VM_CUSTOM;
+import org.omg.CORBA.VM_NONE;
+import org.omg.CORBA.VM_TRUNCATABLE;
 import org.omg.CORBA.WStringValueHelper;
+import org.omg.CORBA.portable.BoxedValueHelper;
 import org.omg.CORBA.portable.IndirectionException;
 import org.omg.CORBA.portable.StreamableValue;
+import org.omg.CORBA.portable.ValueFactory;
 import org.omg.SendingContext.CodeBase;
 
-final public class ValueReader {
-    static final Logger logger = Logger.getLogger(ValueReader.class.getName());
+public final class ValueReader {
+    private static final Logger logger = Logger.getLogger(ValueReader.class.getName());
     //
     // Chunk data
     //
-    static private class ChunkState {
+    private static class ChunkState {
         boolean chunked;
 
         int nestingLevel;
@@ -62,7 +83,7 @@
     //
     // Valuetype header data
     //
-    static private class Header {
+    private static class Header {
         int tag;
 
         int headerPos;
@@ -80,78 +101,71 @@
             ids = new String[0];
             state = new ChunkState();
         }
-        
-        boolean isRMIValue () {
-            return ids != null
-                && ids.length > 0
-                && ids[0].startsWith ("RMI:");
+
+        boolean isRMIValue() {
+            return (ids != null) && (ids.length > 0) && ids[0].startsWith("RMI:");
         }
 
     }
 
-    private org.apache.yoko.orb.OB.ORBInstance orbInstance_;
+    private final ORBInstance orbInstance_;
 
-    private org.apache.yoko.orb.CORBA.InputStream in_;
+    private final InputStream in_;
 
-    private org.apache.yoko.orb.OCI.Buffer buf_;
+    private final Buffer buf_;
 
-    private java.util.Hashtable instanceTable_;
+    private final Map<Integer, Serializable> instanceTable_;
 
-    private java.util.Hashtable headerTable_;
+    private final Map<Integer, Header> headerTable_;
 
-    private java.util.Hashtable positionTable_ = null;
+    private Map<Integer, Integer> positionTable_;
 
-    private ChunkState chunkState_ = new ChunkState();
+    private final ChunkState chunkState_ = new ChunkState();
 
-    private Header currentHeader_ = null; // Java only
-	private ValueHandler valueHandler;
-	private org.omg.SendingContext.CodeBase remoteCodeBase;
+    private Header currentHeader_;
+    private ValueHandler valueHandler;
+    private CodeBase remoteCodeBase;
 
     // ------------------------------------------------------------------
     // Valuetype creation strategies
     // ------------------------------------------------------------------
 
-    private static abstract class CreationStrategy {
-        protected ValueReader reader_;
+    private abstract static class CreationStrategy {
+        final ValueReader reader_;
 
-        protected org.apache.yoko.orb.CORBA.InputStream is_;
+        final InputStream is_;
 
-        CreationStrategy(ValueReader reader,
-                org.apache.yoko.orb.CORBA.InputStream is) {
+        CreationStrategy(ValueReader reader, InputStream is) {
             reader_ = reader;
             is_ = is;
         }
 
-        abstract java.io.Serializable create(Header h);
+        abstract Serializable create(Header h);
     }
 
     //
     // Create a valuebox using a BoxedValueHelper
     //
     private static class BoxCreationStrategy extends CreationStrategy {
-        private org.omg.CORBA.portable.BoxedValueHelper helper_;
+        private final BoxedValueHelper helper_;
 
-        BoxCreationStrategy(ValueReader reader,
-                org.apache.yoko.orb.CORBA.InputStream is,
-                org.omg.CORBA.portable.BoxedValueHelper helper) {
+        BoxCreationStrategy(ValueReader reader, InputStream is, BoxedValueHelper helper) {
             super(reader, is);
             helper_ = helper;
         }
 
-        java.io.Serializable create(Header h) {
-            Assert._OB_assert(h.tag >= 0x7fffff00 && h.tag != -1);
+        Serializable create(Header h) {
+            Assert._OB_assert((h.tag >= 0x7fffff00) && (h.tag != -1));
 
-            java.io.Serializable result = helper_.read_value(is_);
+            final Serializable result = helper_.read_value(is_);
 
             if (result != null) {
                 reader_.addInstance(h.headerPos, result);
                 return result;
             }
 
-            throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                    .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory)
-                    + ": " + helper_.get_id(), org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorNoValueFactory) + ": " + helper_.get_id(), MinorCodes.MinorNoValueFactory,
+                    CompletionStatus.COMPLETED_NO);
         }
     }
 
@@ -159,43 +173,37 @@
     // Create a value using a class
     //
     private static class ClassCreationStrategy extends CreationStrategy {
-        private Class clz_;
+        private final Class<? extends Serializable> clz_;
 
-        ClassCreationStrategy(ValueReader reader,
-                org.apache.yoko.orb.CORBA.InputStream is, Class clz) {
+        ClassCreationStrategy(ValueReader reader, InputStream is, Class<? extends Serializable> clz) {
             super(reader, is);
             clz_ = clz;
         }
 
-        java.io.Serializable create(Header h) {
-            logger.fine("Creating a value object with tag value " + Integer.toHexString(h.tag)); 
-            Assert._OB_assert(h.tag >= 0x7fffff00 && h.tag != -1);
+        Serializable create(Header h) {
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format("Creating a value object with tag value 0x%08x", h.tag));
+            Assert._OB_assert((h.tag >= 0x7fffff00) && (h.tag != -1));
 
             if (h.isRMIValue()) {
-            	return reader_.readRMIValue(h, clz_, h.ids[0]);
+                return reader_.readRMIValue(h, clz_, h.ids[0]);
             }
 
-            java.io.Serializable result = null;
-
             try {
-                result = (java.io.Serializable) clz_.newInstance();
+                Serializable result = clz_.newInstance();
                 reader_.addInstance(h.headerPos, result);
                 try {
                     reader_.unmarshalValueState(result);
-                } catch (org.omg.CORBA.SystemException ex) {
+                } catch (SystemException ex) {
                     reader_.removeInstance(h.headerPos);
                     throw ex;
                 }
                 return result;
-            } catch (ClassCastException ex) {
-            } catch (IllegalAccessException ex) {
-            } catch (InstantiationException ex) {
+            } catch (ClassCastException | InstantiationException | IllegalAccessException ignored) {
             }
 
-            throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                    .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory)
-                    + ": " + clz_.getName(), org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorNoValueFactory) + ": " + clz_.getName(), MinorCodes.MinorNoValueFactory,
+                    CompletionStatus.COMPLETED_NO);
         }
     }
 
@@ -203,23 +211,21 @@
     // Create a value using a factory
     //
     private class FactoryCreationStrategy extends CreationStrategy {
-        private String id_;
+        private final String id_;
 
-        private ORBInstance orbInstance_;
+        private final ORBInstance orbInstance_;
 
-        FactoryCreationStrategy(ValueReader reader,
-                org.apache.yoko.orb.CORBA.InputStream is, String id) {
+        FactoryCreationStrategy(ValueReader reader, InputStream is, String id) {
             super(reader, is);
             id_ = id;
             orbInstance_ = is._OB_ORBInstance();
         }
 
-        private org.omg.CORBA.portable.ValueFactory findFactory(Header h,
-                org.omg.CORBA.StringHolder id) {
-            org.omg.CORBA.portable.ValueFactory f = null;
+        private ValueFactory findFactory(Header h, StringHolder id) {
+            ValueFactory f = null;
 
             if (orbInstance_ != null) {
-                ValueFactoryManager manager = orbInstance_.getValueFactoryManager();
+                final ValueFactoryManager manager = orbInstance_.getValueFactoryManager();
 
                 if (h.ids.length > 0) {
                     for (int i = 0; i < h.ids.length; i++) {
@@ -233,9 +239,10 @@
                         // If we have a formal ID, and we haven't found
                         // a factory yet, then give up
                         //
-                        if (id_ != null && h.ids[i].equals(id_))
+                        if ((id_ != null) && h.ids[i].equals(id_)) {
                             break;
                     }
+                    }
                 } else if (id_ != null) {
                     f = manager.lookupValueFactoryWithClass(id_);
                     id.value = id_;
@@ -245,8 +252,7 @@
             return f;
         }
 
-        private java.io.Serializable createWithFactory(Header h,
-                org.omg.CORBA.portable.ValueFactory factory) {
+        private Serializable createWithFactory(Header h, ValueFactory factory) {
             //
             // The factory's read_value method is expected to create
             // an instance of the valuetype and then call the method
@@ -263,49 +269,44 @@
             }
         }
 
-        private org.omg.CORBA.portable.BoxedValueHelper getBoxedHelper(String id) {
-            org.omg.CORBA.portable.BoxedValueHelper result = null;
+        private BoxedValueHelper getBoxedHelper(String id) {
+            if (WStringValueHelper.id().equals(id))
+                return new WStringValueHelper();
 
-            Class helperClass = Util.idToClass(id, "Helper");
+            final Class helperClass = RepIds.query(id).suffix("Helper").toClass();
 
             if (helperClass != null) {
                 try {
-                    return (org.omg.CORBA.portable.BoxedValueHelper) helperClass
-                            .newInstance();
-                } catch (ClassCastException ex) {
-                } catch (IllegalAccessException ex) {
-                } catch (InstantiationException ex) {
+                    return (BoxedValueHelper) helperClass.newInstance();
+                } catch (ClassCastException | InstantiationException | IllegalAccessException ignored) {
                 }
 
-                throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory)
-                        + ": invalid BoxedValueHelper for " + id,
-                        org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorNoValueFactory) + ": invalid BoxedValueHelper for " + id,
+                        MinorCodes.MinorNoValueFactory, CompletionStatus.COMPLETED_NO);
             }
 
             return null;
         }
 
-        java.io.Serializable create(Header h) {
-            org.omg.CORBA.StringHolder idH = new org.omg.CORBA.StringHolder();
+        Serializable create(Header h) {
+            final StringHolder idH = new StringHolder();
             return create(h, idH);
         }
 
-        java.io.Serializable create(Header h, org.omg.CORBA.StringHolder id) {
-            Assert._OB_assert(h.tag >= 0x7fffff00 && h.tag != -1);
+        Serializable create(Header h, StringHolder id) {
+            Assert._OB_assert((h.tag >= 0x7fffff00) && (h.tag != -1));
 
-            if (h.isRMIValue ()) {
-                Serializable result = readRMIValue (h, null, h.ids[0]);
-                addInstance (h.headerPos, result);
+            if (h.isRMIValue()) {
+                final Serializable result = readRMIValue(h, null, h.ids[0]);
+                addInstance(h.headerPos, result);
                 return result;
             }
             //
             // See if a factory exists that can create the value
             //
-            org.omg.CORBA.portable.ValueFactory factory = findFactory(h, id);
+            final ValueFactory factory = findFactory(h, id);
             if (factory != null) {
-                java.io.Serializable result = createWithFactory(h, factory);
+                final Serializable result = createWithFactory(h, factory);
                 reader_.addInstance(h.headerPos, result);
                 return result;
             }
@@ -314,37 +315,38 @@
             // Another possibility is that we're unmarshalling a valuebox,
             // so we'll try to load the Helper class dynamically
             //
-            org.omg.CORBA.portable.BoxedValueHelper helper = null;
+            BoxedValueHelper helper = null;
             if (h.ids.length > 0) {
                 //
                 // If it's a valuebox, at most one id will be marshalled
                 //
                 helper = getBoxedHelper(h.ids[0]);
-                if (helper != null)
+                if (helper != null) {
                     id.value = h.ids[0];
             }
+            }
 
-            if (helper == null && id_ != null) {
+            if ((helper == null) && (id_ != null)) {
                 helper = getBoxedHelper(id_);
-                if (helper != null)
+                if (helper != null) {
                     id.value = id_;
             }
+            }
 
             if (helper != null) {
-                java.io.Serializable result = helper.read_value(is_);
+                final Serializable result = helper.read_value(is_);
                 reader_.addInstance(h.headerPos, result);
                 return result;
             }
 
             String type = "<unknown>";
-            if (h.ids.length > 0)
+            if (h.ids.length > 0) {
                 type = h.ids[0];
-            else if (id_ != null)
+            } else if (id_ != null) {
                 type = id_;
-            throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                    .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory)
-                    + ": " + type, org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+        }
+            throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorNoValueFactory) + ": " + type, MinorCodes.MinorNoValueFactory,
+                    CompletionStatus.COMPLETED_NO);
         }
     }
 
@@ -353,26 +355,26 @@
     // ------------------------------------------------------------------
 
     // Java only
-    private void addInstance(int pos, java.io.Serializable instance) {
-        // only add this if we have a real value 
+    private void addInstance(int pos, Serializable instance) {
+        // only add this if we have a real value
         if (instance != null) {
-            instanceTable_.put(new Integer(pos), instance);
+            instanceTable_.put(pos, instance);
         }
     }
 
     // Java only
     private void removeInstance(int pos) {
-        instanceTable_.remove(new Integer(pos));
+        instanceTable_.remove(pos);
     }
 
     private void readHeader(Header h) {
-        logger.fine("Reading header with tag value " + Integer.toHexString(h.tag) + " at pos=" 
-        		+ in_.buf_.pos_); 
-        
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Reading header with tag value 0x%08x at pos=0x%x", h.tag, in_.buf_.pos_));
+
         //
         // Special cases are handled elsewhere
         //
-        Assert._OB_assert(h.tag != 0 && h.tag != -1);
+        Assert._OB_assert((h.tag != 0) && (h.tag != -1));
 
         //
         // Check if the value is chunked
@@ -380,7 +382,7 @@
         if ((h.tag & 0x00000008) == 8) {
             h.state.chunked = true;
         } else {
-        	h.state.chunked = false;
+            h.state.chunked = false;
         }
 
         //
@@ -390,23 +392,19 @@
             //
             // Check for indirection tag
             //
-            int save = buf_.pos_;
-            int indTag = in_.read_long();
+            final int save = buf_.pos_;
+            final int indTag = in_.read_long();
             if (indTag == -1) {
-                int offs = in_.read_long();
+                final int offs = in_.read_long();
                 if (offs >= -4) {
-                    throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                            CompletionStatus.COMPLETED_NO);
                 }
-                int tmp = buf_.pos_;
-                buf_.pos_ = buf_.pos_ - 4 + offs;
+                final int tmp = buf_.pos_;
+                buf_.pos_ = (buf_.pos_ - 4) + offs;
                 if (buf_.pos_ < 0) {
-                    throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                            CompletionStatus.COMPLETED_NO);
                 }
                 h.codebase = in_.read_string();
                 buf_.pos_ = tmp;
@@ -414,19 +412,20 @@
                 buf_.pos_ = save;
                 h.codebase = in_.read_string();
             }
-            logger.finer("Value header codebase value is " + h.codebase); 
+            if (logger.isLoggable(Level.FINER))
+                logger.finer(String.format("Value header codebase value is \"%s\"", h.codebase));
         }
 
         //
         // Extract repository ID information
         //
         if ((h.tag & 0x00000006) == 0) {
-            logger.finer("No type information was included"); 
+            logger.finer("No type information was included");
             //
             // No type information was marshalled
             //
         } else if ((h.tag & 0x00000006) == 6) {
-            logger.finer("Multiple types included in header"); 
+            logger.finer("Multiple types included in header");
             //
             // Extract a list of repository IDs, representing the
             // truncatable types for this value
@@ -437,28 +436,25 @@
             //
             int saveList = buf_.pos_;
             int indTag = in_.read_long();
-            boolean indList = (indTag == -1);
+            final boolean indList = (indTag == -1);
 
             if (indList) {
-                int offs = in_.read_long();
+                final int offs = in_.read_long();
                 if (offs > -4) {
-                    throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                            CompletionStatus.COMPLETED_NO);
                 }
                 saveList = buf_.pos_;
-                buf_.pos_ = buf_.pos_ - 4 + offs;
+                buf_.pos_ = (buf_.pos_ - 4) + offs;
                 if (buf_.pos_ < 0) {
-                    throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                            CompletionStatus.COMPLETED_NO);
                 }
-            } else
+            } else {
                 buf_.pos_ = saveList;
+            }
 
-            int count = in_.read_long();
+            final int count = in_.read_long();
             h.ids = new String[count];
 
             for (int i = 0; i < count; i++) {
@@ -468,20 +464,16 @@
                 int saveRep = buf_.pos_;
                 indTag = in_.read_long();
                 if (indTag == -1) {
-                    int offs = in_.read_long();
+                    final int offs = in_.read_long();
                     if (offs > -4) {
-                        throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                                CompletionStatus.COMPLETED_NO);
                     }
                     saveRep = buf_.pos_;
-                    buf_.pos_ = buf_.pos_ - 4 + offs;
+                    buf_.pos_ = (buf_.pos_ - 4) + offs;
                     if (buf_.pos_ < 0) {
-                        throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                            org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                        throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                                CompletionStatus.COMPLETED_NO);
                     }
                     h.ids[i] = in_.read_string();
                     buf_.pos_ = saveRep;
@@ -489,40 +481,38 @@
                     buf_.pos_ = saveRep;
                     h.ids[i] = in_.read_string();
                 }
-                logger.finer("Value header respoitory id added " + h.ids[i]); 
+                if (logger.isLoggable(Level.FINER))
+                    logger.finer(String.format("Value header respoitory id added \"%s\"", h.ids[i]));
             }
 
             //
             // Restore buffer position (case of indirected list)
             //
-            if (indList)
+            if (indList) {
                 buf_.pos_ = saveList;
+            }
         } else if ((h.tag & 0x00000006) == 2) {
             //
             // Extract a single repository ID
             //
-            String id;
+            final String id;
 
             //
             // Check for indirection tag
             //
             int save = buf_.pos_;
-            int indTag = in_.read_long();
+            final int indTag = in_.read_long();
             if (indTag == -1) {
-                int offs = in_.read_long();
+                final int offs = in_.read_long();
                 if (offs > -4) {
-                    throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                            CompletionStatus.COMPLETED_NO);
                 }
                 save = buf_.pos_;
-                buf_.pos_ = buf_.pos_ - 4 + offs;
+                buf_.pos_ = (buf_.pos_ - 4) + offs;
                 if (buf_.pos_ < 0) {
-                    throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorReadInvalidIndirection,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorReadInvalidIndirection), MinorCodes.MinorReadInvalidIndirection,
+                            CompletionStatus.COMPLETED_NO);
                 }
                 id = in_.read_string();
                 buf_.pos_ = save;
@@ -533,7 +523,8 @@
 
             h.ids = new String[1];
             h.ids[0] = id;
-            logger.finer("Single header repository id read " + id); 
+            if (logger.isLoggable(Level.FINER))
+                logger.finer(String.format("Single header repository id read \"%s\"", id));
         }
 
         //
@@ -544,16 +535,19 @@
         //
         // Add entry to header table
         //
-        headerTable_.put(new Integer(h.headerPos), h);
+        headerTable_.put(h.headerPos, h);
     }
 
     private void readChunk(ChunkState state) {
         //
         // Check for a chunk size
         //
-        int size = in_._OB_readLongUnchecked();
-        logger.finest("Reading new chunk.  Size value is " + Integer.toHexString(size) + " current nest is " + state.nestingLevel + " current position=" + buf_.pos_); 
-        if (size >= 0 && size < 0x7fffff00) // chunk size
+        final int size = in_._OB_readLongUnchecked();
+        if (logger.isLoggable(Level.FINEST))
+            logger.finest(String.format(
+                    "Reading new chunk.  Size value is 0x%x current nest is %d current position=0x%x",
+                    size, state.nestingLevel, buf_.pos_));
+        if ((size >= 0) && (size < 0x7fffff00)) // chunk size
         {
             state.chunkStart = buf_.pos_;
             state.chunkSize = size;
@@ -567,14 +561,16 @@
             state.chunkStart = 0;
             state.chunkSize = 0;
         }
-        logger.finest("Chunk read.  start=" + state.chunkStart + ", size=" + state.chunkSize + " buffer position=" + buf_.pos_); 
+        if (logger.isLoggable(Level.FINEST))
+            logger.finest(String.format("Chunk read.  start=0x%x, size=0x%x buffer position=0x%x",
+                    state.chunkStart, state.chunkSize, buf_.pos_));
     }
 
     private void initHeader(Header h) {
         //
         // Null values and indirections must be handled by caller
         //
-        Assert._OB_assert(h.tag != 0 && h.tag != -1);
+        Assert._OB_assert((h.tag != 0) && (h.tag != -1));
 
         h.headerPos = buf_.pos_ - 4; // adjust for alignment
         h.state.copyFrom(chunkState_);
@@ -589,16 +585,18 @@
         // Increment our nesting level if we are chunked
         //
         if (chunkState_.chunked) {
-//          logger.finest("Reading chunk for chunked value.  Header tag=" + Integer.toHexString(h.tag) + " current position=" + buf_.pos_); 
+//          logger.finest("Reading chunk for chunked value.  Header tag=" + Integer.toHexString(h.tag) + " current position=" + buf_.pos_);
             readChunk(chunkState_);
             chunkState_.nestingLevel++;
-//          logger.fine("Chunk nesting level is " + chunkState_.nestingLevel + " current position=" + buf_.pos_ + " chunk size=" + chunkState_.chunkSize); 
+//          logger.fine("Chunk nesting level is " + chunkState_.nestingLevel + " current position=" + buf_.pos_ + " chunk size=" + chunkState_.chunkSize);
         }
     }
 
     private void skipChunk() {
         if (chunkState_.chunked) {
-            logger.fine("Skipping a chunked value.  nesting level=" + chunkState_.nestingLevel + " current position is " + buf_.pos_ + " chunk end is " + (chunkState_.chunkStart + chunkState_.chunkSize)); 
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format("Skipping a chunked value.  nesting level=%d current position is 0x%x chunk end is 0x%x",
+                        chunkState_.nestingLevel, buf_.pos_, (chunkState_.chunkStart + chunkState_.chunkSize)));
             //
             // At this point, the unmarshalling code has finished. However,
             // we may have a truncated value, or we may have unmarshalled a
@@ -616,7 +614,8 @@
             if (chunkState_.chunkStart > 0) {
                 buf_.pos_ = chunkState_.chunkStart;
                 in_._OB_skip(chunkState_.chunkSize);
-                logger.finest("Skipping to end of current chunk.  New position is " + buf_.pos_); 
+                if (logger.isLoggable(Level.FINEST))
+                    logger.finest(String.format("Skipping to end of current chunk.  New position is 0x%x", buf_.pos_));
             }
 
             chunkState_.chunkStart = 0;
@@ -628,42 +627,47 @@
             //
             int level = chunkState_.nestingLevel;
             int tag = in_._OB_readLongUnchecked();
-            logger.finest("Skipping chunk:  read tag value =" + tag); 
-            while (tag >= 0 || (tag < 0 && tag < -chunkState_.nestingLevel)) {
+            if (logger.isLoggable(Level.FINEST))
+                logger.finest(String.format("Skipping chunk:  read tag value =0x%08x", tag));
+            while ((tag >= 0) || ((tag < 0) && (tag < -chunkState_.nestingLevel))) {
                 if (tag >= 0x7fffff00) {
-                    logger.finest("Skipping chunk:  reading a nested chunk value"); 
+                    logger.finest("Skipping chunk:  reading a nested chunk value");
                     //
                     // This indicates a nested value. We read the header
                     // information and store it away, in case a subsequent
                     // indirection refers to this value.
                     //
                     level++;
-                    Header nest = new Header();
+                    final Header nest = new Header();
                     nest.tag = tag;
                     nest.headerPos = buf_.pos_ - 4; // adjust for alignment
                     nest.state.nestingLevel = level;
                     readHeader(nest);
                 } else if (tag >= 0) {
-                    logger.finest("Skipping chunk:  skipping over a chunk for length " +tag); 
+                    if (logger.isLoggable(Level.FINEST))
+                        logger.finest(String.format("Skipping chunk:  skipping over a chunk for length 0x%x", tag));
                     //
                     // Chunk size - advance the stream past the chunk
                     //
                     in_._OB_skip(tag);
                 } else {
-                    logger.finest("Skipping chunk:  chunk end tag=" + Integer.toHexString(tag) + " current level=" + level); 
+                    if (logger.isLoggable(Level.FINEST))
+                        logger.finest(String.format("Skipping chunk:  chunk end tag=0x%08x current level=%d",
+                                tag, level));
                     //
                     // tag is less than 0, so this is an end tag for a nested
                     // value
                     //
-                    // this can terminate more than a single level. 
-                    level = (-tag) - 1; 
+                    // this can terminate more than a single level.
+                    level = (-tag) - 1;
                 }
 
                 //
                 // Read the next tag
                 //
                 tag = in_._OB_readLongUnchecked();
-                logger.finest("Skipping chunk:  read tag value =" + tag); 
+                if (logger.isLoggable(Level.FINEST))
+                    logger.finest(String.format("Skipping chunk:  read tag value=0x%08x", tag));
             }
 
             //
@@ -677,20 +681,23 @@
 
             chunkState_.nestingLevel--;
 
-            logger.finest("New chunk nesting level is " + chunkState_.nestingLevel); 
+            if (logger.isLoggable(Level.FINEST))
+                logger.finest(String.format("New chunk nesting level is %d", chunkState_.nestingLevel));
             if (chunkState_.nestingLevel == 0) {
                 chunkState_.chunked = false;
-            }
-            else {
+            } else {
                 //
                 // We're chunked and still processing nested values, so
                 // another chunk may follow
                 //
-                logger.finest("Reading chunk for skipping to end of a chunk"); 
+                logger.finest("Reading chunk for skipping to end of a chunk");
                 readChunk(chunkState_);
             }
-            
-            logger.finest("Final chunk state is nesting level=" + chunkState_.nestingLevel + " current position is " + buf_.pos_ + " chunk end is " + (chunkState_.chunkStart + chunkState_.chunkSize)); 
+
+            if (logger.isLoggable(Level.FINEST))
+                logger.finest(String.format(
+                        "Final chunk state is nesting level=%d current position is 0x%x chunk end is 0x%x",
+                        chunkState_.nestingLevel, buf_.pos_, (chunkState_.chunkStart + chunkState_.chunkSize)));
         }
     }
 
@@ -699,26 +706,23 @@
     //
     // Java only
     //
-    private void unmarshalValueState(java.io.Serializable v) {
-        if (v instanceof org.omg.CORBA.portable.StreamableValue) {
-            ((org.omg.CORBA.portable.StreamableValue) v)._read(in_);
-        }
-        else if (v instanceof org.omg.CORBA.CustomMarshal) {
-            org.omg.CORBA.DataInputStream dis = new org.apache.yoko.orb.CORBA.DataInputStream(
-                    in_);
-            ((org.omg.CORBA.CustomMarshal) v).unmarshal(dis);
+    private void unmarshalValueState(Serializable v) {
+        if (v instanceof StreamableValue) {
+            ((StreamableValue) v)._read(in_);
+        } else if (v instanceof CustomMarshal) {
+            final DataInputStream dis = new org.apache.yoko.orb.CORBA.DataInputStream(in_);
+            ((CustomMarshal) v).unmarshal(dis);
         } else {
-            throw new org.omg.CORBA.MARSHAL("Valuetype does not implement "
-                    + "StreamableValue or " + "CustomMarshal");
+            throw new MARSHAL("Valuetype does not implement " + "StreamableValue or " + "CustomMarshal");
         }
     }
 
-    private java.io.Serializable readIndirection(CreationStrategy strategy) {
-        int offs = in_.read_long();
-        int pos = buf_.pos_ - 4 + offs;
+    private Serializable readIndirection(CreationStrategy strategy) {
+        final int offs = in_.read_long();
+        int pos = (buf_.pos_ - 4) + offs;
         pos += 3; // adjust for alignment
         pos -= (pos & 0x3);
-        Integer posObj = new Integer(pos);
+        final Integer posObj = pos;
 
         //
         // Check the history for a value that was seen at the specified
@@ -728,13 +732,12 @@
         // of an enclosing value, or to a value that we could not
         // instantiate.
         //
-        java.io.Serializable v = (java.io.Serializable) instanceTable_
-                .get(posObj);
+        Serializable v = (Serializable) instanceTable_.get(posObj);
 
         if (v != null) {
             return v;
         } else {
-            int save = buf_.pos_;
+            final int save = buf_.pos_;
 
             //
             // Check for indirection to null value
@@ -751,33 +754,31 @@
             // If it's not null and it's not in our history, then
             // there's no hope
             //
-            Header nest = (Header) headerTable_.get(posObj);
+            final Header nest = headerTable_.get(posObj);
 
-            if (nest == null)
-                throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory)
-                        + ": cannot instantiate value for indirection",
-                        org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            if (nest == null) {
+                throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorNoValueFactory) + ": cannot instantiate value for indirection",
+                        MinorCodes.MinorNoValueFactory, CompletionStatus.COMPLETED_NO);
+            }
 
-            /* Maybe we have an indirection to an object
-             * that is being deserialized. We throw an
-             * IndirectionException which signals the RMI
-             * implementation to handle the indirection.
+            /*
+             * Maybe we have an indirection to an object that is being
+             * deserialized. We throw an IndirectionException which signals the
+             * RMI implementation to handle the indirection.
              */
-            if(nest.isRMIValue()) {
-            	buf_.pos_ = save;
-            	throw new IndirectionException(pos);
+            if (nest.isRMIValue()) {
+                buf_.pos_ = save;
+                throw new IndirectionException(pos);
             }
             //
             // Create the value
             //
             buf_.pos_ = nest.dataPos;
-            ChunkState saveState = new ChunkState(chunkState_);
+            final ChunkState saveState = new ChunkState(chunkState_);
             chunkState_.copyFrom(nest.state);
-            if (chunkState_.chunked)
-//              logger.finest("Reading chunk in readIndirection()"); 
+            if (chunkState_.chunked) {
                 readChunk(chunkState_);
+            }
 
             try {
                 v = strategy.create(nest);
@@ -797,49 +798,79 @@
         Header h = new Header();
         h.tag = in_.read_long();
 
-//      logger.fine("Read tag value " + Integer.toHexString(h.tag)); 
+//      logger.fine("Read tag value " + Integer.toHexString(h.tag));
         if (h.tag == 0) {
             return null;
         } else if (h.tag == -1) {
             return readIndirection(strategy);
         } else if (h.tag < 0x7fffff00) {
-            throw new org.omg.CORBA.MARSHAL("Illegal valuetype tag 0x"
-                    + Integer.toHexString(h.tag));
+            throw new org.omg.CORBA.MARSHAL(String.format(
+                    "Illegal valuetype tag 0x%08x",
+                    h.tag));
         } else {
             initHeader(h);
-            java.io.Serializable vb = strategy.create(h);
+            // read_value() may be called to skip over a secondary custom valuetype.
+            // If so, return an internal marker object so it shows up if misused.
+            final Serializable result = isSecondaryCustomValuetype(h) ?
+                    SecondaryValuetypeMarker.ATTEMPT_TO_READ_CUSTOM_DATA_AS_VALUE
+                    : strategy.create(h);
             skipChunk();
-            return vb;
+            return result;
         }
     }
 
+    private enum SecondaryValuetypeMarker {
+        ATTEMPT_TO_READ_CUSTOM_DATA_AS_VALUE
+    }
+
+    private boolean isSecondaryCustomValuetype(Header h) {
+        // there must be exactly one repository ID
+        if (h.ids.length != 1)
+            return false;
+
+        // the repository ID must start with one of the Java-to-IDL spec prefixes
+        final String repId = h.ids[0];
+        if (!(repId.startsWith("RMI:org.omg.custom.") || repId.startsWith("RMI:org.omg.customRMI.")))
+            return false;
+
+        // it matched enough of the rules, so treat it as a secondary custom valuetype
+
+        // there should not be a codebase (tolerate but log this)
+        if (h.codebase != null) {
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format(
+                        "Secondary custom marshal valuetype found with non-null codebase: \"%s\", repId: \"%s\"",
+                        h.codebase, repId));
+        }
+
+        return true;
+    }
+
     //
     // Remarshal each valuetype member
     //
-    private void copyValueState(org.omg.CORBA.TypeCode tc, org.apache.yoko.orb.CORBA.OutputStream out) {
+    private void copyValueState(TypeCode tc, OutputStream out) {
         try {
-            if (tc.kind() == org.omg.CORBA.TCKind.tk_value) {
+            if (tc.kind() == TCKind.tk_value) {
                 //
                 // First copy the state of the concrete base type, if any
                 //
-                org.omg.CORBA.TypeCode base = tc.concrete_base_type();
+                final TypeCode base = tc.concrete_base_type();
                 if (base != null) {
                     copyValueState(base, out);
                 }
 
                 for (int i = 0; i < tc.member_count(); i++) {
-//                  logger.fine("writing member of typecode " + tc.member_type(i).kind().value()); 
+//                  logger.fine("writing member of typecode " + tc.member_type(i).kind().value());
                     out.write_InputStream(in_, tc.member_type(i));
                 }
-            } else if (tc.kind() == org.omg.CORBA.TCKind.tk_value_box) {
+            } else if (tc.kind() == TCKind.tk_value_box) {
                 out.write_InputStream(in_, tc.content_type());
-            } else
+            } else {
                 Assert._OB_assert(false);
-        } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            logger.log(Level.FINER, "Invalid type kind", ex); 
-            Assert._OB_assert(ex);
-        } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            logger.log(Level.FINER, "Invalid type kind", ex); 
+            }
+        } catch (BadKind | Bounds ex) {
+            logger.log(Level.FINER, "Invalid type kind", ex);
             Assert._OB_assert(ex);
         }
     }
@@ -861,26 +892,23 @@
     // Search up the valuetype's inheritance hierarchy for a TypeCode
     // with the given repository ID
     //
-    private org.omg.CORBA.TypeCode findTypeCode(String id,
-            org.omg.CORBA.TypeCode tc) {
-        org.omg.CORBA.TypeCode result = null;
-        org.omg.CORBA.TypeCode t = tc;
-//      logger.finer("Locating type code for id " + id); 
+    private TypeCode findTypeCode(String id, TypeCode tc) {
+        TypeCode result = null;
+        TypeCode t = tc;
+//      logger.finer("Locating type code for id " + id);
         while (result == null) {
             try {
-                org.omg.CORBA.TypeCode t2 = org.apache.yoko.orb.CORBA.TypeCode
-                        ._OB_getOrigType(t);
-//              logger.finer("Checking typecode " + id + " against " + t2.id()); 
+                final TypeCode t2 = org.apache.yoko.orb.CORBA.TypeCode._OB_getOrigType(t);
+//              logger.finer("Checking typecode " + id + " against " + t2.id());
                 if (id.equals(t2.id())) {
                     result = t;
-                } else if (t2.kind() == org.omg.CORBA.TCKind.tk_value
-                        && t2.type_modifier() == org.omg.CORBA.VM_TRUNCATABLE.value) {
+                } else if ((t2.kind() == TCKind.tk_value) && (t2.type_modifier() == VM_TRUNCATABLE.value)) {
                     t = t2.concrete_base_type();
-//                  logger.finer("Iterating with concrete type " + t.id()); 
+//                  logger.finer("Iterating with concrete type " + t.id());
                 } else {
                     break;
                 }
-            } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
+            } catch (BadKind ex) {
                 Assert._OB_assert(ex);
             }
         }
@@ -892,195 +920,190 @@
     // Public methods
     // ------------------------------------------------------------------
 
-    public ValueReader(org.apache.yoko.orb.CORBA.InputStream in) {
+    public ValueReader(InputStream in) {
         in_ = in;
         buf_ = in._OB_buffer();
         orbInstance_ = in._OB_ORBInstance();
-        instanceTable_ = new java.util.Hashtable(131);
-        headerTable_ = new java.util.Hashtable(131);
+        instanceTable_ = new Hashtable<Integer, Serializable>(131);
+        headerTable_ = new Hashtable<Integer, Header>(131);
     }
 
-    java.io.Serializable readRMIValue(Header h, Class clz, String repid)
-    {
-        logger.fine("Reading RMI value of type " + repid); 
+    private Serializable readRMIValue(Header h, Class<? extends Serializable> clz, String repid) {
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Reading RMI value of type \"%s\"", repid));
         if (valueHandler == null) {
-            valueHandler = javax.rmi.CORBA.Util.createValueHandler ();
+            valueHandler = javax.rmi.CORBA.Util.createValueHandler();
         }
 
         if (repid == null) {
             repid = h.ids[0];
 
             if (repid == null) {
-                throw new org.omg.CORBA.MARSHAL("missing repository id");
+                throw new MARSHAL("missing repository id");
             }
         }
 
-        String className = Util.idToClassName (repid, "");
+        final String className = RepIds.query(repid).toClassName();
         String codebase  = h.codebase;
-        Class repoClass = null;
 
         if (codebase == null) {
-            codebase = in_.__getCodeBase ();
+            codebase = in_.__getCodeBase();
         }
 
-        repoClass = resolveRepoClass(className, codebase);
+        Class repoClass = resolveRepoClass(className, codebase);
 
-        // if we have a non-null codebase and can't resolve this, throw an 
-        // exception now.  Otherwise, we'll try again after grabbing the remote 
-        // codebase. 
-        if (repoClass == null && codebase != null && codebase.length() > 0) {
-            throw new org.omg.CORBA.MARSHAL("class "+className
-                                            +" not found (cannot load from "+codebase+")");
+        // if we have a non-null codebase and can't resolve this, throw an
+        // exception now.  Otherwise, we'll try again after grabbing the remote
+        // codebase.
+        if ((repoClass == null) && (codebase != null) && !codebase.isEmpty()) {
+            throw new MARSHAL("class " + className + " not found (cannot load from " + codebase + ")");
         }
 
         if (remoteCodeBase == null) {
-            remoteCodeBase = in_.__getSendingContextRuntime ();
+            remoteCodeBase = in_.__getSendingContextRuntime();
         }
         if (repoClass == null) {
-            if (codebase == null && remoteCodeBase != null) {
+            if ((codebase == null) && (remoteCodeBase != null)) {
                 try {
-                    codebase = remoteCodeBase.implementation (repid);
-                } catch (org.omg.CORBA.SystemException ex) {
-                    // ignore
+                    codebase = remoteCodeBase.implementation(repid);
+                } catch (SystemException ignored) {
                 }
 
             }
 
             if (codebase == null) {
                 // TODO: add minor code
-                throw new org.omg.CORBA.MARSHAL
-                ("class "+className+" not found (no codebase provided)");
+                throw new MARSHAL("class " + className + " not found (no codebase provided)");
             } else {
-                repoClass = resolveRepoClass(className, codebase); 
+                repoClass = resolveRepoClass(className, codebase);
                 if (repoClass == null) {
-                    throw new org.omg.CORBA.MARSHAL("class "+className+" not found (cannot load from " + codebase+ ")");
+                    throw new MARSHAL("class " + className + " not found (cannot load from " + codebase + ")");
                 }
             }
         }
 
-        /* Suns crappy ValueHandler implementation narrows the remote CodeBase 
-         * to a com.sun.org.omg.SendingContext.CodeBase.
-         * Narrowing CodeBaseProxy is not possible, we
-         * need a stub.
+        /*
+         * Suns crappy ValueHandler implementation narrows the remote CodeBase
+         * to a com.sun.org.omg.SendingContext.CodeBase. Narrowing CodeBaseProxy
+         * is not possible, we need a stub.
          */
         if (remoteCodeBase instanceof CodeBaseProxy) {
             remoteCodeBase = ((CodeBaseProxy) remoteCodeBase).getCodeBase();
         }
-        
-        java.io.Serializable serobj = null;
+
+        Serializable serobj = null;
         try {
-        	serobj = valueHandler.readValue(in_, h.headerPos, repoClass, repid, remoteCodeBase);
+            serobj = valueHandler.readValue(in_, h.headerPos, repoClass, repid, remoteCodeBase);
         } catch (RuntimeException ex) {
-            logger.log(Level.FINE, "RuntimeException happens when reading GIOP stream coming to pos_=" + in_.buf_.pos_);
-            logger.log(Level.FINE, "Wrong data section: \n" + in_.dumpData());
-            int currentpos = in_.buf_.pos_;
-            in_.buf_.pos_ = 0;
-            logger.log(Level.FINE, "Full GIOP stream dump: \n" + in_.dumpData());
-            in_.buf_.pos_ = currentpos;
+            if (logger.isLoggable(Level.FINE)) {
+                logger.fine(String.format(
+                        "RuntimeException happens when reading GIOP stream coming to pos_=0x%x",
+                        in_.buf_.pos_));
+                logger.fine(String.format("Wrong data section:%n%s", in_.dumpData()));
+                final int currentpos = in_.buf_.pos_;
+                in_.buf_.pos_ = 0;
+                logger.fine(String.format("Full GIOP stream dump:%n%s", in_.dumpData()));
+                in_.buf_.pos_ = currentpos;
+            }
             throw ex;
         }
 
         return serobj;
     }
-    
-    private Class resolveRepoClass(String name, String codebase) 
-    {
-        logger.fine("Attempting to resolve class " + name + " from codebase " + codebase);
+
+    private Class resolveRepoClass(String name, String codebase) {
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format(
+                    "Attempting to resolve class \"%s\" from codebase \"%s\"",
+                    name, codebase));
         if (name.startsWith("[")) {
-            int levels = 0; 
+            int levels = 0;
             for (int i = 0; name.charAt(i) == '['; i++) {
-                levels++; 
+                levels++;
             }
-            Class elementClass = null; 
-            
-            // now resolve the element descriptor to a class 
+            Class elementClass = null;
+
+            // now resolve the element descriptor to a class
             switch (name.charAt(levels)) {
                 case 'Z':
                     elementClass = Boolean.TYPE;
-                    break; 
+                    break;
                 case 'B':
                     elementClass = Byte.TYPE;
-                    break; 
+                    break;
                 case 'S':
                     elementClass = Short.TYPE;
-                    break; 
+                    break;
                 case 'C':
                     elementClass = Character.TYPE;
-                    break; 
+                    break;
                 case 'I':
                     elementClass = Integer.TYPE;
-                    break; 
+                    break;
                 case 'J':
                     elementClass = Long.TYPE;
-                    break; 
+                    break;
                 case 'F':
                     elementClass = Float.TYPE;
-                    break; 
+                    break;
                 case 'D':
                     elementClass = Double.TYPE;
-                    break; 
+                    break;
                 case 'L':
                     // extract the class from the name and resolve that.
                     elementClass = resolveRepoClass(name.substring(levels + 1, name.indexOf(';')), codebase);
                     if (elementClass == null) {
-                        return null; 
+                        return null;
                     }
-                    break; 
+                    break;
             }
-            
+
             // ok, we need to recurse and resolve the base array element class
-            Object arrayInstance = null;
-            // this is easier with a single level     
+            Object arrayInstance;
+            // this is easier with a single level
             if (levels == 1) {
-                arrayInstance = Array.newInstance(elementClass, 0); 
+                arrayInstance = Array.newInstance(elementClass, 0);
+            } else {
+                // all elements will be zero
+                final int[] dimensions = new int[levels];
+                arrayInstance = Array.newInstance(elementClass, dimensions);
             }
-            else {
-                // all elements will be zero 
-                int[] dimensions = new int[levels]; 
-                arrayInstance = Array.newInstance(elementClass, dimensions); 
-            }
-            // return the class associated with this array 
+            // return the class associated with this array
             return arrayInstance.getClass();
-        }
-        else {
-            try
-            {
-                return javax.rmi.CORBA.Util.loadClass(name, codebase,
-                     Util.getContextClassLoader());
-            }
-            catch (ClassNotFoundException ex)
-            {
-                // this will be sorted out later 
-                return null; 
+        } else {
+            try {
+                return javax.rmi.CORBA.Util.loadClass(name, codebase, Util.getContextClassLoader());
+            } catch (ClassNotFoundException ex) {
+                // this will be sorted out later
+                return null;
             }
         }
     }
 
-    public java.io.Serializable readValue() {
-        FactoryCreationStrategy strategy = new FactoryCreationStrategy(this,
-                in_, null);
+    public Serializable readValue() {
+        final FactoryCreationStrategy strategy = new FactoryCreationStrategy(this, in_, null);
         return read(strategy);
     }
 
-    public java.io.Serializable readValue(String id) {
-        logger.fine("Reading value of type " + id); 
-        FactoryCreationStrategy strategy = new FactoryCreationStrategy(this,
-                in_, id);
+    public Serializable readValue(String id) {
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Reading value of type \"%s\"", id));
+        final FactoryCreationStrategy strategy = new FactoryCreationStrategy(this, in_, id);
         return read(strategy);
     }
 
-    public java.io.Serializable readValue(Class clz) {
-        logger.fine("Reading value of type " + clz.getName()); 
-    	if(clz.equals(String.class)) {
-    		return WStringValueHelper.read(in_);
-    	}
-        ClassCreationStrategy strategy = new ClassCreationStrategy(this, in_,
-                clz);
-        java.io.Serializable result = null;
+    public Serializable readValue(Class<? extends Serializable> clz) {
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Reading value of type \"%s\"", clz.getName()));
+        if (clz.equals(String.class)) {
+            return WStringValueHelper.read(in_);
+        }
+        final ClassCreationStrategy strategy = new ClassCreationStrategy(this, in_, clz);
+        Serializable result;
         try {
             result = read(strategy);
-        } catch (org.omg.CORBA.MARSHAL marshalex) {
-            logger.severe(marshalex.getMessage() + " at pos=" + (in_.buf_.pos_- 4));
+        } catch (MARSHAL marshalex) {
+            logger.severe(String.format("MARSHAL \"%s\", at pos=0x%x", marshalex.getMessage(), (in_.buf_.pos_ - 4)));
             if ("true".equalsIgnoreCase(System.getProperty("org.apache.yoko.ignoreInvalidValueTag"))) {
                 result = read(strategy);
             } else {
@@ -1090,14 +1113,12 @@
         return result;
     }
 
-    public java.io.Serializable readValueBox(
-            org.omg.CORBA.portable.BoxedValueHelper helper) {
-        BoxCreationStrategy strategy = new BoxCreationStrategy(this, in_,
-                helper);
+    public Serializable readValueBox(BoxedValueHelper helper) {
+        final BoxCreationStrategy strategy = new BoxCreationStrategy(this, in_, helper);
         return read(strategy);
     }
 
-    public void initializeValue(java.io.Serializable value) {
+    public void initializeValue(Serializable value) {
         //
         // We should have previously pushed a Header on the stack
         //
@@ -1113,35 +1134,37 @@
         //
         try {
             unmarshalValueState(value);
-        } catch (org.omg.CORBA.SystemException ex) {
+        } catch (SystemException ex) {
             removeInstance(currentHeader_.headerPos);
             throw ex;
         }
     }
 
-    public java.lang.Object readAbstractInterface() {
+    public Object readAbstractInterface() {
         //
         // Abstract interfaces are marshalled like a union with a
         // boolean discriminator - if true, an objref follows,
         // otherwise a valuetype follows
         //
-        if (in_.read_boolean())
+        if (in_.read_boolean()) {
             return in_.read_Object();
-        else
+        } else {
             return readValue();
     }
+    }
 
-    public java.lang.Object readAbstractInterface(Class clz) {
+    public Object readAbstractInterface(Class clz) {
         //
         // Abstract interfaces are marshalled like a union with a
         // boolean discriminator - if true, an objref follows,
         // otherwise a valuetype follows
         //
-        if (in_.read_boolean())
+        if (in_.read_boolean()) {
             return in_.read_Object(clz);
-        else
+        } else {
             return readValue(clz);
     }
+    }
 
     //
     // Copy a value from out InputStream to the given OutputStream.
@@ -1151,8 +1174,7 @@
     // may not represent the actual most-derived type, since a more-derived
     // value may have been read.
     //
-    public org.omg.CORBA.TypeCode remarshalValue(org.omg.CORBA.TypeCode tc,
-            org.apache.yoko.orb.CORBA.OutputStream out) {
+    public TypeCode remarshalValue(TypeCode tc, OutputStream out) {
         //
         // TODO: We've removed the reset of the position table at each top
         // level call. We need to perform more testing and analysis to verify
@@ -1164,29 +1186,28 @@
         // Create a new Hashtable for each top-level call to remarshalValue
         //
         if (positionTable_ == null) {
-            positionTable_ = new java.util.Hashtable(131);
+            positionTable_ = new Hashtable<Integer, Integer>(131);
         }
 
-        org.omg.CORBA.TypeCode origTC = org.apache.yoko.orb.CORBA.TypeCode
-                ._OB_getOrigType(tc);
+        final TypeCode origTC = org.apache.yoko.orb.CORBA.TypeCode._OB_getOrigType(tc);
 
-        org.omg.CORBA.TypeCode result = null;
-
-        Header h = new Header();
+        final Header h = new Header();
         h.tag = in_.read_long();
-        
-        logger.fine("Read tag value " + Integer.toHexString(h.tag)); 
+
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Read tag value 0x%08x", h.tag));
         h.headerPos = buf_.pos_ - 4; // adjust for alignment
         h.state.copyFrom(chunkState_);
 
         //
         // Remember starting position of this valuetype
         //
-        int pos = h.headerPos;
+        final int pos = h.headerPos;
 
         //
         // Check for special cases (null values and indirections)
         //
+        TypeCode result;
         if (h.tag == 0) {
             out.write_long(0);
             result = tc;
@@ -1196,7 +1217,7 @@
             // output stream, we use a table to map old positions to new ones
             //
             int offs = in_.read_long();
-            int oldPos = buf_.pos_ - 4 + offs;
+            int oldPos = (buf_.pos_ - 4) + offs;
             oldPos += 3; // adjust alignment to start of value
             oldPos -= (oldPos & 0x3);
 
@@ -1206,33 +1227,35 @@
             // to a valuetype that we were unable to create and we therefore
             // raise MARSHAL.
             //
-            Integer newPos = (Integer) positionTable_.get(new Integer(oldPos));
+            @SuppressWarnings("UnnecessaryBoxing")
+            final Integer newPos = positionTable_.get(oldPos);
             if (newPos != null) {
                 out.write_long(h.tag);
-                offs = newPos.intValue() - out._OB_pos();
+                offs = newPos - out._OB_pos();
                 out.write_long(offs);
                 //
                 // TODO: The TypeCode may not necessarily reflect the
                 // TypeCode of the indirected value.
                 //
                 result = tc;
-            } else
-                throw new org.omg.CORBA.MARSHAL(
-                        "Cannot find value for indirection");
+        } else {
+                throw new MARSHAL("Cannot find value for indirection");
+            }
         } else {
             if (h.tag < 0x7fffff00) {
-                throw new org.omg.CORBA.MARSHAL("Illegal valuetype tag 0x" + Integer.toHexString(h.tag));
+                throw new MARSHAL("Illegal valuetype tag 0x" + Integer.toHexString(h.tag));
             }
-            
-            logger.fine("Remarshalling header with tag value " + h.tag); 
-            
+
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format("Remarshalling header with tag value 0x%08x", h.tag));
+
             //
             // Add valuetype to position map
             //
             int outPos = out._OB_pos();
             outPos += 3; // adjust alignment to start of value
             outPos -= (outPos & 0x3);
-            positionTable_.put(new Integer(pos), new Integer(outPos));
+            positionTable_.put(pos, outPos);
 
             //
             // Read value header info
@@ -1241,19 +1264,19 @@
             chunkState_.copyFrom(h.state);
 
             if (chunkState_.chunked) {
-                logger.finest("Reading chunk in remarshal value()"); 
+                logger.finest("Reading chunk in remarshal value()");
                 readChunk(chunkState_);
                 chunkState_.nestingLevel++;
             }
 
             String tcId = null;
-            short mod = org.omg.CORBA.VM_NONE.value;
-            int idPos;
+            short mod = VM_NONE.value;
             try {
                 tcId = origTC.id();
-                if (origTC.kind() == org.omg.CORBA.TCKind.tk_value)
+                if (origTC.kind() == TCKind.tk_value) {
                     mod = origTC.type_modifier();
-            } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
+                }
+            } catch (BadKind ex) {
                 Assert._OB_assert(ex);
             }
 
@@ -1274,32 +1297,43 @@
             // OutputStream.
             //
 
-            logger.fine("Attempting to resolve typeId " + tcId); 
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format("Attempting to resolve typeId \"%s\"", tcId));
             //
             // See if the TypeCode ID matches any of the valuetype's IDs -
             // stop at the first match
             //
             String id = null;
+            int idPos;
             for (idPos = 0; idPos < h.ids.length; idPos++) {
-                logger.finer("Comparing type id " + tcId + " against " + h.ids[idPos]); 
+                if (logger.isLoggable(Level.FINER))
+                    logger.finer(String.format(
+                            "Comparing type id \"%s\" against \"%s\"",
+                            tcId, h.ids[idPos]));
                 if (tcId.equals(h.ids[idPos])) {
                     id = h.ids[idPos];
                     break;
                 }
             }
-            
+
             // if this is null, then try again to see if we can find a class in the ids list
             // that is compatible with the base type.  This will require resolving the classes.
             if (id == null) {
-                // see if we can resolve the type for the stored type code 
-                Class baseType = Util.idToClass(tcId, ""); 
+                // see if we can resolve the type for the stored type code
+                final Class<?> baseType = RepIds.query(tcId).toClass();
                 if (baseType != null) {
                     for (idPos = 0; idPos < h.ids.length; idPos++) {
-                        logger.finer("Comparing type id " + tcId + " against " + h.ids[idPos]); 
-                        Class idType = Util.idToClass(h.ids[idPos], "");
+                        if (logger.isLoggable(Level.FINER))
+                            logger.finer(String.format(
+                                    "Considering base types of id \"%s\" against \"%s\"",
+                                    tcId, h.ids[idPos]));
+                        final Class idType = RepIds.query(h.ids[idPos]).toClass();
                         if (idType != null) {
-                            // if these classes are assignment compatible, go with that as the type. 
-                            logger.finer("Comparing type id " + baseType.getName() + " against " + idType.getName()); 
+                            // if these classes are assignment compatible, go with that as the type.
+                            if (logger.isLoggable(Level.FINER))
+                                logger.finer(String.format(
+                                        "Comparing type id \"%s\" against \"%s\"",
+                                        baseType.getName(), idType.getName()));
                             if (baseType.isAssignableFrom(idType)) {
                                 id = h.ids[idPos];
                                 break;
@@ -1315,14 +1349,12 @@
             //
             String factoryId = null;
             int factoryPos = 0;
-            org.omg.CORBA.portable.ValueFactory factory = null;
+            ValueFactory factory = null;
             if (orbInstance_ != null) {
-                ValueFactoryManager manager = orbInstance_
-                        .getValueFactoryManager();
+                final ValueFactoryManager manager = orbInstance_.getValueFactoryManager();
 
                 for (factoryPos = 0; factoryPos < h.ids.length; factoryPos++) {
-                    factory = manager
-                            .lookupValueFactoryWithClass(h.ids[factoryPos]);
+                    factory = manager.lookupValueFactoryWithClass(h.ids[factoryPos]);
                     if (factory != null) {
                         factoryId = h.ids[factoryPos];
                         break;
@@ -1334,25 +1366,20 @@
             // If no ID matched the TypeCode, and no factory was found,
             // then we have no way to remarshal the data
             //
-            if (h.ids.length > 0 && id == null && factoryId == null) {
-                logger.fine("Unable to resolve a factory for type " + tcId); 
-                throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory)
-                        + ": insufficient information to copy valuetype",
-                        org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            if ((h.ids.length > 0) && (id == null) && (factoryId == null)) {
+                if (logger.isLoggable(Level.FINE))
+                    logger.fine(String.format("Unable to resolve a factory for type \"%s\"", tcId));
+                throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorNoValueFactory) + ": insufficient information to copy valuetype",
+                        MinorCodes.MinorNoValueFactory, CompletionStatus.COMPLETED_NO);
             }
 
             //
             // If value is custom and there is no factory, then we have
             // no way to remarshal the data
             //
-            if (mod == org.omg.CORBA.VM_CUSTOM.value && factoryId == null) {
-                throw new org.omg.CORBA.MARSHAL(org.apache.yoko.orb.OB.MinorCodes
-                        .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory)
-                        + ": unable to copy custom valuetype",
-                        org.apache.yoko.orb.OB.MinorCodes.MinorNoValueFactory,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            if ((mod == VM_CUSTOM.value) && (factoryId == null)) {
+                throw new MARSHAL(MinorCodes.describeMarshal(MinorCodes.MinorNoValueFactory) + ": unable to copy custom valuetype",
+                        MinorCodes.MinorNoValueFactory, CompletionStatus.COMPLETED_NO);
             }
 
             //
@@ -1364,20 +1391,17 @@
             // because we don't have the BoxedHelper and may not be
             // able to locate one via the class loader.
             //
-            if (idPos < factoryPos || h.ids.length == 0
-                    || origTC.kind() == org.omg.CORBA.TCKind.tk_value_box) {
-                int i;
+            if ((idPos < factoryPos) || (h.ids.length == 0) || (origTC.kind() == TCKind.tk_value_box)) {
 
                 //
                 // We may need to truncate the state of this value, which
                 // means we need to revise the list of repository IDs
                 //
-                int numIds = h.ids.length - idPos;
-                String[] ids = new String[numIds];
-                for (i = idPos; i < h.ids.length; i++)
-                    ids[i - idPos] = h.ids[i];
+                final int numIds = h.ids.length - idPos;
+                final String[] ids = new String[numIds];
+                System.arraycopy(h.ids, idPos, ids, idPos - idPos, h.ids.length - idPos);
 
-                logger.fine("Copying value state of object using truncated type"); 
+                logger.fine("Copying value state of object using truncated type");
                 out._OB_beginValue(h.tag, ids, h.state.chunked);
                 copyValueState(origTC, out);
                 out._OB_endValue();
@@ -1389,8 +1413,8 @@
                 //
                 try {
                     pushHeader(h);
-                    java.io.Serializable vb = factory.read_value(in_);
-                    logger.fine("Creating a temporary copy of the object for marshalling"); 
+                    final Serializable vb = factory.read_value(in_);
+                    logger.fine("Creating a temporary copy of the object for marshalling");
                     try {
                         out.write_value(vb);
                     } finally {
@@ -1406,9 +1430,10 @@
                 //
                 result = findTypeCode(h.ids[factoryPos], tc);
 
-                if (result == null)
+                if (result == null) {
                     result = tc;
             }
+            }
 
             skipChunk();
         }
@@ -1417,7 +1442,7 @@
         return result;
     }
 
-    public void readValueAny(org.omg.CORBA.Any any, org.omg.CORBA.TypeCode tc) {
+    public void readValueAny(Any any, TypeCode tc) {
         //
         // In constrast to other complex types, valuetypes and value boxes
         // in Anys cannot simply be "remarshalled". The reason is that
@@ -1441,25 +1466,27 @@
             //
         }
 
-        org.omg.CORBA.TypeCode origTC = org.apache.yoko.orb.CORBA.TypeCode
-                ._OB_getOrigType(tc);
+        final TypeCode origTC = org.apache.yoko.orb.CORBA.TypeCode._OB_getOrigType(tc);
 
-        logger.fine("Reading an Any value of kind=" + origTC.kind().value() + " from position " + buf_.pos_); 
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format(
+                    "Reading an Any value of kind=%d from position 0x%x",
+                    origTC.kind().value(), buf_.pos_));
 
         //
         // Check if the Any contains an abstract interface
         //
-        if (origTC.kind() == org.omg.CORBA.TCKind.tk_abstract_interface) {
-            boolean b = in_.read_boolean();
+        if (origTC.kind() == TCKind.tk_abstract_interface) {
+            final boolean b = in_.read_boolean();
             if (b) {
-                logger.fine("Reading an object reference for an abstract interface"); 
+                logger.fine("Reading an object reference for an abstract interface");
                 //
                 // The abstract interface represents an object reference
                 //
                 any.insert_Object(in_.read_Object(), tc);
                 return;
             } else {
-                logger.fine("Reading an object value for an abstract interface"); 
+                logger.fine("Reading an object value for an abstract interface");
                 //
                 // The abstract interface represents a valuetype. The
                 // readValue() method will raise an exception if an
@@ -1483,13 +1510,14 @@
         // CORBA::ValueBase doesn't seem very useful anyway.
         //
         try {
-            String id = origTC.id();
-            logger.fine("Reading an Any value of id=" + id); 
-            if (id.equals("IDL:omg.org/CORBA/ValueBase:1.0")) {
+            final String id = origTC.id();
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format("Reading an Any value of id=\"%s\"", id));
+            if ("IDL:omg.org/CORBA/ValueBase:1.0".equals(id)) {
                 any.insert_Value(readValue(), tc);
                 return;
             }
-        } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
+        } catch (BadKind ex) {
             Assert._OB_assert(ex);
         }
 
@@ -1502,43 +1530,42 @@
         // Save some state so that we can restore things prior to
         // remarshalling
         //
-        int startPos = buf_.pos_;
-        ChunkState startState = new ChunkState(chunkState_);
+        final int startPos = buf_.pos_;
+        final ChunkState startState = new ChunkState(chunkState_);
 
         //
         // No need to worry about truncation for boxed valuetypes
         //
-        if (origTC.kind() == org.omg.CORBA.TCKind.tk_value_box) {
+        if (origTC.kind() == TCKind.tk_value_box) {
             try {
                 any.insert_Value(readValue(tc.id()), tc);
                 return;
-            } catch (org.omg.CORBA.MARSHAL ex) {
+            } catch (MARSHAL ex) {
                 //
                 // Creation failed - restore our state and try remarshalling
                 //
                 buf_.pos_ = startPos;
                 chunkState_.copyFrom(startState);
 
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
-                org.apache.yoko.orb.CORBA.OutputStream out = new org.apache.yoko.orb.CORBA.OutputStream(
-                        buf);
+                final Buffer buf = new Buffer();
+                final OutputStream out = new OutputStream(buf);
                 out._OB_ORBInstance(orbInstance_);
                 remarshalValue(origTC, out);
-                org.apache.yoko.orb.CORBA.InputStream in = (org.apache.yoko.orb.CORBA.InputStream) out
-                        .create_input_stream();
+                final InputStream in = (InputStream) out.create_input_stream();
                 Assert._OB_assert(obAny != null);
                 obAny.replace(tc, in);
-                return;  
-            } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
+                return;
+            } catch (BadKind ex) {
                 Assert._OB_assert(ex);
             }
         } else {
             //
             // Read valuetype header tag
             //
-            Header h = new Header();
+            final Header h = new Header();
             h.tag = in_.read_long();
-            logger.fine("Read tag value " + Integer.toHexString(h.tag)); 
+            if (logger.isLoggable(Level.FINE))
+                logger.fine(String.format("Read tag value 0x%08x", h.tag));
 
             //
             // Check tag for special cases
@@ -1546,16 +1573,15 @@
             if (h.tag == 0) {
                 any.insert_Value(null, tc);
                 return;
-            } else if (h.tag != -1 && h.tag < 0x7fffff00) {
-                throw new org.omg.CORBA.MARSHAL("Illegal valuetype tag 0x"
-                        + Integer.toHexString(h.tag));
+            }
+            if ((h.tag != -1) && (h.tag < 0x7fffff00)) {
+                throw new MARSHAL("Illegal valuetype tag 0x" + Integer.toHexString(h.tag));
             }
 
             //
             // Try to create an instance of the valuetype using a factory
             //
-            FactoryCreationStrategy strategy = new FactoryCreationStrategy(
-                    this, in_, null);
+            final FactoryCreationStrategy strategy = new FactoryCreationStrategy(this, in_, null);
             try {
                 if (h.tag == -1) {
                     //
@@ -1565,14 +1591,15 @@
                     // Fixing this probably requires maintaining a
                     // map of stream position to TypeCode.
                     //
-                    logger.fine("Handling a value type indirection value"); 
+                    logger.fine("Handling a value type indirection value");
                     any.insert_Value(readIndirection(strategy), tc);
                     return;
                 } else {
                     initHeader(h);
-                    org.omg.CORBA.StringHolder idH = new org.omg.CORBA.StringHolder();
-                    java.io.Serializable vb = strategy.create(h, idH);
-                    logger.fine("Obtained a value of type " + vb.getClass().getName()); 
+                    final StringHolder idH = new StringHolder();
+                    final Serializable vb = strategy.create(h, idH);
+                    if (logger.isLoggable(Level.FINE))
+                        logger.fine(String.format("Obtained a value of type \"%s\"", vb.getClass().getName()));
                     skipChunk();
 
                     //
@@ -1589,33 +1616,30 @@
                     // 3) The TypeCode is a base type of tc. In this case,
                     // the valuetype was truncated.
                     //
-                    org.omg.CORBA.TypeCode t = null;
-                    if(idH.value != null) {
-                    	t = findTypeCode(idH.value, tc);
+                    TypeCode t = null;
+                    if (idH.value != null) {
+                        t = findTypeCode(idH.value, tc);
                     }
                     if (t != null) {
                         any.insert_Value(vb, t);
-                    }
-                    else {
+                    } else {
                         any.insert_Value(vb, tc);
                     }
                     return;
                 }
-            } catch (org.omg.CORBA.MARSHAL ex) {
-                logger.log(Level.FINE, "Marshaling exception occurred, attempting to remarshal", ex); 
+            } catch (MARSHAL ex) {
+                logger.log(Level.FINE, "Marshaling exception occurred, attempting to remarshal", ex);
                 //
                 // Creation failed - restore our state and try remarshalling
                 //
                 buf_.pos_ = startPos;
                 chunkState_.copyFrom(startState);
 
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
-                org.apache.yoko.orb.CORBA.OutputStream out = new org.apache.yoko.orb.CORBA.OutputStream(
-                        buf);
+                final Buffer buf = new Buffer();
+                final OutputStream out = new OutputStream(buf);
                 out._OB_ORBInstance(orbInstance_);
-                org.omg.CORBA.TypeCode t = remarshalValue(origTC, out);
-                org.apache.yoko.orb.CORBA.InputStream in = (org.apache.yoko.orb.CORBA.InputStream) out
-                        .create_input_stream();
+                final TypeCode t = remarshalValue(origTC, out);
+                final InputStream in = (InputStream) out.create_input_stream();
                 Assert._OB_assert(obAny != null);
                 obAny.replace(t, in);
                 return;
@@ -1626,10 +1650,11 @@
     }
 
     public void beginValue() {
-        Header h = new Header();
+        final Header h = new Header();
         h.tag = in_.read_long();
-        logger.fine("Read tag value " + Integer.toHexString(h.tag)); 
-        Assert._OB_assert(h.tag != 0 && h.tag != -1);
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Read tag value 0x%08x", h.tag));
+        Assert._OB_assert((h.tag != 0) && (h.tag != -1));
 
         initHeader(h);
     }
@@ -1639,17 +1664,17 @@
     }
 
     public void checkChunk() {
-        if (!chunkState_.chunked)
+        if (!chunkState_.chunked) {
             return;
-        
-//      logger.finest("Checking chunk position.  end=" + (chunkState_.chunkStart + chunkState_.chunkSize) + " buffer position=" + buf_.pos_); 
+        }
+
+//      logger.finest("Checking chunk position.  end=" + (chunkState_.chunkStart + chunkState_.chunkSize) + " buffer position=" + buf_.pos_);
         //
         // If we've reached the end of the current chunk, then check
         // for the start of a new chunk
         //
-        if (chunkState_.chunkStart > 0 && chunkState_.chunkStart + chunkState_.chunkSize == buf_.pos_)
-        {
-//          logger.finest("Reading chunk from check chunk"); 
+        if ((chunkState_.chunkStart > 0) && ((chunkState_.chunkStart + chunkState_.chunkSize) == buf_.pos_)) {
+//          logger.finest("Reading chunk from check chunk");
             readChunk(chunkState_);
         }
     }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueWriter.java b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueWriter.java
index 858d1fc..bc9a6b5 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueWriter.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OB/ValueWriter.java
@@ -21,9 +21,11 @@
 
 import javax.rmi.CORBA.ValueHandler;
 
-import org.apache.yoko.orb.CORBA.ORB;
+import org.apache.yoko.util.cmsf.RepIds;
 import org.apache.yoko.osgi.ProviderLocator;
+import org.omg.CORBA.WStringValueHelper;
 import org.omg.CORBA.portable.BoxedValueHelper;
+import org.omg.CORBA.portable.IDLEntity;
 
 final public class ValueWriter {
     //
@@ -183,7 +185,14 @@
         BoxedValueHelper result = null;
 
         Class helperClass = null;
+        final Class<?> valueClass = value.getClass();
 
+        //Short-cuts
+        if (String.class == valueClass) {
+            return new WStringValueHelper();
+        } else if (!!!IDLEntity.class.isAssignableFrom(valueClass)) {
+            return null;
+        }
         //
         // First try constructing a class name based on the class of
         // the value. This will only work for primitive types, because
@@ -209,7 +218,7 @@
                 org.omg.CORBA.TypeCode origType = org.apache.yoko.orb.CORBA.TypeCode
                         ._OB_getOrigType(type);
                 String id = origType.id();
-                helperClass = Util.idToClass(id, "Helper");
+                helperClass = RepIds.query(id).suffix("Helper").toClass();
             } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
                 Assert._OB_assert(ex);
             }
@@ -470,7 +479,7 @@
         //
         // Determine if chunked encoding is needed.
         //
-        boolean isChunked = valueHandler.isCustomMarshaled (clz);
+        boolean isChunked = valueHandler.isCustomMarshaled(clz);
 
         int pos = beginValue (tag, ids, codebase, isChunked);
         instanceTable_.put (value, new Integer (pos));
@@ -531,8 +540,8 @@
                 out_.write_boolean(false); // discriminator for valuetype
                 writeValue((java.io.Serializable) obj, null);
             } else
-                throw new org.omg.CORBA.MARSHAL("Object is not an object "
-                        + "reference or valuetype");
+                throw new org.omg.CORBA.MARSHAL("Object of class " + obj.getClass().getName() 
+                        + " is not an object reference or valuetype");
         } else {
             //
             // A nil abstract interface is marshalled as a null valuetype
@@ -642,7 +651,6 @@
 
     public void endValue() {
         if (chunked_) {
-            boolean nc = needChunk_;
             needChunk_ = false;
 
             //
@@ -658,15 +666,7 @@
                 buf_.pos_ = lastEndTagPos_; // same as "buf_.pos_ -= 4;"
                 out_.write_long(lastTag_);
             } else {
-                //
-                // This value does not coterminate with a nested value.
-                // If we still need a chunk, then add an empty chunk,
-                // otherwise end the current chunk.
-                //
-                if (nc)
-                    out_.write_long(0);
-                else
-                    endChunk();
+                endChunk();
 
                 //
                 // Write the end tag and remember its position
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 fb8fba0..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
@@ -1,10 +1,10 @@
 /*
  *  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
+ *  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
  *
@@ -19,8 +19,18 @@
 
 import java.security.AccessController;
 import java.util.Properties;
+
+import org.apache.yoko.orb.cmsf.CmsfClientInterceptor;
+import org.apache.yoko.orb.cmsf.CmsfIORInterceptor;
+import org.apache.yoko.orb.cmsf.CmsfServerInterceptor;
+import org.apache.yoko.orb.util.AutoLock;
+import org.apache.yoko.orb.util.AutoReadWriteLock;
 import org.apache.yoko.orb.util.GetSystemPropertyAction;
+import org.apache.yoko.orb.yasf.YasfClientInterceptor;
+import org.apache.yoko.orb.yasf.YasfIORInterceptor;
+import org.apache.yoko.orb.yasf.YasfServerInterceptor;
 import org.apache.yoko.osgi.ProviderLocator;
+import org.omg.CORBA.OBJECT_NOT_EXIST;
 
 // This class must be public and not final
 public class ORB_impl extends org.apache.yoko.orb.CORBA.ORBSingleton {
@@ -37,8 +47,8 @@
     //
     // Has the ORB been destroyed?
     //
+    private final AutoReadWriteLock destroyLock_ = new AutoReadWriteLock();
     private boolean destroy_;
-
     //
     // The OCI Plugin Manager
     //
@@ -94,9 +104,9 @@
                     + version);
         }
 
-        destroy_ = false;
+        try (AutoLock writeLock = destroyLock_.getWriteLock()) {
+            destroy_ = false;
 
-        try {
             //
             // Create the ORBControl
             //
@@ -148,20 +158,20 @@
             dsf._OB_setORBInstance(orbInstance_);
             try {
                 urlRegistry
-                        .add_scheme(new org.apache.yoko.orb.OB.IORURLScheme_impl(
-                                orbInstance_));
+                .add_scheme(new org.apache.yoko.orb.OB.IORURLScheme_impl(
+                        orbInstance_));
                 urlRegistry
-                        .add_scheme(new org.apache.yoko.orb.OB.FileURLScheme_impl(
-                                false, urlRegistry));
+                .add_scheme(new org.apache.yoko.orb.OB.FileURLScheme_impl(
+                        false, urlRegistry));
                 urlRegistry
-                        .add_scheme(new org.apache.yoko.orb.OB.FileURLScheme_impl(
-                                true, urlRegistry));
+                .add_scheme(new org.apache.yoko.orb.OB.FileURLScheme_impl(
+                        true, urlRegistry));
                 urlRegistry
-                        .add_scheme(new org.apache.yoko.orb.OB.CorbalocURLScheme_impl(
-                                orbInstance_));
+                .add_scheme(new org.apache.yoko.orb.OB.CorbalocURLScheme_impl(
+                        orbInstance_));
                 urlRegistry
-                        .add_scheme(new org.apache.yoko.orb.OB.CorbanameURLScheme_impl(
-                                this, urlRegistry));
+                .add_scheme(new org.apache.yoko.orb.OB.CorbanameURLScheme_impl(
+                        this, urlRegistry));
             } catch (org.apache.yoko.orb.OB.URLRegistryPackage.SchemeAlreadyExists ex) {
                 org.apache.yoko.orb.OB.Assert._OB_assert(ex);
             }
@@ -279,6 +289,27 @@
             } catch (org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName ex) {
                 org.apache.yoko.orb.OB.Assert._OB_assert(ex);
             }
+            
+            //
+            // Install interceptors for Yoko Auxilliary Stream Format
+            //
+            try {
+                piManager.addIORInterceptor(new YasfIORInterceptor(), true);
+                piManager.addClientRequestInterceptor(new YasfClientInterceptor());
+                piManager.addServerRequestInterceptor(new YasfServerInterceptor(piManager.allocateSlotId()));
+            } catch (org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName ex) {
+                org.apache.yoko.orb.OB.Assert._OB_assert(ex);
+            }
+            //
+            // Install interceptors for Custom Marshal Stream Format negotiation
+            //
+            try {
+                piManager.addIORInterceptor(new CmsfIORInterceptor(), false);
+                piManager.addClientRequestInterceptor(new CmsfClientInterceptor());
+                piManager.addServerRequestInterceptor(new CmsfServerInterceptor(piManager.allocateSlotId()));
+            } catch (org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName ex) {
+                org.apache.yoko.orb.OB.Assert._OB_assert(ex);
+            }
 
             //
             // Install IOR interceptor for Message Routing
@@ -291,11 +322,11 @@
                 routerListHolder.value = new org.omg.MessageRouting.Router[0];
 
                 org.apache.yoko.orb.OB.MessageRoutingUtil
-                        .getRouterListFromConfig(orbInstance_, routerListHolder);
+                .getRouterListFromConfig(orbInstance_, routerListHolder);
                 piManager
-                        .addIORInterceptor(
-                                new org.apache.yoko.orb.OB.MessageRoutingIORInterceptor_impl(
-                                        routerListHolder.value), false);
+                .addIORInterceptor(
+                        new org.apache.yoko.orb.OB.MessageRoutingIORInterceptor_impl(
+                                routerListHolder.value), false);
             } catch (org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName ex) {
                 org.apache.yoko.orb.OB.Assert._OB_assert(ex);
             }
@@ -343,16 +374,16 @@
             org.omg.CORBA.portable.ValueFactory ortFactory = new org.apache.yoko.orb.OBPortableInterceptor.TransientORTFactory_impl(
                     orbInstance_);
             valueFactoryManager
-                    .registerValueFactory(
-                            "IDL:orb.yoko.apache.org/OBPortableInterceptor/TransientORT:1.0",
-                            ortFactory);
+            .registerValueFactory(
+                    "IDL:orb.yoko.apache.org/OBPortableInterceptor/TransientORT:1.0",
+                    ortFactory);
 
             ortFactory = new org.apache.yoko.orb.OBPortableInterceptor.PersistentORTFactory_impl(
                     orbInstance_);
             valueFactoryManager
-                    .registerValueFactory(
-                            "IDL:orb.yoko.apache.org/OBPortableInterceptor/PersistentORT:1.0",
-                            ortFactory);
+            .registerValueFactory(
+                    "IDL:orb.yoko.apache.org/OBPortableInterceptor/PersistentORT:1.0",
+                    ortFactory);
 
             ortFactory = new org.apache.yoko.orb.OBPortableInterceptor.IMRORTFactory_impl();
             valueFactoryManager.registerValueFactory(
@@ -1029,9 +1060,9 @@
                 try {
                     int max = Integer.valueOf(value).intValue();
                     org.apache.yoko.orb.OB.GIOPIncomingMessage
-                            .setMaxMessageSize(max);
+                    .setMaxMessageSize(max);
                     org.apache.yoko.orb.OB.GIOPOutgoingMessage
-                            .setMaxMessageSize(max);
+                    .setMaxMessageSize(max);
                 } catch (NumberFormatException ex) {
                     String err = "ORB.init: invalid value for "
                             + "yoko.orb.giop.max_message_size: " + value;
@@ -1064,108 +1095,122 @@
     // Standard IDL to Java Mapping
     // ------------------------------------------------------------------
 
-    public synchronized String[] list_initial_services() {
-        if (destroy_)
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+    public String[] list_initial_services() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
+            if (destroy_)
+                throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
-        return orbInstance_.getInitialServiceManager().listInitialServices();
+            return orbInstance_.getInitialServiceManager().listInitialServices();
+        }
     }
 
-    public synchronized org.omg.CORBA.Object resolve_initial_references(
+    public org.omg.CORBA.Object resolve_initial_references(
             String identifier) throws org.omg.CORBA.ORBPackage.InvalidName {
-        if (destroy_) {
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
-        }
-
-        org.apache.yoko.orb.OB.InitialServiceManager initServiceManager = orbInstance_
-                .getInitialServiceManager();
-
-        org.omg.CORBA.Object obj = null;
-
-        try {
-            obj = initServiceManager.resolveInitialReferences(identifier);
-        } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
-            //
-            // If the service is the RootPOA and it hasn't yet been
-            // initialized, create it. We could put in some automatic method
-            // here for late binding of objects at some later point.
-            //
-            if (identifier.equals("RootPOA")) {
-                orbControl_.initializeRootPOA(this);
-                return resolve_initial_references(identifier);
-            } else {
-                throw ex;
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
+            if (destroy_) {
+                throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
             }
+
+            org.apache.yoko.orb.OB.InitialServiceManager initServiceManager = orbInstance_
+                    .getInitialServiceManager();
+
+            org.omg.CORBA.Object obj = null;
+
+            try {
+                obj = initServiceManager.resolveInitialReferences(identifier);
+            } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
+                //
+                // If the service is the RootPOA and it hasn't yet been
+                // initialized, create it. We could put in some automatic method
+                // here for late binding of objects at some later point.
+                //
+                if (identifier.equals("RootPOA")) {
+                    orbControl_.initializeRootPOA(this);
+                    return resolve_initial_references(identifier);
+                } else {
+                    throw ex;
+                }
+            }
+            return obj;
         }
-        return obj;
     }
 
-    public synchronized void register_initial_reference(String name,
+    public void register_initial_reference(String name,
             org.omg.CORBA.Object obj)
-            throws org.omg.CORBA.ORBPackage.InvalidName {
-        if (destroy_)
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+                    throws org.omg.CORBA.ORBPackage.InvalidName {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
 
-        orbInstance_.getInitialServiceManager().addInitialReference(name, obj);
+            if (destroy_)
+                throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+
+            orbInstance_.getInitialServiceManager().addInitialReference(name, obj);
+        }
     }
 
     public String object_to_string(org.omg.CORBA.Object p) {
-        synchronized (this) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
             if (destroy_)
                 throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+
+            org.omg.IOP.IOR ior;
+
+            if (p == null) {
+                ior = new org.omg.IOP.IOR("", new org.omg.IOP.TaggedProfile[0]);
+            } else {
+                if (p instanceof org.omg.CORBA.LocalObject)
+                    throw new org.omg.CORBA.MARSHAL(
+                            org.apache.yoko.orb.OB.MinorCodes
+                            .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorLocalObject),
+                            org.apache.yoko.orb.OB.MinorCodes.MinorLocalObject,
+                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+
+                org.apache.yoko.orb.CORBA.Delegate delegate = (org.apache.yoko.orb.CORBA.Delegate) (((org.omg.CORBA.portable.ObjectImpl) p)
+                        ._get_delegate());
+                ior = delegate._OB_origIOR();
+            }
+
+            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
+            org.apache.yoko.orb.CORBA.OutputStream out = new org.apache.yoko.orb.CORBA.OutputStream(
+                    buf);
+
+            out._OB_writeEndian();
+            org.omg.IOP.IORHelper.write(out, ior);
+
+            String str = org.apache.yoko.orb.OB.HexConverter.octetsToAscii(buf
+                    .data(), buf.length());
+            return "IOR:" + str;
         }
-
-        org.omg.IOP.IOR ior;
-
-        if (p == null) {
-            ior = new org.omg.IOP.IOR("", new org.omg.IOP.TaggedProfile[0]);
-        } else {
-            if (p instanceof org.omg.CORBA.LocalObject)
-                throw new org.omg.CORBA.MARSHAL(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeMarshal(org.apache.yoko.orb.OB.MinorCodes.MinorLocalObject),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorLocalObject,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-
-            org.apache.yoko.orb.CORBA.Delegate delegate = (org.apache.yoko.orb.CORBA.Delegate) (((org.omg.CORBA.portable.ObjectImpl) p)
-                    ._get_delegate());
-            ior = delegate._OB_origIOR();
-        }
-
-        org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
-        org.apache.yoko.orb.CORBA.OutputStream out = new org.apache.yoko.orb.CORBA.OutputStream(
-                buf);
-
-        out._OB_writeEndian();
-        org.omg.IOP.IORHelper.write(out, ior);
-
-        String str = org.apache.yoko.orb.OB.HexConverter.octetsToAscii(buf
-                .data(), buf.length());
-        return "IOR:" + str;
     }
 
-    public synchronized org.omg.CORBA.Object string_to_object(String ior) {
-        if (destroy_)
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+    public org.omg.CORBA.Object string_to_object(String ior) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
+            if (destroy_)
+                throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
-        return orbInstance_.getObjectFactory().stringToObject(ior);
+            return orbInstance_.getObjectFactory().stringToObject(ior);
+        }
     }
 
-    public synchronized org.omg.CORBA.NVList create_list(int count) {
-        if (destroy_)
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+    public org.omg.CORBA.NVList create_list(int count) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
 
-        if (count < 0)
-            count = 0;
+            if (destroy_)
+                throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
-        return new org.apache.yoko.orb.CORBA.NVList(this, count);
+            if (count < 0)
+                count = 0;
+
+            return new org.apache.yoko.orb.CORBA.NVList(this, count);
+        }
     }
 
     /**
      * @deprecated Deprecated by CORBA 2.3.
      */
-    public synchronized org.omg.CORBA.NVList create_operation_list(
+    public org.omg.CORBA.NVList create_operation_list(
             org.omg.CORBA.OperationDef oper) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
+
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
@@ -1189,115 +1234,138 @@
 
             int flags = 0;
             switch (par.mode.value()) {
-            case org.omg.CORBA.ParameterMode._PARAM_IN:
-                flags = org.omg.CORBA.ARG_IN.value;
-                break;
+                case org.omg.CORBA.ParameterMode._PARAM_IN:
+                    flags = org.omg.CORBA.ARG_IN.value;
+                    break;
 
-            case org.omg.CORBA.ParameterMode._PARAM_OUT:
-                flags = org.omg.CORBA.ARG_OUT.value;
-                break;
+                case org.omg.CORBA.ParameterMode._PARAM_OUT:
+                    flags = org.omg.CORBA.ARG_OUT.value;
+                    break;
 
-            case org.omg.CORBA.ParameterMode._PARAM_INOUT:
-                flags = org.omg.CORBA.ARG_INOUT.value;
-                break;
+                case org.omg.CORBA.ParameterMode._PARAM_INOUT:
+                    flags = org.omg.CORBA.ARG_INOUT.value;
+                    break;
 
-            default:
-                org.apache.yoko.orb.OB.Assert._OB_assert(false);
+                default:
+                    org.apache.yoko.orb.OB.Assert._OB_assert(false);
             }
 
             list.add_value(par.name, any, flags);
         }
 
         return list;
+        }
     }
 
-    public synchronized org.omg.CORBA.NVList create_operation_list(
+    public  org.omg.CORBA.NVList create_operation_list(
             org.omg.CORBA.Object oper) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
+
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.omg.CORBA.OperationDef def = org.omg.CORBA.OperationDefHelper
                 .narrow(oper);
         return create_operation_list(def);
+        }
     }
 
-    public synchronized org.omg.CORBA.NamedValue create_named_value(
+    public org.omg.CORBA.NamedValue create_named_value(
             String name, org.omg.CORBA.Any value, int flags) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return new org.apache.yoko.orb.CORBA.NamedValue(name, value, flags);
+        }
     }
 
-    public synchronized org.omg.CORBA.ExceptionList create_exception_list() {
+    public org.omg.CORBA.ExceptionList create_exception_list() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return new org.apache.yoko.orb.CORBA.ExceptionList();
+        }
     }
 
-    public synchronized org.omg.CORBA.ContextList create_context_list() {
+    public org.omg.CORBA.ContextList create_context_list() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return new org.apache.yoko.orb.CORBA.ContextList();
+        }
     }
 
-    public synchronized org.omg.CORBA.Context get_default_context() {
+    public org.omg.CORBA.Context get_default_context() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return new org.apache.yoko.orb.CORBA.Context(this, "");
+        }
     }
 
-    public synchronized org.omg.CORBA.Environment create_environment() {
+    public org.omg.CORBA.Environment create_environment() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return new org.apache.yoko.orb.CORBA.Environment();
+        }
     }
 
-    public synchronized void send_multiple_requests_oneway(
+    public void send_multiple_requests_oneway(
             org.omg.CORBA.Request[] requests) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.apache.yoko.orb.OB.MultiRequestSender multi = orbInstance_
                 .getMultiRequestSender();
         multi.sendMultipleRequestsOneway(requests);
+        }
     }
 
-    public synchronized void send_multiple_requests_deferred(
+    public void send_multiple_requests_deferred(
             org.omg.CORBA.Request[] requests) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.apache.yoko.orb.OB.MultiRequestSender multi = orbInstance_
                 .getMultiRequestSender();
         multi.sendMultipleRequestsDeferred(requests);
+        }
     }
 
-    public synchronized boolean poll_next_response() {
+    public boolean poll_next_response() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.apache.yoko.orb.OB.MultiRequestSender multi = orbInstance_
                 .getMultiRequestSender();
         return multi.pollNextResponse();
+        }
     }
 
-    public synchronized org.omg.CORBA.Request get_next_response()
+    public org.omg.CORBA.Request get_next_response()
             throws org.omg.CORBA.WrongTransaction {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.apache.yoko.orb.OB.MultiRequestSender multi = orbInstance_
                 .getMultiRequestSender();
         return multi.getNextResponse();
+        }
     }
 
-    public synchronized boolean get_service_information(short service_type,
+    public boolean get_service_information(short service_type,
             org.omg.CORBA.ServiceInformationHolder service_info) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
@@ -1305,6 +1373,7 @@
         service_info.value.service_options = new int[0];
         service_info.value.service_details = new org.omg.CORBA.ServiceDetail[0];
         return false;
+        }
     }
 
     public boolean work_pending() {
@@ -1312,6 +1381,7 @@
         // Ensure that the ORB mutex is not locked during the call to
         // ORBControl methods
         //
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
@@ -1322,6 +1392,7 @@
         Thread.yield();
 
         return orbControl_.workPending();
+        }
     }
 
     public void perform_work() {
@@ -1329,9 +1400,11 @@
         // Ensure that the ORB mutex is not locked during the call to
         // ORBControl methods
         //
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
         orbControl_.performWork();
+        }
     }
 
     public void run() {
@@ -1339,9 +1412,11 @@
         // Ensure that the ORB mutex is not locked during the call to
         // ORBControl methods
         //
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+            throw new OBJECT_NOT_EXIST("ORB is destroyed");
         orbControl_.run();
+        }
     }
 
     public void shutdown(boolean wait_for_completion) {
@@ -1349,71 +1424,76 @@
         // Ensure that the ORB mutex is not locked during the call to
         // ORBControl methods
         //
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+            throw new OBJECT_NOT_EXIST("ORB is destroyed");
         orbControl_.shutdownServer(wait_for_completion);
+        }
     }
 
-    public synchronized void destroy() {
-        //
-        // From the specification:
-        //
-        // This operation destroys the ORB so that its resources can be
-        // reclaimed by the application. Any operation invoked on a
-        // destroyed ORB reference will raise the OBJECT_NOT_EXIST
-        // exception. Once an ORB has been destroyed, another call to
-        // ORB_init with the same ORBid will return a reference to a newly
-        // constructed ORB.
-        //
-        // If destroy is called on an ORB that has not been shut down, it
-        // will start the shut down process and block until the ORB has
-        // shut down before it destroys the ORB. If an application calls
-        // destroy in a thread that is currently servicing an invocation,
-        // the BAD_INV_ORDER system exception will be raised with the OMG
-        // minor code 3, since blocking would result in a deadlock.
-        //
-        // For maximum portability and to avoid resource leaks, an
-        // application should always call shutdown and destroy on all ORB
-        // instances before exiting.
-        //
+    public void destroy() {
+        try (AutoLock writelock = destroyLock_.getWriteLock()) {
+            //
+            // From the specification:
+            //
+            // This operation destroys the ORB so that its resources can be
+            // reclaimed by the application. Any operation invoked on a
+            // destroyed ORB reference will raise the OBJECT_NOT_EXIST
+            // exception. Once an ORB has been destroyed, another call to
+            // ORB_init with the same ORBid will return a reference to a newly
+            // constructed ORB.
+            //
+            // If destroy is called on an ORB that has not been shut down, it
+            // will start the shut down process and block until the ORB has
+            // shut down before it destroys the ORB. If an application calls
+            // destroy in a thread that is currently servicing an invocation,
+            // the BAD_INV_ORDER system exception will be raised with the OMG
+            // minor code 3, since blocking would result in a deadlock.
+            //
+            // For maximum portability and to avoid resource leaks, an
+            // application should always call shutdown and destroy on all ORB
+            // instances before exiting.
+            //
 
-        //
-        // Has the ORB been destroyed yet?
-        //
-        if (destroy_)
-            throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
+            //
+            // Has the ORB been destroyed yet?
+            //
+            if (destroy_)
+                throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
-        //
-        // Shutdown both the server & client side of the ORB
-        //
-        orbControl_.shutdownServerClient();
+            //
+            // Shutdown both the server & client side of the ORB
+            //
+            orbControl_.shutdownServerClient();
 
-        //
-        // Destroy the ORBControl. Don't set to _nil.
-        //
-        orbControl_.destroy();
-        // orbControl_ = null;
+            //
+            // Destroy the ORBControl. Don't set to _nil.
+            //
+            orbControl_.destroy();
+            // orbControl_ = null;
 
-        //
-        // Destroy the ORBInstance object
-        //
-        orbInstance_.destroy();
-        orbInstance_ = null;
+            //
+            // Destroy the ORBInstance object
+            //
+            orbInstance_.destroy();
+            orbInstance_ = null;
 
-        //
-        // Destroy the OCI Plugin Manager. This must be done after all
-        // the OCI objects have been destroyed.
-        //
-        pluginManager_.destroy();
-        pluginManager_ = null;
+            //
+            // Destroy the OCI Plugin Manager. This must be done after all
+            // the OCI objects have been destroyed.
+            //
+            pluginManager_.destroy();
+            pluginManager_ = null;
 
-        //
-        // Mark the ORB as destroyed
-        //
-        destroy_ = true;
+            //
+            // Mark the ORB as destroyed
+            //
+            destroy_ = true;
+        }
     }
 
-    public synchronized org.omg.CORBA.portable.OutputStream create_output_stream() {
+    public org.omg.CORBA.portable.OutputStream create_output_stream() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
@@ -1422,10 +1502,12 @@
                 buf);
         out._OB_ORBInstance(orbInstance_);
         return out;
+        }
     }
 
-    public synchronized org.omg.CORBA.Object get_value_def(String repid)
+    public org.omg.CORBA.Object get_value_def(String repid)
             throws org.omg.CORBA.BAD_PARAM {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
@@ -1441,21 +1523,24 @@
 
         throw new org.omg.CORBA.BAD_PARAM("Repository lookup failed for "
                 + repid);
+        }
     }
 
-    public synchronized void set_delegate(java.lang.Object wrapper) {
+    public void set_delegate(java.lang.Object wrapper) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         try {
             org.omg.PortableServer.Servant servant = (org.omg.PortableServer.Servant) wrapper;
             servant
-                    ._set_delegate(new org.apache.yoko.orb.PortableServer.Delegate(
-                            this));
+            ._set_delegate(new org.apache.yoko.orb.PortableServer.Delegate(
+                    this));
         } catch (ClassCastException ex) {
             throw (org.omg.CORBA.BAD_PARAM)new org.omg.CORBA.BAD_PARAM(
                     "Argument is not of type "
-                    + "org.omg.PortableServer." + "Servant").initCause(ex);
+                            + "org.omg.PortableServer." + "Servant").initCause(ex);
+        }
         }
     }
 
@@ -1724,7 +1809,7 @@
                 properties.put(propName, propValue);
             } else if (name.equals("repository")) {
                 properties
-                        .put("yoko.orb.service.InterfaceRepository", value[0]);
+                .put("yoko.orb.service.InterfaceRepository", value[0]);
             } else if (name.equals("naming")) {
                 properties.put("yoko.orb.service.NameService", value[0]);
             } else if (name.equals("trace_connections")
@@ -1789,67 +1874,81 @@
         return args;
     }
 
-    synchronized public org.omg.CORBA.Policy create_policy(int type,
+    public org.omg.CORBA.Policy create_policy(int type,
             org.omg.CORBA.Any any) throws org.omg.CORBA.PolicyError {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return orbInstance_.getPolicyFactoryManager().createPolicy(type, any);
+        }
     }
 
-    synchronized public org.omg.CORBA.portable.ValueFactory register_value_factory(
+    public org.omg.CORBA.portable.ValueFactory register_value_factory(
             String id, org.omg.CORBA.portable.ValueFactory factory) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.apache.yoko.orb.OB.ValueFactoryManager valueFactoryManager = orbInstance_
                 .getValueFactoryManager();
         return valueFactoryManager.registerValueFactory(id, factory);
+        }
     }
 
-    synchronized public void unregister_value_factory(String id) {
+    public void unregister_value_factory(String id) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.apache.yoko.orb.OB.ValueFactoryManager valueFactoryManager = orbInstance_
                 .getValueFactoryManager();
         valueFactoryManager.unregisterValueFactory(id);
+        }
     }
 
-    synchronized public org.omg.CORBA.portable.ValueFactory lookup_value_factory(
+    public org.omg.CORBA.portable.ValueFactory lookup_value_factory(
             String id) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         org.apache.yoko.orb.OB.ValueFactoryManager valueFactoryManager = orbInstance_
                 .getValueFactoryManager();
         return valueFactoryManager.lookupValueFactory(id);
+        }
     }
 
     // ------------------------------------------------------------------
     // Additional Yoko specific functions
     // ------------------------------------------------------------------
 
-    synchronized public java.util.Properties properties() {
+    public java.util.Properties properties() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return orbInstance_.getProperties();
+        }
     }
 
-    synchronized public org.apache.yoko.orb.OB.Logger logger() {
+    public org.apache.yoko.orb.OB.Logger logger() {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return orbInstance_.getLogger();
+        }
     }
 
-    synchronized public org.apache.yoko.orb.OB.UnknownExceptionStrategy set_unknown_exception_strategy(
+    public org.apache.yoko.orb.OB.UnknownExceptionStrategy set_unknown_exception_strategy(
             org.apache.yoko.orb.OB.UnknownExceptionStrategy strategy) {
+        try (AutoLock readLock = destroyLock_.getReadLock()) {
         if (destroy_)
             throw new org.omg.CORBA.OBJECT_NOT_EXIST("ORB is destroyed");
 
         return orbInstance_.setUnknownExceptionStrategy(strategy);
+        }
     }
 
     // ------------------------------------------------------------------
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OBMessaging/ExceptionHolder_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OBMessaging/ExceptionHolder_impl.java
index 1bffbcc..b9461a6 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OBMessaging/ExceptionHolder_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OBMessaging/ExceptionHolder_impl.java
@@ -16,8 +16,9 @@
  */
 
 package org.apache.yoko.orb.OBMessaging;
+import static org.apache.yoko.orb.OCI.GiopVersion.GIOP1_2;
+
 import org.apache.yoko.osgi.ProviderLocator;
-import org.omg.CORBA.Any;
 
 public class ExceptionHolder_impl extends org.omg.Messaging._ExceptionHolder {
     //
@@ -305,7 +306,7 @@
         org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
                 marshaled_exception, marshaled_exception.length);
         org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
-                buf, 0, false, null, 258);
+                buf, 0, false, null, GIOP1_2);
 
         return in;
     }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/AcceptorInfoOperations.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/AcceptorInfoOperations.java
index 64b390e..3931b51 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/AcceptorInfoOperations.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/AcceptorInfoOperations.java
@@ -66,31 +66,8 @@
     //
     // IDL:orb.yoko.apache.org/OCI/AcceptorInfo/add_accept_cb:1.0
     //
-    /**
-     *
-     * Add a callback that is called whenever a new connection is
-     * accepted. If the callback has already been registered, this
-     * method has no effect.
-     *
-     * @param cb The callback to add.
-     *
-     **/
-
-    void
-    add_accept_cb(AcceptCB cb);
 
     //
     // IDL:orb.yoko.apache.org/OCI/AcceptorInfo/remove_accept_cb:1.0
     //
-    /**
-     *
-     * Remove an accept callback. If the callback was not registered,
-     * this method has no effect.
-     *
-     * @param cb The callback to remove.
-     *
-     **/
-
-    void
-    remove_accept_cb(AcceptCB cb);
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Buffer.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Buffer.java
index cd50b1b..6cdee79 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Buffer.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Buffer.java
@@ -17,6 +17,8 @@
 
 package org.apache.yoko.orb.OCI;
 
+import org.apache.yoko.orb.OB.IORUtil;
+
 public final class Buffer {
     private int max_; // The maximum size of the buffer
 
@@ -66,14 +68,10 @@
      */
     public String dumpData() 
     {
-        StringBuffer dump = new StringBuffer(); 
-        dump.append("Buffer pos="); 
-        dump.append(pos_); 
-        dump.append(" Buffer len="); 
-        dump.append(len_); 
-        dump.append(" Remaining buffer data=\n\n"); 
+        StringBuilder dump = new StringBuilder(); 
+        dump.append(String.format("Buffer pos=0x%x Buffer len=0x%x Remaining buffer data=%n%n", pos_, len_)); 
         
-        dump.append(org.apache.yoko.orb.OB.IORUtil.dump_octets(data_, pos_, rest_length())); 
+        org.apache.yoko.orb.OB.IORUtil.dump_octets(data_, pos_, rest_length(), dump); 
         return dump.toString(); 
     }
 
@@ -159,4 +157,14 @@
     public Buffer(int len) {
         alloc(len);
     }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        int pos = pos_, len = len_;
+        IORUtil.dump_octets(data_, 0, pos, sb);
+        sb.append(String.format("------------------ pos = 0x%08X -------------------%n", pos));
+        IORUtil.dump_octets(data_, pos, len_ - pos, sb);
+        return sb.toString();
+    }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/ConnectorInfoOperations.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/ConnectorInfoOperations.java
index 5841a3f..7edb247 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/ConnectorInfoOperations.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/ConnectorInfoOperations.java
@@ -62,35 +62,4 @@
 
     String
     describe();
-
-    //
-    // IDL:orb.yoko.apache.org/OCI/ConnectorInfo/add_connect_cb:1.0
-    //
-    /**
-     *
-     * Add a callback that is called whenever a new connection is
-     * established. If the callback has already been registered, this
-     * method has no effect.
-     *
-     * @param cb The callback to add.
-     *
-     **/
-
-    void
-    add_connect_cb(ConnectCB cb);
-
-    //
-    // IDL:orb.yoko.apache.org/OCI/ConnectorInfo/remove_connect_cb:1.0
-    //
-    /**
-     *
-     * Remove a connect callback. If the callback was not registered,
-     * this method has no effect.
-     *
-     * @param cb The callback to remove.
-     *
-     **/
-
-    void
-    remove_connect_cb(ConnectCB cb);
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/CurrentOperations.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/CurrentOperations.java
index 580d592..a0d51be 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/CurrentOperations.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/CurrentOperations.java
@@ -47,16 +47,4 @@
     //
     // IDL:orb.yoko.apache.org/OCI/Current/get_oci_acceptor_info:1.0
     //
-    /**
-     *
-     * This method returns the Acceptor information object for the
-     * Acceptor which created the Transport used to invoke the current
-     * request.
-     *
-     * @returns The Acceptor information object.
-     *
-     **/
-
-    AcceptorInfo
-    get_oci_acceptor_info();
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Current_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Current_impl.java
index c013f11..c19db57 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Current_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/Current_impl.java
@@ -68,14 +68,6 @@
                 .firstElement();
     }
 
-    public org.apache.yoko.orb.OCI.AcceptorInfo get_oci_acceptor_info() {
-        org.apache.yoko.orb.OCI.TransportInfo info = get_oci_transport_info();
-        if (info != null)
-            return info.acceptor_info();
-        else
-            return null;
-    }
-
     // ------------------------------------------------------------------
     // Yoko internal functions
     // Application programs must not use these functions directly
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/GiopVersion.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/GiopVersion.java
new file mode 100644
index 0000000..77d793a
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/GiopVersion.java
@@ -0,0 +1,23 @@
+package org.apache.yoko.orb.OCI;
+
+public enum GiopVersion {
+    GIOP1_0(1,0), GIOP1_1(1,1), GIOP1_2(1,2);
+
+    public final byte major;
+    public final byte minor;
+
+    private GiopVersion(int major, int minor) {
+        this.major = (byte)(major & 0xff);
+        this.minor = (byte)(minor & 0xff);
+    }
+
+    public static GiopVersion get(byte major, byte minor) {
+        if (major < 1) return GIOP1_0;
+        if (major > 1) return GIOP1_2;
+        switch (minor) {
+            case 0: return GIOP1_0;
+            case 1: return GIOP1_1;
+            default: return GIOP1_2;
+        }
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AccFactory_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AccFactory_impl.java
index 3e18dc4..0f0b1f3 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AccFactory_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AccFactory_impl.java
@@ -20,13 +20,21 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.yoko.orb.OB.Assert;
 import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.IOP.Codec;
+import org.omg.IOP.CodecFactory;
+import org.omg.IOP.ENCODING_CDR_ENCAPS;
+import org.omg.IOP.Encoding;
+import org.omg.IOP.CodecFactoryPackage.UnknownEncoding;
 
 final class AccFactory_impl extends org.omg.CORBA.LocalObject implements
         org.apache.yoko.orb.OCI.AccFactory {
 
     // the real logger backing instance.  We use the interface class as the locator
     static final Logger logger = Logger.getLogger(org.apache.yoko.orb.OCI.AccFactory.class.getName());
+    private static final Encoding CDR_1_2_ENCODING = new Encoding(ENCODING_CDR_ENCAPS.value, (byte) 1, (byte) 2);
     //
     // AccFactory information
     //
@@ -37,6 +45,7 @@
     private ConnectionHelper connectionHelper_;   // client connection helper
 
     private ListenerMap listenMap_;
+    private ExtendedConnectionHelper extendedConnectionHelper_;
 
     // ------------------------------------------------------------------
     // Standard IDL to Java Mapping
@@ -142,9 +151,11 @@
                     throw new org.apache.yoko.orb.OCI.InvalidParam(
                             "invalid port");
                 i += 2;
-            } else {
+            } else  if (connectionHelper_ != null){
                 throw new org.apache.yoko.orb.OCI.InvalidParam(
                         "unknown parameter: " + params[i]);
+            } else {
+                i++;
             }
         }
 
@@ -154,15 +165,16 @@
         }
 
         logger.fine("Creating acceptor for port=" + port);
+        Codec codec;
+        try {
+                codec = ((CodecFactory) orb_.resolve_initial_references("CodecFactory")).create_codec(CDR_1_2_ENCODING);
+        } catch (InvalidName e) {
+            throw new org.apache.yoko.orb.OCI.InvalidParam("Could not obtain codec factory using name 'CodecFactory'");
+        } catch (UnknownEncoding e) {
+            throw new org.apache.yoko.orb.OCI.InvalidParam("Could not obtain codec using encoding " + CDR_1_2_ENCODING);
+        }
 
-        if (bind == null) {
-            return new Acceptor_impl(hosts, multiProfile, port, backlog,
-                    keepAlive, connectionHelper_, listenMap_);
-        }
-        else {
-            return new Acceptor_impl(bind, hosts, multiProfile, port, backlog,
-                    keepAlive, connectionHelper_, listenMap_);
-        }
+        return new Acceptor_impl(bind, hosts, multiProfile, port, backlog, keepAlive, connectionHelper_, extendedConnectionHelper_, listenMap_, params, codec);
     }
 
     public void change_key(org.omg.IOP.IORHolder ior, byte[] key) {
@@ -178,7 +190,7 @@
                 org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
                         data, data.length);
                 org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
-                        buf, 0, false, null, 0);
+                        buf, 0, false, null, null);
                 in._OB_readEndian();
                 org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
                         .read(in);
@@ -233,10 +245,13 @@
     // Application programs must not use these functions directly
     // ------------------------------------------------------------------
 
-    public AccFactory_impl(org.omg.CORBA.ORB orb, ListenerMap lm, ConnectionHelper helper) {
+    public AccFactory_impl(org.omg.CORBA.ORB orb, ListenerMap lm, ConnectionHelper helper, ExtendedConnectionHelper extendedHelper) {
+        Assert._OB_assert((helper == null) ^ (extendedHelper == null));
         orb_ = orb;
         info_ = new AccFactoryInfo_impl();
         listenMap_ = lm;
         connectionHelper_ = helper;
+        extendedConnectionHelper_ = extendedHelper;
     }
+    
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AcceptorInfo_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AcceptorInfo_impl.java
index bd46fc7..48c2411 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AcceptorInfo_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/AcceptorInfo_impl.java
@@ -19,16 +19,11 @@
 
 import org.apache.yoko.orb.OCI.IIOP.AcceptorInfo;
 import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
+import org.omg.CORBA.LocalObject;
 
-public final class AcceptorInfo_impl extends org.omg.CORBA.LocalObject
-        implements AcceptorInfo {
+public final class AcceptorInfo_impl extends LocalObject implements AcceptorInfo {
     private Acceptor_impl acceptor_; // The associated acceptor
 
-    //
-    // All accept callback objects
-    //
-    private java.util.Vector acceptCBVec_ = new java.util.Vector();
-
     // ------------------------------------------------------------------
     // Standard IDL to Java Mapping
     // ------------------------------------------------------------------
@@ -62,24 +57,6 @@
         return desc;
     }
 
-    public synchronized void add_accept_cb(org.apache.yoko.orb.OCI.AcceptCB cb) {
-        int length = acceptCBVec_.size();
-        for (int i = 0; i < length; i++)
-            if (acceptCBVec_.elementAt(i) == cb)
-                return; // Already registered
-        acceptCBVec_.addElement(cb);
-    }
-
-    public synchronized void remove_accept_cb(
-            org.apache.yoko.orb.OCI.AcceptCB cb) {
-        int length = acceptCBVec_.size();
-        for (int i = 0; i < length; i++)
-            if (acceptCBVec_.elementAt(i) == cb) {
-                acceptCBVec_.removeElementAt(i);
-                return;
-            }
-    }
-
     public synchronized String[] hosts() {
         if (acceptor_ == null)
             throw new org.omg.CORBA.NO_RESOURCES();
@@ -115,16 +92,6 @@
         acceptor_ = acceptor;
     }
 
-    synchronized void _OB_callAcceptCB(
-            org.apache.yoko.orb.OCI.TransportInfo info) {
-        int length = acceptCBVec_.size();
-        for (int i = 0; i < length; i++) {
-            org.apache.yoko.orb.OCI.AcceptCB cb = (org.apache.yoko.orb.OCI.AcceptCB) acceptCBVec_
-                    .elementAt(i);
-            cb.accept_cb(info);
-        }
-    }
-
     synchronized void _OB_destroy() {
         acceptor_ = null;
     }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Acceptor_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Acceptor_impl.java
index ba29635..0cc863a 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Acceptor_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Acceptor_impl.java
@@ -17,11 +17,20 @@
 
 package org.apache.yoko.orb.OCI.IIOP;
 
+import static org.apache.yoko.orb.OCI.IIOP.Exceptions.*;
+import static org.apache.yoko.orb.OB.MinorCodes.*;
+
+import java.io.InterruptedIOException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.apache.yoko.orb.CORBA.OutputStream;
-import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
+import org.apache.yoko.orb.OB.Assert;
+import org.apache.yoko.orb.OB.MinorCodes;
+import org.apache.yoko.orb.OCI.Transport;
+import org.omg.CORBA.COMM_FAILURE;
+import org.omg.IOP.Codec;
+import org.omg.IOP.TAG_INTERNET_IOP;
 
 final class Acceptor_impl extends org.omg.CORBA.LocalObject implements
         org.apache.yoko.orb.OCI.Acceptor {
@@ -42,11 +51,15 @@
 
     private java.net.InetAddress localAddress_; // The local address
 
-    private AcceptorInfo_impl info_; // Acceptor information
+    private final AcceptorInfo_impl info_; // Acceptor information
 
     private ListenerMap listenMap_;
 
-    private ConnectionHelper connectionHelper_;    // plugin for managing connection config/creation
+    private final ConnectionHelper connectionHelper_;    // plugin for managing connection config/creation
+
+    private final ExtendedConnectionHelper extendedConnectionHelper_;
+    
+    private final Codec codec_;
 
     // ------------------------------------------------------------------
     // Standard IDL to Java Mapping
@@ -57,7 +70,7 @@
     }
 
     public int tag() {
-        return org.omg.IOP.TAG_INTERNET_IOP.value;
+        return TAG_INTERNET_IOP.value;
     }
 
     public int handle() {
@@ -65,7 +78,7 @@
     }
 
     public void close() {
-        logger.fine("Closing connection to host=" + localAddress_ + ", port=" + port_);
+        logger.log(Level.FINE, "Closing server socket with host=" + localAddress_ + ", port=" + port_, new Exception("Stack trace"));
         //
         // Destroy the info object
         //
@@ -77,7 +90,9 @@
         try {
             socket_.close();
             socket_ = null;
+            logger.log(Level.FINE, "Closed server socket with host=" + localAddress_ + ", port=" + port_);
         } catch (java.io.IOException ex) {
+            logger.log(Level.FINE, "Exception closing server socket with host=" + localAddress_ + ", port=" + port_, ex);
         }
     }
 
@@ -115,22 +130,11 @@
                 return null; // Timeout
             else {
                 logger.log(Level.FINE, "Failure accepting connection for host=" + localAddress_ + ", port=" + port_, ex);
-
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorAccept)
-                                + ": " + ex.getMessage(),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorAccept,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+                throw asCommFailure(ex, MinorAccept);
             }
         } catch (java.io.IOException ex) {
             logger.log(Level.FINE, "Failure accepting connection for host=" + localAddress_ + ", port=" + port_, ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorAccept)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorAccept,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex, MinorAccept);
         }
 
         //
@@ -142,18 +146,13 @@
                 socket.setKeepAlive(true);
         } catch (java.net.SocketException ex) {
             logger.log(Level.FINE, "Failure configuring server connection for host=" + localAddress_ + ", port=" + port_, ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex, MinorSetsockopt);
         }
 
         //
         // Create new transport
         //
-        org.apache.yoko.orb.OCI.Transport tr = null;
+        Transport tr = null;
         try {
             tr = new Transport_impl(this, socket, listenMap_);
             logger.fine("Inbound connection received from " + socket.getInetAddress()); 
@@ -167,46 +166,28 @@
         }
 
         //
-        // Call callbacks
-        //
-        org.apache.yoko.orb.OCI.TransportInfo trInfo = tr.get_info();
-        try {
-            info_._OB_callAcceptCB(trInfo);
-        } catch (org.omg.CORBA.SystemException ex) {
-            tr.close();
-            logger.log(Level.FINE, "error calling connection callbacks", ex); 
-            throw ex;
-        }
-
-        //
         // Return new transport
         //
         return tr;
     }
 
-    public org.apache.yoko.orb.OCI.Transport connect_self() {
+    public Transport connect_self() {
         //
         // Create socket and connect to local address
         //
         java.net.Socket socket = null;
         try {
-            socket = connectionHelper_.createSelfConnection(localAddress_, port_);
+            if (connectionHelper_ != null) {
+                socket = connectionHelper_.createSelfConnection(localAddress_, port_);
+            } else {
+                socket = extendedConnectionHelper_.createSelfConnection(localAddress_, port_);
+            }
         } catch (java.net.ConnectException ex) {
             logger.log(Level.FINE, "Failure making self connection for host=" + localAddress_ + ", port=" + port_, ex);
-            throw new org.omg.CORBA.TRANSIENT(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+            throw asTransient(ex, MinorConnectFailed);
         } catch (java.io.IOException ex) {
             logger.log(Level.FINE, "Failure making self connection for host=" + localAddress_ + ", port=" + port_, ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex, MinorSocket);
         }
 
         //
@@ -220,20 +201,14 @@
                 socket.close();
             } catch (java.io.IOException e) {
             }
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex);
         }
 
         //
         // Create and return new transport
         //
-        org.apache.yoko.orb.OCI.Transport tr = null;
         try {
-            tr = new Transport_impl(this, socket, listenMap_);
+            return new Transport_impl(this, socket, listenMap_);
         } catch (org.omg.CORBA.SystemException ex) {
             try {
                 socket.close();
@@ -241,7 +216,6 @@
             }
             throw ex;
         }
-        return tr;
     }
 
     public void add_profiles(org.apache.yoko.orb.OCI.ProfileInfo profileInfo,
@@ -414,7 +388,7 @@
 
         for (int i = 0; i < hosts_.length; i++) {
             Util.extractAllProfileInfos(ior, profileInfoSeq, true, hosts_[i],
-                    port_, true);
+                    port_, true, codec_);
         }
 
         return profileInfoSeq.value;
@@ -429,81 +403,16 @@
     // Application programs must not use these functions directly
     // ------------------------------------------------------------------
 
-    public Acceptor_impl(String[] hosts, boolean multiProfile, int port,
-            int backlog, boolean keepAlive, ConnectionHelper helper, ListenerMap lm) {
-        hosts_ = hosts;
-        multiProfile_ = multiProfile;
-        keepAlive_ = keepAlive;
-        connectionHelper_ = helper;
-        info_ = new AcceptorInfo_impl(this);
-        listenMap_ = lm;
-        
-        if (backlog == 0)
-            backlog = 50; // 50 is the JDK's default value
-
-        //
-        // Get the local address for use by connect_self. Since we are
-        // binding to all network interfaces, we'll use the loopback
-        // address.
-        //
-        try {
-            localAddress_ = java.net.InetAddress.getLocalHost();
-        } catch (java.net.UnknownHostException ex) {
-            logger.log(Level.FINE, "Host resolution failure", ex); 
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
-        }
-
-        //
-        // Create socket and bind to all network interfaces
-        //
-        try {
-            socket_ = connectionHelper_.createServerSocket(port, backlog);
-
-            //
-            // Read back the port. This is needed if the port was selected by
-            // the operating system.
-            //
-            port_ = socket_.getLocalPort();
-            logger.fine("Acceptor created using socket " + socket_); 
-        } catch (java.net.BindException ex) {
-            logger.log(Level.FINE, "Failure creating server socket for host=" + localAddress_ + ", port=" + port, ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorBind)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorBind,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
-        } catch (java.io.IOException ex) {
-            logger.log(Level.FINE, "Failure creating server socket for host=" + localAddress_ + ", port=" + port, ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
-        }
-
-        //
-        // add these endpoints to the listenMap_
-        //
-        synchronized (listenMap_) {
-            for (int i = 0; i < hosts_.length; i++)
-                listenMap_.add(hosts_[i], (short) port_);
-        }
-    }
-
     public Acceptor_impl(String address, String[] hosts, boolean multiProfile,
-            int port, int backlog, boolean keepAlive, ConnectionHelper helper, ListenerMap lm) {
+            int port, int backlog, boolean keepAlive, ConnectionHelper helper, ExtendedConnectionHelper extendedConnectionHelper, ListenerMap lm, String[] params, Codec codec) {
         // System.out.println("Acceptor_impl");
+        Assert._OB_assert((helper == null) ^ (extendedConnectionHelper == null));
         hosts_ = hosts;
         multiProfile_ = multiProfile;
         keepAlive_ = keepAlive;
         connectionHelper_ = helper;
+        extendedConnectionHelper_ = extendedConnectionHelper;
+        codec_ = codec;
         info_ = new AcceptorInfo_impl(this);
         listenMap_ = lm;
 
@@ -514,22 +423,36 @@
         // Get the local address for use by connect_self
         //
         try {
-            localAddress_ = java.net.InetAddress.getByName(address);
+            if (address == null) {
+                //Since we are
+                // binding to all network interfaces, we'll use the loopback
+                // address.
+                localAddress_ = java.net.InetAddress.getLocalHost();                
+            } else {
+                localAddress_ = java.net.InetAddress.getByName(address);
+            }
         } catch (java.net.UnknownHostException ex) {
             logger.log(Level.FINE, "Host resolution failure", ex); 
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex);
         }
 
         //
         // Create socket and bind to requested network interface
         //
         try {
-            socket_ = connectionHelper_.createServerSocket(port, backlog, localAddress_);
+            if (address == null) {
+                if (connectionHelper_ != null) {
+                    socket_ = connectionHelper_.createServerSocket(port, backlog);
+                } else {
+                    socket_ = extendedConnectionHelper_.createServerSocket(port, backlog, params);
+                }
+            } else {
+                if (connectionHelper_ != null) {
+                    socket_ = connectionHelper_.createServerSocket(port, backlog, localAddress_);
+                } else {
+                    socket_ = extendedConnectionHelper_.createServerSocket(port, backlog, localAddress_, params);
+                }
+            }
 
             //
             // Read back the port. This is needed if the port was selected by
@@ -547,12 +470,7 @@
                     org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
         } catch (java.io.IOException ex) {
             logger.log(Level.FINE, "Failure creating server socket for host=" + localAddress_ + ", port=" + port, ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex, MinorSocket);
         }
 
         //
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConFactory_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConFactory_impl.java
index 5c58c95..5485bf9 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConFactory_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConFactory_impl.java
@@ -17,15 +17,42 @@
 
 package org.apache.yoko.orb.OCI.IIOP;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
+import org.apache.yoko.orb.CORBA.InputStream;
+import org.apache.yoko.orb.OB.Assert;
+import org.apache.yoko.orb.OB.IORDump;
+import org.apache.yoko.orb.OB.IORUtil;
+import org.apache.yoko.orb.OB.PROTOCOL_POLICY_ID;
+import org.apache.yoko.orb.OB.ProtocolPolicy;
+import org.apache.yoko.orb.OB.ProtocolPolicyHelper;
+import org.apache.yoko.orb.OCI.Buffer;
+import org.apache.yoko.orb.OCI.ConnectCB;
+import org.apache.yoko.orb.OCI.Connector;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.CORBA.Policy;
+import org.omg.IIOP.ProfileBody_1_0;
+import org.omg.IIOP.ProfileBody_1_0Helper;
+import org.omg.IOP.Codec;
+import org.omg.IOP.CodecFactory;
+import org.omg.IOP.CodecFactoryPackage.UnknownEncoding;
+import org.omg.IOP.ENCODING_CDR_ENCAPS;
+import org.omg.IOP.Encoding;
+import org.omg.IOP.IOR;
+import org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS;
+import org.omg.IOP.TAG_INTERNET_IOP;
+import org.omg.IOP.TaggedComponent;
+import org.omg.IOP.TaggedComponentHelper;
+import org.omg.IOP.TaggedProfile;
 
 final class ConFactory_impl extends org.omg.CORBA.LocalObject implements
         org.apache.yoko.orb.OCI.ConFactory {
     // the real logger backing instance.  We use the interface class as the locator
     static final Logger logger = Logger.getLogger(org.apache.yoko.orb.OCI.ConFactory.class.getName());
+    private static final Encoding CDR_1_2_ENCODING = new Encoding(ENCODING_CDR_ENCAPS.value, (byte) 1, (byte) 2);
 
     private boolean keepAlive_; // The keepalive flag
     
@@ -37,6 +64,8 @@
 
     private ConnectionHelper connectionHelper_;  // plugin for making ssl transport decisions.
 
+    private ExtendedConnectionHelper extendedConnectionHelper_;
+
     // ------------------------------------------------------------------
     // Standard IDL to Java Mapping
     // ------------------------------------------------------------------
@@ -46,26 +75,22 @@
     }
 
     public int tag() {
-        return org.omg.IOP.TAG_INTERNET_IOP.value;
+        return TAG_INTERNET_IOP.value;
     }
 
-    public String describe_profile(org.omg.IOP.TaggedProfile profile) {
-        org.apache.yoko.orb.OB.Assert
-                ._OB_assert(profile.tag == org.omg.IOP.TAG_INTERNET_IOP.value);
+    public String describe_profile(TaggedProfile profile) {
+        Assert._OB_assert(profile.tag == TAG_INTERNET_IOP.value);
 
         //
         // Get the IIOP profile body
         //
         byte[] data = profile.profile_data;
-        org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
-                data, data.length);
-        org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
-                buf);
+        Buffer buf = new Buffer(data, data.length);
+        InputStream in = new InputStream(buf);
         in._OB_readEndian();
-        org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
-                .read(in);
+        ProfileBody_1_0 body = ProfileBody_1_0Helper.read(in);
 
-        StringBuffer result = new StringBuffer();
+        StringBuilder result = new StringBuilder();
 
         //
         // Show general info
@@ -73,144 +98,127 @@
         result.append("iiop_version: " + (int) body.iiop_version.major + '.'
                 + (int) body.iiop_version.minor + '\n');
         result.append("host: " + body.host + '\n');
-        int port;
-        if (body.port < 0)
-            port = 0xffff + (int) body.port + 1;
-        else
-            port = body.port;
+        final int port = ((char)body.port);
         result.append("port: " + port + '\n');
         result.append("object_key: (" + body.object_key.length + ")\n");
-        String tmp = org.apache.yoko.orb.OB.IORUtil.dump_octets(
-                body.object_key, 0, body.object_key.length);
-        result.append(tmp);
+        IORUtil.dump_octets(body.object_key, 0, body.object_key.length, result);
 
         //
         // Print IIOP 1.1 information (components)
         //
         if (body.iiop_version.major > 1 || body.iiop_version.minor >= 1) {
-            int l = in.read_ulong();
+            final int tcCount = in.read_ulong();
 
-            for (int i = 0; i < l; i++) {
-                org.omg.IOP.TaggedComponent component = org.omg.IOP.TaggedComponentHelper
-                        .read(in);
+            for (int i = 0; i < tcCount; i++) {
+                TaggedComponent component = TaggedComponentHelper.read(in);
 
-                String desc = org.apache.yoko.orb.OB.IORUtil
-                        .describe_component(component);
-                result.append(desc);
+                IORUtil.describe_component(component, result);
             }
         }
 
         return result.toString();
     }
 
-    public org.apache.yoko.orb.OCI.Connector[] create_connectors(
-            org.omg.IOP.IOR ior, org.omg.CORBA.Policy[] policies) {
+    private static final Connector[] EMPTY_CONNECTORS = new Connector[0];
+
+    public Connector[] create_connectors(IOR ior, Policy[] policies) {
         if (logger.isLoggable(Level.FINEST)) {
-            logger.finest("Creating connection for ior: " + org.apache.yoko.orb.OB.IORDump.PrintObjref(orb_, ior)); 
+            logger.finest("Creating connection for ior: " + IORDump.PrintObjref(orb_, ior));
         }
         
         //
         // Check whether policies are satisfied
         //
-        for (int i = 0; i < policies.length; i++) {
-            if (policies[i].policy_type() == org.apache.yoko.orb.OB.PROTOCOL_POLICY_ID.value) {
-                org.apache.yoko.orb.OB.ProtocolPolicy protocolPolicy = org.apache.yoko.orb.OB.ProtocolPolicyHelper
-                        .narrow(policies[i]);
+        for (Policy policy: policies) {
+            if (policy.policy_type() == PROTOCOL_POLICY_ID.value) {
+                ProtocolPolicy protocolPolicy = ProtocolPolicyHelper.narrow(policy);
                 if (!protocolPolicy.contains(PLUGIN_ID.value))
-                    return new org.apache.yoko.orb.OCI.Connector[0];
+                    return EMPTY_CONNECTORS;
             }
         }
 
         //
         // Create Connectors from profiles
         //
-        java.util.Vector seq = new java.util.Vector();
-        for (int i = 0; i < ior.profiles.length; i++) {
-            if (ior.profiles[i].tag == tag()) {
+        final List<Connector> connectors = new ArrayList<>();
+        for (TaggedProfile profile: ior.profiles) {
+            if (profile.tag != tag()) continue;
+
+            //
+            // Get the IIOP profile body
+            //
+            final byte[] data = profile.profile_data;
+            final Buffer buf = new Buffer(data, data.length);
+            final InputStream in = new InputStream(buf, 0, false);
+            in._OB_readEndian();
+            final ProfileBody_1_0 body = ProfileBody_1_0Helper.read(in);
+
+            //
+            // Create new connector for this profile
+            //
+            final int port = ((char)body.port);
+            ConnectCB[] cbs = info_._OB_getConnectCBSeq();
+            logger.fine("Creating connector to host=" + body.host +", port=" + port);
+            Codec codec = null;
+            try {
+                    codec = ((CodecFactory) orb_.resolve_initial_references("CodecFactory")).create_codec(CDR_1_2_ENCODING);
+            } catch (InvalidName e) {
+                logger.fine("Could not obtain codec factory using name 'CodecFactory'");
+            } catch (UnknownEncoding e) {
+                logger.fine("Could not obtain codec using encoding " + CDR_1_2_ENCODING);
+            }
+            connectors.add(createConnector(ior, policies, body.host, port, cbs, codec));
+
+            //
+            // If this is a 1.1 profile, check for
+            // TAG_ALTERNATE_IIOP_ADDRESS in the components
+            //
+            if (body.iiop_version.major > 1 || body.iiop_version.minor > 0) {
                 //
-                // Get the IIOP profile body
+                // Unmarshal the tagged components
                 //
-                byte[] data = ior.profiles[i].profile_data;
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
-                        data, data.length);
-                org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
-                        buf, 0, false);
-                in._OB_readEndian();
-                org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
-                        .read(in);
+                final int tcCount = in.read_ulong();
+                List<TaggedComponent> components = new ArrayList<>(tcCount);
+                for (int c = 0; c < tcCount; c++)
+                    components.add(TaggedComponentHelper.read(in));
 
                 //
-                // Create new connector for this profile
+                // Check for TAG_ALTERNATE_IIOP_ADDRESS
                 //
-                int port;
-                if (body.port < 0)
-                    port = 0xffff + (int) body.port + 1;
-                else
-                    port = (int) body.port;
-                org.apache.yoko.orb.OCI.ConnectCB[] cbs = info_
-                        ._OB_getConnectCBSeq();
-                logger.fine("Creating connector to host=" + body.host +", port=" + port);
-                seq.addElement(new Connector_impl(ior, policies, body.host, port, keepAlive_,
-                        cbs, listenMap_, connectionHelper_));
+                for (TaggedComponent tc: components) {
+                    if (tc.tag == TAG_ALTERNATE_IIOP_ADDRESS.value) {
+                        final Buffer cbuf = new Buffer(tc.component_data, tc.component_data.length);
+                        final InputStream cin = new InputStream(cbuf, 0, false);
+                        cin._OB_readEndian();
+                        final String host = cin.read_string();
+                        final short s = cin.read_ushort();
+                        final int cport = ((char)s);
 
-                //
-                // If this is a 1.1 profile, check for
-                // TAG_ALTERNATE_IIOP_ADDRESS in the components
-                //
-                if (body.iiop_version.major > 1 || body.iiop_version.minor > 0) {
-                    //
-                    // Unmarshal the tagged components
-                    //
-                    int len = in.read_ulong();
-                    org.omg.IOP.TaggedComponent[] components = new org.omg.IOP.TaggedComponent[len];
-                    for (int c = 0; c < len; c++)
-                        components[c] = org.omg.IOP.TaggedComponentHelper
-                                .read(in);
-
-                    //
-                    // Check for TAG_ALTERNATE_IIOP_ADDRESS
-                    //
-                    for (int c = 0; c < components.length; c++)
-                        if (components[c].tag == org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS.value) {
-                            byte[] cdata = components[c].component_data;
-                            int clen = components[c].component_data.length;
-                            org.apache.yoko.orb.OCI.Buffer cbuf = new org.apache.yoko.orb.OCI.Buffer(
-                                    cdata, clen);
-                            org.apache.yoko.orb.CORBA.InputStream cin = new org.apache.yoko.orb.CORBA.InputStream(
-                                    cbuf, 0, false);
-                            cin._OB_readEndian();
-                            String host = cin.read_string();
-                            short s = cin.read_ushort();
-                            int cport;
-                            if (s < 0)
-                                cport = 0xffff + (int) s + 1;
-                            else
-                                cport = (int) s;
-
-                            //
-                            // Create new connector for this component
-                            //
-                            org.apache.yoko.orb.OCI.ConnectCB[] ccbs = info_
-                                    ._OB_getConnectCBSeq();
-                            logger.fine("Creating alternate connector to host=" + host +", port=" + cport);
-                            seq.addElement(new Connector_impl(ior, policies, host, cport,
-                                    keepAlive_, ccbs, listenMap_, connectionHelper_));
-                        }
+                        //
+                        // Create new connector for this component
+                        //
+                        ConnectCB[] ccbs = info_._OB_getConnectCBSeq();
+                        logger.fine("Creating alternate connector to host=" + host + ", port=" + cport);
+                        connectors.add(createConnector(ior, policies, host, cport, ccbs, codec));
+                    }
                 }
             }
         }
 
-        org.apache.yoko.orb.OCI.Connector[] result = new org.apache.yoko.orb.OCI.Connector[seq
-                .size()];
-        seq.copyInto(result);
-        return result;
+        return connectors.toArray(EMPTY_CONNECTORS);
     }
 
-    public boolean equivalent(org.omg.IOP.IOR ior1, org.omg.IOP.IOR ior2) {
+    private Connector createConnector(IOR ior, Policy[] policies, String host, int port, ConnectCB[] cbs, Codec codec) {
+        return ((connectionHelper_ != null) ?
+                new Connector_impl(ior, policies, host, port, keepAlive_, cbs, listenMap_, connectionHelper_, codec) :
+                new Connector_impl(ior, policies, host, port, keepAlive_, cbs, listenMap_, extendedConnectionHelper_, codec));
+    }
+
+    public boolean equivalent(IOR ior1, IOR ior2) {
         return Util.equivalent(ior1, ior2);
     }
 
-    public int hash(org.omg.IOP.IOR ior, int max) {
+    public int hash(IOR ior, int max) {
         return Util.hash(ior, max);
     }
 
@@ -232,6 +240,15 @@
         connectionHelper_ = helper;
     }
 
+    public ConFactory_impl(org.omg.CORBA.ORB orb, boolean keepAlive, ListenerMap lm, ExtendedConnectionHelper helper) {
+        // System.out.println("ConFactory");
+        orb_ = orb;
+        keepAlive_ = keepAlive;
+        info_ = new ConFactoryInfo_impl();
+        listenMap_ = lm;
+        extendedConnectionHelper_ = helper;
+    }
+
     public void finalize() throws Throwable {
         // System.out.println("~ConFactory");
         super.finalize();
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfoOperations.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfoOperations.java
index c222f8b..f6eeea5 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfoOperations.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfoOperations.java
@@ -20,6 +20,9 @@
 //
 // IDL:orb.yoko.apache.org/OCI/IIOP/ConnectorInfo:1.0
 //
+
+import org.apache.yoko.orb.OCI.Connector;
+
 /**
  *
  * Information on an IIOP OCI Connector object.
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfo_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfo_impl.java
index a076a8d..21411a8 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfo_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ConnectorInfo_impl.java
@@ -17,114 +17,88 @@
 
 package org.apache.yoko.orb.OCI.IIOP;
 
-import org.apache.yoko.orb.OCI.IIOP.ConnectorInfo;
-import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
+import static org.apache.yoko.orb.OCI.IIOP.Exceptions.*;
 
-public final class ConnectorInfo_impl extends org.omg.CORBA.LocalObject
-        implements ConnectorInfo {
-    private Connector_impl connector_; // The associated connector
+import org.apache.yoko.orb.OCI.ConnectCB;
+import org.omg.CORBA.LocalObject;
+import org.omg.IOP.TAG_INTERNET_IOP;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.*;
+
+/**
+ * Immutable memo of the endpoint details for a connection. The InetAddress
+ * is looked up when first needed but never changed again. It is used in
+ * hashcode() and equals().
+ */
+public final class ConnectorInfo_impl extends LocalObject implements ConnectorInfo {
+    private final String host;
+    private final short port;
+    private volatile InetAddress addr; // initialised lazily
 
     //
     // All connect callback objects
     //
-    private java.util.Vector connectCBVec_ = new java.util.Vector();
+    private final List<ConnectCB> callbacks;
 
     // ------------------------------------------------------------------
     // Standard IDL to Java Mapping
     // ------------------------------------------------------------------
 
-    public String id() {
-        return PLUGIN_ID.value;
-    }
+    public String id() {return PLUGIN_ID.value;}
 
-    public int tag() {
-        return org.omg.IOP.TAG_INTERNET_IOP.value;
-    }
+    public int tag() {return TAG_INTERNET_IOP.value;}
 
-    public synchronized String describe() {
-        short remotePort = remote_port();
+    public String describe() {return String.format("id: %s%nremote address: %s:%d", PLUGIN_ID.value, remote_addr(), port);}
 
-        String desc = "id: " + PLUGIN_ID.value;
-        desc += "\nremote address: ";
-        desc += remote_addr();
-        desc += ":";
-        desc += (remotePort < 0 ? 0xffff + (int) remotePort + 1 : remotePort);
+    public String remote_addr() {return getInetAddress().getHostAddress();}
 
-        return desc;
-    }
-
-    public synchronized void add_connect_cb(org.apache.yoko.orb.OCI.ConnectCB cb) {
-        int length = connectCBVec_.size();
-        for (int i = 0; i < length; i++)
-            if (connectCBVec_.elementAt(i) == cb)
-                return; // Already registered
-        connectCBVec_.addElement(cb);
-    }
-
-    public synchronized void remove_connect_cb(
-            org.apache.yoko.orb.OCI.ConnectCB cb) {
-        int length = connectCBVec_.size();
-        for (int i = 0; i < length; i++)
-            if (connectCBVec_.elementAt(i) == cb) {
-                connectCBVec_.removeElementAt(i);
-                return;
-            }
-    }
-
-    public synchronized String remote_addr() {
-        if (connector_ == null)
-            throw new org.omg.CORBA.NO_RESOURCES("No connector");
-
-        try {
-            java.net.InetAddress address = java.net.InetAddress
-                    .getByName(connector_.host_);
-            return address.getHostAddress();
-        } catch (java.net.UnknownHostException ex) {
-            throw new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO);
-        }
-    }
-
-    public synchronized short remote_port() {
-        if (connector_ == null)
-            throw new org.omg.CORBA.NO_RESOURCES("No connector");
-
-        int port = connector_.port_;
-
-        if (port >= 0x8000)
-            return (short) (port - 0xffff - 1);
-        else
-            return (short) port;
-    }
+    public short remote_port() {return port;}
 
     // ------------------------------------------------------------------
     // Yoko internal functions
     // Application programs must not use these functions directly
     // ------------------------------------------------------------------
 
-    ConnectorInfo_impl(Connector_impl connector,
-            org.apache.yoko.orb.OCI.ConnectCB[] cb) {
-        connector_ = connector;
-
-        for (int i = 0; i < cb.length; i++)
-            connectCBVec_.addElement(cb[i]);
+    ConnectorInfo_impl(String host, int port, ConnectCB...cb) {
+        this.host = host;
+        this.port = (short)port;
+        if (cb == null || cb.length == 0)
+            callbacks = Collections.emptyList();
+        else
+            callbacks = Collections.unmodifiableList(new ArrayList<ConnectCB>(Arrays.asList(cb)));
     }
 
-    synchronized void _OB_callConnectCB(
-            org.apache.yoko.orb.OCI.TransportInfo info) {
-        int length = connectCBVec_.size();
-        for (int i = 0; i < length; i++) {
-            org.apache.yoko.orb.OCI.ConnectCB cb = (org.apache.yoko.orb.OCI.ConnectCB) connectCBVec_
-                    .elementAt(i);
-            cb.connect_cb(info);
+    String getHost() { return host; }
+
+    int getPort() { return (char)port; }
+
+    private InetAddress getInetAddress() {
+        if (addr == null) synchronized (this) {
+            if (addr == null) try {
+                addr = InetAddress.getByName(host);
+            } catch (UnknownHostException ex) {
+                throw asCommFailure(ex);
+            }
         }
+        return addr;
     }
 
-    synchronized void _OB_destroy() {
-        connector_ = null;
+    synchronized void _OB_callConnectCB(org.apache.yoko.orb.OCI.TransportInfo info) {
+        for (ConnectCB cb : callbacks) cb.connect_cb(info);
     }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) return true;
+        if (!!! (other instanceof ConnectorInfo_impl)) return false;
+
+        ConnectorInfo_impl that = (ConnectorInfo_impl) other;
+
+        return (this.port == that.port) && this.getInetAddress().equals(that.getInetAddress());
+    }
+
+    @Override
+    public int hashCode() {return 31*port + getInetAddress().hashCode();}
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Connector_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Connector_impl.java
index a2f346d..b257a22 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Connector_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Connector_impl.java
@@ -17,56 +17,54 @@
 
 package org.apache.yoko.orb.OCI.IIOP;
 
+import static org.apache.yoko.orb.OCI.IIOP.Exceptions.*;
+
 import java.util.Arrays;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.yoko.orb.OCI.ConnectCB;
+import org.apache.yoko.orb.OCI.Connector;
 import org.apache.yoko.orb.OCI.ProfileInfo;
 import org.apache.yoko.orb.OCI.ProfileInfoHolder;
 import org.omg.CORBA.Policy;
 import org.omg.CSIIOP.TAG_CSI_SEC_MECH_LIST;
+import org.omg.IOP.Codec;
 import org.omg.IOP.IOR;
 import org.omg.IOP.TaggedComponent;
 
-final class Connector_impl extends org.omg.CORBA.LocalObject implements
-        org.apache.yoko.orb.OCI.Connector {
+final class Connector_impl extends org.omg.CORBA.LocalObject implements Connector {
 
     // the real logger backing instance.  We use the interface class as the locator
-    static final Logger logger = Logger.getLogger(org.apache.yoko.orb.OCI.Connector.class.getName());
+    static final Logger logger = Logger.getLogger(Connector.class.getName());
 
     private final IOR ior_;    // the target IOR we're connecting with
 
     private final Policy[] policies_;    // the policies used for the connection.
 
-    // Some data member must not be private because the info object
-    // must be able to access them
-    public String host_; // The host
-
-    public int port_; // The port
-
     private boolean keepAlive_; // The keepalive flag
 
-    private ConnectorInfo_impl info_; // Connector information
+    private final ConnectorInfo_impl info_; // Connector information
 
     private java.net.Socket socket_; // The socket
 
     private ListenerMap listenMap_;
 
-    private ConnectionHelper connectionHelper_;
+    private final ConnectionHelper connectionHelper_;
 
     private byte[] transportInfo;
 
+    private final ExtendedConnectionHelper extendedConnectionHelper_;
+
+    private final Codec codec_;
+
 
     // ------------------------------------------------------------------
     // Private and protected functions
     // ------------------------------------------------------------------
 
     private void close() {
-        logger.fine("Closing connection to host=" + host_ + ", port=" + port_);
-        //
-        // Destroy the info object
-        //
-        info_._OB_destroy();
+        logger.fine("Closing connection to host=" + this.info_.getHost() + ", port=" + this.info_.getPort());
 
         //
         // Close the socket
@@ -100,15 +98,10 @@
         //
         java.net.InetAddress address;
         try {
-            address = java.net.InetAddress.getByName(host_);
+            address = java.net.InetAddress.getByName(this.info_.getHost());
         } catch (java.net.UnknownHostException ex) {
             logger.log(Level.FINE, "Host resolution error", ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex);
         }
 
 
@@ -116,23 +109,27 @@
         // Create socket and connect
         //
         try {
-            logger.fine("Connecting to host=" + address + ", port=" + port_);
-            socket_ = connectionHelper_.createSocket(ior_, policies_, address, port_);
-            logger.fine("Connection created with socket " + socket_); 
+            logger.fine("Connecting to host=" + address + ", port=" + this.info_.getPort());
+            if (connectionHelper_ != null) {
+                socket_ = connectionHelper_.createSocket(ior_, policies_, address, this.info_.getPort());
+            } else {
+                socket_ = extendedConnectionHelper_.createSocket(ior_, policies_, address, this.info_.getPort());
+            }
+            logger.fine("Connection created with socket " + socket_);
         } catch (java.net.ConnectException ex) {
-            logger.log(Level.FINE, "Error connecting to host=" + address + ", port=" + port_, ex);
+            logger.log(Level.FINE, "Error connecting to host=" + address + ", port=" + this.info_.getPort(), ex);
             throw new org.omg.CORBA.TRANSIENT(
                     org.apache.yoko.orb.OB.MinorCodes
                             .describeTransient(org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed)
-                            + ": " + ex.getMessage(),
+                            + "Error connecting to host=" + address + ", port=" + this.info_.getPort() + ": " + ex.getMessage(),
                     org.apache.yoko.orb.OB.MinorCodes.MinorConnectFailed,
                     org.omg.CORBA.CompletionStatus.COMPLETED_NO);
         } catch (java.io.IOException ex) {
-            logger.log(Level.FINE, "Error connecting to host=" + address + ", port=" + port_, ex);
+            logger.log(Level.FINE, "Error connecting to host=" + address + ", port=" + this.info_.getPort(), ex);
             throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
                     org.apache.yoko.orb.OB.MinorCodes
                             .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
-                            + ": " + ex.getMessage(),
+                            + "Error connecting to host=" + address + ", port=" + this.info_.getPort() + ": " + ex.getMessage(),
                     org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
                     org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
         }
@@ -151,12 +148,7 @@
                 socket_.close();
             } catch (java.io.IOException e) {
             }
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw Exceptions.asCommFailure(ex);
         }
 
         //
@@ -164,7 +156,7 @@
         //
         org.apache.yoko.orb.OCI.Transport tr = null;
         try {
-            tr = new Transport_impl(this, socket_, listenMap_);
+            tr = new Transport_impl(socket_, listenMap_);
             socket_ = null;
         } catch (org.omg.CORBA.SystemException ex) {
             logger.log(Level.FINE, "Transport creation error", ex);
@@ -213,7 +205,11 @@
 
         public void run() {
             try {
-                so_ = connectionHelper_.createSocket(ior_, policies_, address_, port_);
+                if (connectionHelper_ != null) {
+                    so_ = connectionHelper_.createSocket(ior_, policies_, address_, Connector_impl.this.info_.getPort());
+                } else {
+                    so_ = extendedConnectionHelper_.createSocket(ior_, policies_, address_, Connector_impl.this.info_.getPort());
+                }
             } catch (java.io.IOException ex) {
                 logger.log(Level.FINE, "Socket creation error", ex);
                 ex_ = ex;
@@ -271,15 +267,10 @@
         //
         java.net.InetAddress address = null;
         try {
-            address = java.net.InetAddress.getByName(host_);
+            address = java.net.InetAddress.getByName(this.info_.getHost());
         } catch (java.net.UnknownHostException ex) {
             logger.log(Level.FINE, "Host resolution error", ex);
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorGethostbyname,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw asCommFailure(ex);
         }
 
         //
@@ -325,12 +316,7 @@
                 socket_.close();
             } catch (java.io.IOException e) {
             }
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt)
-                            + ": " + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            throw Exceptions.asCommFailure(ex);
         }
 
         //
@@ -338,7 +324,7 @@
         //
         org.apache.yoko.orb.OCI.Transport tr = null;
         try {
-            tr = new Transport_impl(this, socket_, listenMap_);
+            tr = new Transport_impl(socket_, listenMap_);
             socket_ = null;
         } catch (org.omg.CORBA.SystemException ex) {
             logger.log(Level.FINE, "Transport setup error", ex);
@@ -383,8 +369,8 @@
 
         org.apache.yoko.orb.OCI.ProfileInfoSeqHolder profileInfoSeq = new org.apache.yoko.orb.OCI.ProfileInfoSeqHolder();
         profileInfoSeq.value = new org.apache.yoko.orb.OCI.ProfileInfo[0];
-        Util.extractAllProfileInfos(ior, profileInfoSeq, true, host_, port_,
-                false);
+        Util.extractAllProfileInfos(ior, profileInfoSeq, true, this.info_.getHost(), this.info_.getPort(),
+                false, codec_);
 
         //check that the transport info matches ours.
         //we could return just the profiles that match rather than bailing if one doesn't match.
@@ -416,23 +402,23 @@
         //
         // Compare ports
         //
-        if (port_ != impl.port_)
+        if (this.info_.getPort() != impl.info_.getPort())
             return false;
 
         //
         // Direct host name comparison
         //
-        if (!host_.equals(impl.host_)) {
+        if (!this.info_.getHost().equals(impl.info_.getHost())) {
             //
             // Direct host name comparision failed - must look up
             // addresses to be really sure if the hosts differ
             //
             try {
                 java.net.InetAddress addr1 = java.net.InetAddress
-                        .getByName(host_);
+                        .getByName(this.info_.getHost());
 
                 java.net.InetAddress addr2 = java.net.InetAddress
-                        .getByName(impl.host_);
+                        .getByName(impl.info_.getHost());
 
                 if (!addr1.equals(addr2))
                     return false;
@@ -445,11 +431,6 @@
         }
 
         return Arrays.equals(transportInfo, impl.transportInfo);
-
-        //
-        // OK, connectors are the same
-        //
-//        return true;
     }
 
     byte[] extractTransportInfo(IOR ior) {
@@ -477,22 +458,28 @@
     // Application programs must not use these functions directly
     // ------------------------------------------------------------------
 
-    public Connector_impl(org.omg.IOP.IOR ior, org.omg.CORBA.Policy[] policies, String host, int port, boolean keepAlive,
-            org.apache.yoko.orb.OCI.ConnectCB[] cb, ListenerMap lm, ConnectionHelper helper) {
-        // System.out.println("Connector_impl");
+    private Connector_impl(IOR ior, Policy[] policies, String host, int port, boolean keepAlive, ConnectCB[] cb, ListenerMap lm, ConnectionHelper helper, ExtendedConnectionHelper xhelper, Codec codec) {
+        if ((null == helper) && (null == xhelper)) throw new IllegalArgumentException("Both connection helpers must not be null");
         ior_ = ior;
         policies_ = policies;
-        host_ = host;
-        port_ = port;
         keepAlive_ = keepAlive;
-        info_ = new ConnectorInfo_impl(this, cb);
+        info_ = new ConnectorInfo_impl(host, port, cb);
         listenMap_ = lm;
         connectionHelper_ = helper;
+        extendedConnectionHelper_ = xhelper;
+        codec_ = codec;
         transportInfo = extractTransportInfo(ior);
     }
 
+    public Connector_impl(IOR ior, Policy[] policies, String host, int port, boolean keepAlive, ConnectCB[] cb, ListenerMap lm, ConnectionHelper helper, Codec codec) {
+        this(ior, policies, host, port, keepAlive, cb, lm, helper, null, codec);
+    }
+
+    public Connector_impl(IOR ior, Policy[] policies, String host, int port, boolean keepAlive, ConnectCB[] cb, ListenerMap lm, ExtendedConnectionHelper xhelper, Codec codec) {
+        this(ior, policies, host, port, keepAlive, cb, lm, null, xhelper, codec);
+    }
+
     public void finalize() throws Throwable {
-        // System.out.println("~Connector_impl");
         if (socket_ != null)
             close();
 
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/DefaultConnectionHelper.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/DefaultConnectionHelper.java
index 0e7b656..3b02365 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/DefaultConnectionHelper.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/DefaultConnectionHelper.java
@@ -28,6 +28,7 @@
 import java.net.InetAddress;
 import java.net.Socket;
 import java.net.ServerSocket;
+import java.net.SocketException;
 
 import org.omg.CORBA.ORB;
 import org.omg.CORBA.Policy;
@@ -40,19 +41,30 @@
     }
 
     public Socket createSocket(IOR ior, Policy[] policies, InetAddress address, int port) throws IOException, ConnectException {
-        return new Socket(address, port);
+        return setOptions(new Socket(address, port));
     }
 
     public Socket createSelfConnection(InetAddress address, int port) throws IOException, ConnectException {
-        return new Socket(address, port);
+        return setOptions(new Socket(address, port));
+    }
+
+    private Socket setOptions(Socket socket) throws SocketException {
+        socket.setTcpNoDelay(true);
+        return socket;
     }
 
     public ServerSocket createServerSocket(int port, int backlog)  throws IOException, ConnectException {
-        return new ServerSocket(port, backlog);
+        return setOptions(new ServerSocket(port, backlog));
     }
 
     public ServerSocket createServerSocket(int port, int backlog, InetAddress address) throws IOException, ConnectException {
-        return new ServerSocket(port, backlog, address);
+        return setOptions(new ServerSocket(port, backlog, address));
+    }
+
+    private ServerSocket setOptions(ServerSocket serverSocket) throws SocketException {
+        serverSocket.setReuseAddress(true);
+        serverSocket.setPerformancePreferences(0, 2, 1);
+        return serverSocket;
     }
 }
 
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Exceptions.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Exceptions.java
new file mode 100644
index 0000000..16b7d46
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Exceptions.java
@@ -0,0 +1,35 @@
+package org.apache.yoko.orb.OCI.IIOP;
+
+import static org.apache.yoko.orb.OB.MinorCodes.*;
+
+import org.omg.CORBA.COMM_FAILURE;
+import org.omg.CORBA.TRANSIENT;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+
+import static org.apache.yoko.orb.OB.MinorCodes.MinorSetsockopt;
+import static org.apache.yoko.orb.OB.MinorCodes.describeCommFailure;
+import static org.omg.CORBA.CompletionStatus.COMPLETED_NO;
+
+enum Exceptions {;
+    static COMM_FAILURE asCommFailure(SocketException e) {return asCommFailure(e, MinorSetsockopt);}
+    static COMM_FAILURE asCommFailure(UnknownHostException e) {return asCommFailure(e, MinorGethostbyname);}
+
+    static COMM_FAILURE asCommFailure(IOException e, int minor) {
+        String msg = String.format("%s: %s", describeCommFailure(minor), e.getMessage());
+        return (COMM_FAILURE) new COMM_FAILURE(msg, minor, COMPLETED_NO).initCause(e);
+    }
+
+    static COMM_FAILURE asCommFailure(Exception e, int minor, String message) {
+        String msg = String.format("%s: %s: %s", describeCommFailure(minor), message, e.getMessage());
+        return (COMM_FAILURE) new COMM_FAILURE(msg, minor, COMPLETED_NO).initCause(e);
+    }
+
+    static TRANSIENT asTransient(Exception e, int minor) {
+        String msg = String.format("%s: %s", describeTransient(minor), e.getMessage());
+        return (TRANSIENT) new TRANSIENT(msg, minor, COMPLETED_NO);
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ExtendedConnectionHelper.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ExtendedConnectionHelper.java
new file mode 100644
index 0000000..f5515c1
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/ExtendedConnectionHelper.java
@@ -0,0 +1,61 @@
+/**
+ *
+ * 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.
+ */
+
+
+/**
+ * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
+ */
+
+package org.apache.yoko.orb.OCI.IIOP;
+
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.ServerSocket;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Policy;
+import org.omg.IOP.IOR;
+
+//
+// IDL:orb.yoko.apache.org/OCI/IIOP/AcceptorInfo:1.0
+//
+/**
+ *
+ * Information on an IIOP OCI Acceptor object.
+ *
+ * @see Acceptor
+ * @see AcceptorInfo
+ *
+ **/
+
+public interface ExtendedConnectionHelper
+{
+    public void init(ORB orb, String parms);
+
+    public Socket createSocket(IOR ior, Policy[] policies, InetAddress address, int port) throws IOException, ConnectException;
+
+    public Socket createSelfConnection(InetAddress address, int port) throws IOException, ConnectException;
+
+    public ServerSocket createServerSocket(int port, int backlog, String[] params)  throws IOException, ConnectException;
+
+    public ServerSocket createServerSocket(int port, int backlog, InetAddress address, String[] params) throws IOException, ConnectException;
+
+}
+
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Plugin_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Plugin_impl.java
index ca0b5c6..fa7150f 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Plugin_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Plugin_impl.java
@@ -18,6 +18,7 @@
 package org.apache.yoko.orb.OCI.IIOP;
 
 import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
+import org.omg.CORBA.ORB;
 
 public final class Plugin_impl extends org.omg.CORBA.LocalObject implements
         org.apache.yoko.orb.OCI.Plugin {
@@ -25,7 +26,9 @@
 
     private ListenerMap listenMap_; // list of listenPoints
 
-    private ConnectionHelper connectionHelper_;   // SSL connection helper
+    private final ConnectionHelper connectionHelper_;   // SSL connection helper
+
+    private final ExtendedConnectionHelper extendedConnectionHelper_;
 
     // ------------------------------------------------------------------
     // Standard IDL to Java Mapping
@@ -60,7 +63,11 @@
                     .resolve_initial_references("OCIConFactoryRegistry");
             org.apache.yoko.orb.OCI.ConFactoryRegistry registry = org.apache.yoko.orb.OCI.ConFactoryRegistryHelper
                     .narrow(obj);
-            registry.add_factory(new ConFactory_impl(orb_, keepAlive, listenMap_, connectionHelper_));
+            if (connectionHelper_ != null) {
+                registry.add_factory(new ConFactory_impl(orb_, keepAlive, listenMap_, connectionHelper_));
+            } else {
+                registry.add_factory(new ConFactory_impl(orb_, keepAlive, listenMap_, extendedConnectionHelper_));                
+            }
         } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
             org.apache.yoko.orb.OB.Assert._OB_assert(ex);
         } catch (org.apache.yoko.orb.OCI.FactoryAlreadyExists ex) {
@@ -95,7 +102,7 @@
                     .resolve_initial_references("OCIAccFactoryRegistry");
             org.apache.yoko.orb.OCI.AccFactoryRegistry registry = org.apache.yoko.orb.OCI.AccFactoryRegistryHelper
                     .narrow(obj);
-            registry.add_factory(new AccFactory_impl(orb_, listenMap_, connectionHelper_));
+            registry.add_factory(new AccFactory_impl(orb_, listenMap_, connectionHelper_, extendedConnectionHelper_));
         } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
             org.apache.yoko.orb.OB.Assert._OB_assert(ex);
         } catch (org.apache.yoko.orb.OCI.FactoryAlreadyExists ex) {
@@ -113,6 +120,14 @@
     public Plugin_impl(org.omg.CORBA.ORB orb, ConnectionHelper helper) {
         orb_ = orb;
         connectionHelper_ = helper;
+        extendedConnectionHelper_ = null;
+        listenMap_ = new ListenerMap();
+    }
+
+    public Plugin_impl(ORB orb, ExtendedConnectionHelper helper) {
+        orb_ = orb;
+        connectionHelper_ = null;
+        extendedConnectionHelper_ = helper;
         listenMap_ = new ListenerMap();
     }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/TransportInfo_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/TransportInfo_impl.java
index 54ce73e..353de16 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/TransportInfo_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/TransportInfo_impl.java
@@ -18,27 +18,32 @@
 package org.apache.yoko.orb.OCI.IIOP;
 
 import java.net.Socket;
+import java.util.Objects;
 
-import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
-import org.apache.yoko.orb.OCI.IIOP.TransportInfo;
+import org.apache.yoko.orb.CORBA.InputStream;
+import org.apache.yoko.orb.OB.Net;
+import org.apache.yoko.orb.OCI.*;
+import org.omg.BiDirPolicy.BIDIRECTIONAL_POLICY_TYPE;
+import org.omg.BiDirPolicy.BOTH;
+import org.omg.BiDirPolicy.BidirectionalPolicy;
+import org.omg.BiDirPolicy.BidirectionalPolicyHelper;
+import org.omg.CORBA.LocalObject;
+import org.omg.CORBA.NO_RESOURCES;
+import org.omg.CORBA.Policy;
+import org.omg.IIOP.BiDirIIOPServiceContext;
+import org.omg.IIOP.BiDirIIOPServiceContextHelper;
+import org.omg.IIOP.ListenPoint;
+import org.omg.IOP.BI_DIR_IIOP;
+import org.omg.IOP.ServiceContext;
+import org.omg.IOP.TAG_INTERNET_IOP;
 
-public final class TransportInfo_impl extends org.omg.CORBA.LocalObject
-        implements TransportInfo {
-    private org.apache.yoko.orb.OCI.ConnectorInfo connectorInfo_; // connector
-                                                                    // info
+public final class TransportInfo_impl extends LocalObject implements TransportInfo {
+    private enum Origin{CLIENT(CLIENT_SIDE.value), SERVER(SERVER_SIDE.value); final short value; Origin(int v) {value = (short)v;}}
+    private final Socket socket;
+    private final Origin origin;
+    private final ListenerMap listenMap_;
+    private volatile ListenPoint[] listenPoints_ = null;
 
-    private org.apache.yoko.orb.OCI.AcceptorInfo acceptorInfo_; // acceptor info
-
-    private Transport_impl transport_; // associated transport
-
-    private org.omg.IIOP.ListenPoint[] listenPoints_ = null;
-
-    private ListenerMap listenMap_;
-
-    //
-    // All close callback objects
-    //
-    private java.util.Vector closeCBVec_ = new java.util.Vector();
 
     // ------------------------------------------------------------------
     // Standard IDL to Java Mapping
@@ -49,14 +54,11 @@
     }
 
     public int tag() {
-        return org.omg.IOP.TAG_INTERNET_IOP.value;
+        return TAG_INTERNET_IOP.value;
     }
 
     public short origin() {
-        if (acceptorInfo_ == null)
-            return org.apache.yoko.orb.OCI.CLIENT_SIDE.value;
-        else
-            return org.apache.yoko.orb.OCI.SERVER_SIDE.value;
+        return origin.value;
     }
 
     public synchronized String describe() {
@@ -79,94 +81,32 @@
         return desc;
     }
 
-    public synchronized org.apache.yoko.orb.OCI.ConnectorInfo connector_info() {
-        return connectorInfo_;
-    }
+    public Socket getSocket() {return socket;}
 
-    public synchronized org.apache.yoko.orb.OCI.AcceptorInfo acceptor_info() {
-        return acceptorInfo_;
-    }
+    public String addr() {return socket.getLocalAddress().getHostAddress();}
 
-    public synchronized void add_close_cb(org.apache.yoko.orb.OCI.CloseCB cb) {
-        int length = closeCBVec_.size();
-        for (int i = 0; i < length; i++)
-            if (closeCBVec_.elementAt(i) == cb)
-                return; // Already registered
-        closeCBVec_.addElement(cb);
-    }
+    public short port() {return (short)socket.getLocalPort();}
 
-    public synchronized void remove_close_cb(org.apache.yoko.orb.OCI.CloseCB cb) {
-        int length = closeCBVec_.size();
-        for (int i = 0; i < length; i++)
-            if (closeCBVec_.elementAt(i) == cb) {
-                closeCBVec_.removeElementAt(i);
-                return;
-            }
-    }
+    public String remote_addr() {return socket.getInetAddress().getHostAddress();}
 
-    public synchronized java.net.Socket socket() {
-        if (transport_ == null)
-            throw new org.omg.CORBA.NO_RESOURCES();
+    public short remote_port() {return (short)socket.getPort();}
 
-        return transport_.socket_;
-    }
-
-
-    public synchronized String addr() {
-        if (transport_ == null)
-            throw new org.omg.CORBA.NO_RESOURCES();
-
-        return transport_.socket_.getLocalAddress().getHostAddress();
-    }
-
-    public synchronized short port() {
-        if (transport_ == null)
-            throw new org.omg.CORBA.NO_RESOURCES();
-
-        int port = transport_.socket_.getLocalPort();
-
-        if (port >= 0x8000)
-            return (short) (port - 0xffff - 1);
-        else
-            return (short) port;
-    }
-
-    public synchronized String remote_addr() {
-        if (transport_ == null)
-            throw new org.omg.CORBA.NO_RESOURCES();
-
-        return transport_.socket_.getInetAddress().getHostAddress();
-    }
-
-    public synchronized short remote_port() {
-        if (transport_ == null)
-            throw new org.omg.CORBA.NO_RESOURCES();
-
-        int port = transport_.socket_.getPort();
-
-        if (port >= 0x8000)
-            return (short) (port - 0xffff - 1);
-        else
-            return (short) port;
-    }
-
-    public org.omg.IOP.ServiceContext[] get_service_contexts(
-            org.omg.CORBA.Policy[] policies) {
-        org.omg.IOP.ServiceContext[] scl;
+    public ServiceContext[] get_service_contexts(Policy[] policies) {
+        ServiceContext[] scl;
         boolean bHaveBidir = false;
 
-        for (int i = 0; i < policies.length; i++) {
-            if (policies[i].policy_type() == org.omg.BiDirPolicy.BIDIRECTIONAL_POLICY_TYPE.value) {
-                org.omg.BiDirPolicy.BidirectionalPolicy p = org.omg.BiDirPolicy.BidirectionalPolicyHelper
-                        .narrow(policies[i]);
-                if (p.value() == org.omg.BiDirPolicy.BOTH.value)
+        for (Policy policy : policies) {
+            if (policy.policy_type() == BIDIRECTIONAL_POLICY_TYPE.value) {
+                BidirectionalPolicy p = BidirectionalPolicyHelper
+                        .narrow(policy);
+                if (p.value() == BOTH.value)
                     bHaveBidir = true;
                 break;
             }
         }
 
         if (bHaveBidir) {
-            org.omg.IIOP.BiDirIIOPServiceContext biDirCtxt = new org.omg.IIOP.BiDirIIOPServiceContext();
+            BiDirIIOPServiceContext biDirCtxt = new BiDirIIOPServiceContext();
             biDirCtxt.listen_points = listenMap_.getListenPoints();
 
             org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
@@ -200,22 +140,19 @@
     }
 
     public void handle_service_contexts(org.omg.IOP.ServiceContext[] contexts) {
-        for (int i = 0; i < contexts.length; i++) {
-            if (contexts[i].context_id == org.omg.IOP.BI_DIR_IIOP.value) {
-                byte[] pOct = contexts[i].context_data;
-                int len = contexts[i].context_data.length;
+        for (ServiceContext context : contexts) {
+            if (context.context_id == BI_DIR_IIOP.value) {
+                byte[] pOct = context.context_data;
+                int len = context.context_data.length;
 
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
-                        pOct, len);
-                org.apache.yoko.orb.CORBA.InputStream in = new org.apache.yoko.orb.CORBA.InputStream(
-                        buf, 0, false);
+                Buffer buf = new Buffer(pOct, len);
+                InputStream in = new InputStream(buf, 0, false);
                 in._OB_readEndian();
 
                 //
                 // unmarshal the octets back to the bidir format
                 //
-                org.omg.IIOP.BiDirIIOPServiceContext biDirCtxt = org.omg.IIOP.BiDirIIOPServiceContextHelper
-                        .read(in);
+                BiDirIIOPServiceContext biDirCtxt = BiDirIIOPServiceContextHelper.read(in);
 
                 //
                 // save the listening points in the transport
@@ -228,14 +165,10 @@
     }
 
     public synchronized boolean received_bidir_SCL() {
-        if (listenPoints_ == null)
-            return false;
-
-        return (listenPoints_.length > 0);
+        return listenPoints_ != null && (listenPoints_.length > 0);
     }
 
-    public synchronized boolean endpoint_alias_match(
-            org.apache.yoko.orb.OCI.ConnectorInfo connInfo) {
+    public synchronized boolean endpoint_alias_match(org.apache.yoko.orb.OCI.ConnectorInfo connInfo) {
         //
         // we only deal with Connectors that are of our specific type,
         // namely IIOP connectors (and ConnectorInfos)
@@ -257,10 +190,10 @@
         short port = infoImpl.remote_port();
         String host = infoImpl.remote_addr();
 
-        for (int i = 0; i < listenPoints_.length; i++) {
-            if ((listenPoints_[i].port == port)
-                    && org.apache.yoko.orb.OB.Net.CompareHosts(
-                            listenPoints_[i].host, host))
+        for (ListenPoint aListenPoints_ : listenPoints_) {
+            if ((aListenPoints_.port == port)
+                    && Net.CompareHosts(
+                    aListenPoints_.host, host))
                 return true;
         }
 
@@ -279,31 +212,20 @@
     // Yoko internal functions
     // Application programs must not use these functions directly
     // ------------------------------------------------------------------
-
-    TransportInfo_impl(Transport_impl transport,
-            org.apache.yoko.orb.OCI.Connector connector, ListenerMap lm) {
-        transport_ = transport;
-        connectorInfo_ = connector.get_info();
+    private TransportInfo_impl(Socket socket, Origin origin, ListenerMap lm) {
+        this.socket = socket;
+        this.origin = origin;
         listenMap_ = lm;
     }
 
-    TransportInfo_impl(Transport_impl transport,
-            org.apache.yoko.orb.OCI.Acceptor acceptor, ListenerMap lm) {
-        transport_ = transport;
-        acceptorInfo_ = acceptor.get_info();
-        listenMap_ = lm;
+
+    // client-side constructor
+    TransportInfo_impl(Transport_impl transport, ListenerMap lm) {
+        this(transport.socket_, Origin.CLIENT, lm);
     }
 
-    synchronized void _OB_callCloseCB(org.apache.yoko.orb.OCI.TransportInfo info) {
-        int length = closeCBVec_.size();
-        for (int i = 0; i < length; i++) {
-            org.apache.yoko.orb.OCI.CloseCB cb = (org.apache.yoko.orb.OCI.CloseCB) closeCBVec_
-                    .elementAt(i);
-            cb.close_cb(info);
-        }
-    }
-
-    synchronized void _OB_destroy() {
-        transport_ = null;
+    //server-side constructor
+    TransportInfo_impl(Transport_impl transport, Acceptor acceptor, ListenerMap lm) {
+        this(transport.socket_, Origin.SERVER, lm);
     }
 }
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Transport_impl.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Transport_impl.java
index d9dda5b..e986502 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Transport_impl.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Transport_impl.java
@@ -17,22 +17,35 @@
 
 package org.apache.yoko.orb.OCI.IIOP;
 
+import static org.apache.yoko.orb.OCI.IIOP.Exceptions.*;
+import static org.apache.yoko.orb.OB.MinorCodes.*;
+
+import org.apache.yoko.orb.OB.MinorCodes;
+import org.apache.yoko.orb.OCI.Acceptor;
+import org.apache.yoko.orb.OCI.SendReceiveMode;
+import org.omg.CORBA.COMM_FAILURE;
+import org.omg.CORBA.CompletionStatus;
+import org.omg.CORBA.NO_IMPLEMENT;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.net.Socket;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.apache.yoko.orb.OCI.IIOP.PLUGIN_ID;
+import static org.apache.yoko.orb.OCI.SendReceiveMode.*;
 
 final public class Transport_impl extends org.omg.CORBA.LocalObject implements
         org.apache.yoko.orb.OCI.Transport {
     // This data member must not be private because the info object
     // must be able to access it
-    public java.net.Socket socket_; // The socket
+    public final java.net.Socket socket_; // The socket
 
     private java.io.InputStream in_; // The socket's input stream
 
     private java.io.OutputStream out_; // The socket's output stream
 
-    private boolean shutdown_; // True if shutdown() was called
+    private volatile boolean shutdown_; // True if shutdown() was called
 
     private int soTimeout_ = 0; // The value for setSoTimeout()
 
@@ -54,7 +67,7 @@
             } catch (java.net.SocketException ex) {
                 logger.log(Level.FINE, "Socket setup error", ex); 
                 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
+                throw (COMM_FAILURE)new COMM_FAILURE(
                         org.apache.yoko.orb.OB.MinorCodes
                                 .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetSoTimeout)
                                 + ": socket error during setSoTimeout: "
@@ -63,7 +76,7 @@
                         org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
             } catch (java.lang.NullPointerException ex) {
                 logger.log(Level.FINE, "Socket setup error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
+                throw (COMM_FAILURE)new COMM_FAILURE(
                         org.apache.yoko.orb.OB.MinorCodes
                                 .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSetSoTimeout)
                                 + ": NullPointerException error during setSoTimeout: "
@@ -86,41 +99,27 @@
     // shutdown the receiving side. If how == 1, shutdown the sending
     // side. If how == 2, shutdown both.
     //
-    private static void shutdownSocket(java.net.Socket socket, int how) {
-        if (socket == null) // Socket already closed
-            return;
-
-        if (how == 2) {
-            shutdownSocket(socket, 0);
-            shutdownSocket(socket, 1);
-            return;
-        }
-
+    private void shutdownSocket() {
         try {
-            if (how == 0) {
                 try {
-                    socket.shutdownInput();
+                    socket_.shutdownInput();
                 } catch (UnsupportedOperationException e) {
                 // if we're using an SSL connection, this is an unsupported operation.
                 // just ignore the error and proceed to the close.
                 }
-            } else if (how == 1) {
                 try {
-                    socket.shutdownOutput();
+                    socket_.shutdownOutput();
                 } catch (UnsupportedOperationException e) {
                 // if we're using an SSL connection, this is an unsupported operation.
                 // just ignore the error and proceed to the close.
                 }
-            } else {
-                throw new InternalError();
-            }
         } catch (java.net.SocketException ex) {
             //
             // Some VMs (namely JRockit) raise a SocketException if
             // the socket has already been closed.
             // This exception can be ignored.
             //
-        } catch (java.io.IOException ex) {
+        } catch (IOException ex) {
             logger.log(Level.FINE, "Socket shutdown error", ex); 
             throw (InternalError)new InternalError().initCause(ex);
         }
@@ -138,28 +137,15 @@
         return org.omg.IOP.TAG_INTERNET_IOP.value;
     }
 
-    public org.apache.yoko.orb.OCI.SendReceiveMode mode() {
-        return org.apache.yoko.orb.OCI.SendReceiveMode.SendReceive;
+    public SendReceiveMode mode() {
+        return SendReceive;
     }
 
     public int handle() {
-        throw new org.omg.CORBA.NO_IMPLEMENT();
+        throw new NO_IMPLEMENT();
     }
 
     public void close() {
-        if (socket_ == null) // shutdown() may call close()
-            return;
-
-        //
-        // Call callbacks
-        //
-        info_._OB_callCloseCB(info_);
-
-        //
-        // Destroy the info object
-        //
-        info_._OB_destroy();
-
         //
         // I must set socket_ to null *before* the close or the code
         // below, to avoid a race condition with send/receive
@@ -168,24 +154,22 @@
         //
         // Close the socket
         //
-        java.net.Socket saveSocket = socket_;
-        socket_ = null; // Must be set to null before the shutdown/close
-        shutdownSocket(saveSocket, 2); // This helps to unblock threads
+        shutdownSocket(); // This helps to unblock threads
         // blocking in recv()
         try {
-            saveSocket.close();
-        } catch (java.io.IOException ex) {
+            socket_.close();
+        } catch (IOException ex) {
         }
     }
 
     public void shutdown() {
-        shutdownSocket(socket_, 2); // Shutdown send side only
-        if (socket_ != null) {
-            // blocking in recv()
-            try {
-                socket_.close();
-            } catch (java.io.IOException ex) {
-            }
+        logger.info("shutdown: " + this); 
+        shutdown_ = true;
+        shutdownSocket(); // Shutdown send side only
+        // blocking in recv()
+        try {
+            socket_.close();
+        } catch (IOException ex) {
         }
     }
 
@@ -197,39 +181,28 @@
             try {
                 int result = in_.read(buf.data(), buf.pos(), buf.rest_length());
                 if (result <= 0) {
-                    throw new org.omg.CORBA.COMM_FAILURE(
-                            org.apache.yoko.orb.OB.MinorCodes
-                                    .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorRecvZero),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorRecvZero,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new COMM_FAILURE(describeCommFailure(MinorRecvZero), MinorRecvZero, CompletionStatus.COMPLETED_NO);
                 }
                 buf.advance(result);
-            } catch (java.io.InterruptedIOException ex) {
+            } catch (InterruptedIOException ex) {
                 logger.log(Level.FINE, "Received interrupted exception", ex); 
                 buf.advance(ex.bytesTransferred);
 
                 if (!block)
                     return;
+                if (shutdown_)
+                    throw asCommFailure(ex, MinorCodes.MinorRecv, "Interrupted I/O exception during shutdown");
             } catch (java.io.IOException ex) {
                 logger.log(Level.FINE, "Socket read error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorRecv)
-                                + ": I/O error during read: " + ex.getMessage(), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorRecv,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); 
+                throw asCommFailure(ex, MinorCodes.MinorRecv, "I/O error during read");
             } catch (java.lang.NullPointerException ex) {
-                logger.log(Level.FINE, "Socket read error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorRecv)
-                                + ": NullPointerException during read",
-                        org.apache.yoko.orb.OB.MinorCodes.MinorRecv,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+                logger.log(Level.FINE, "Socket read error", ex);
+                throw asCommFailure(ex, MinorCodes.MinorRecv, "NullPointerException during read");
             }
         }
     }
 
+
     public boolean receive_detect(org.apache.yoko.orb.OCI.Buffer buf,
             boolean block) {
         setBlock(block);
@@ -270,11 +243,7 @@
             try {
                 int result = in_.read(buf.data(), buf.pos(), buf.rest_length());
                 if (result <= 0) {
-                    throw new org.omg.CORBA.COMM_FAILURE(
-                            org.apache.yoko.orb.OB.MinorCodes
-                                    .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorRecvZero),
-                            org.apache.yoko.orb.OB.MinorCodes.MinorRecvZero,
-                            org.omg.CORBA.CompletionStatus.COMPLETED_NO);
+                    throw new COMM_FAILURE(describeCommFailure(MinorRecvZero), MinorRecvZero, CompletionStatus.COMPLETED_NO);
                 }
                 buf.advance(result);
             } catch (java.io.InterruptedIOException ex) {
@@ -282,20 +251,10 @@
                 return;
             } catch (java.io.IOException ex) {
                 logger.log(Level.FINE, "Socket read error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorRecv)
-                                + ": I/O error during read: " + ex.getMessage(), 
-                        org.apache.yoko.orb.OB.MinorCodes.MinorRecv,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); 
+                throw asCommFailure(ex, MinorRecv, "I/O error during read");
             } catch (java.lang.NullPointerException ex) {
                 logger.log(Level.FINE, "Socket read error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorRecv)
-                                + ": NullPointerException during read",
-                        org.apache.yoko.orb.OB.MinorCodes.MinorRecv,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex); 
+                throw asCommFailure(ex, MinorRecv, "NullPointerException during read");
             }
         }
     }
@@ -345,21 +304,11 @@
                 if (!block)
                     return;
             } catch (java.io.IOException ex) {
-                logger.log(Level.FINE, "Socket write error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSend)
-                                + ": I/O error during write: " + ex.getMessage(),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorSend,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+                logger.log(Level.FINE, "Socket write error", ex);
+                throw asCommFailure(ex, MinorSend, "I/O error during write");
             } catch (java.lang.NullPointerException ex) {
-                logger.log(Level.FINE, "Socket write error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSend)
-                                + ": NullPointerException during write",
-                        org.apache.yoko.orb.OB.MinorCodes.MinorSend,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+                logger.log(Level.FINE, "Socket write error", ex);
+                throw asCommFailure(ex, MinorSend, "NullPointerException during write");
             }
         }
     }
@@ -407,21 +356,11 @@
                 buf.advance(ex.bytesTransferred);
                 return;
             } catch (java.io.IOException ex) {
-                logger.log(Level.FINE,  "Socket write error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSend)
-                                + ": I/O error during write: " + ex.getMessage(),
-                        org.apache.yoko.orb.OB.MinorCodes.MinorSend,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+                logger.log(Level.FINE,  "Socket write error", ex);
+                throw asCommFailure(ex, MinorSend, "I/O error during write");
             } catch (java.lang.NullPointerException ex) {
-                logger.log(Level.FINE, "Socket write error", ex); 
-                throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                        org.apache.yoko.orb.OB.MinorCodes
-                                .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSend)
-                                + ": NullPointerException during write",
-                        org.apache.yoko.orb.OB.MinorCodes.MinorSend,
-                        org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+                logger.log(Level.FINE, "Socket write error", ex);
+                throw asCommFailure(ex, MinorSend, "NullPointerException during write");
             }
         }
     }
@@ -462,8 +401,7 @@
     // Application programs must not use these functions directly
     // ------------------------------------------------------------------
 
-    public Transport_impl(org.apache.yoko.orb.OCI.Connector connector,
-            java.net.Socket socket, ListenerMap lm) {
+    public Transport_impl(java.net.Socket socket, ListenerMap lm) {
         socket_ = socket;
         shutdown_ = false;
 
@@ -475,25 +413,18 @@
             in_ = socket_.getInputStream();
             out_ = socket_.getOutputStream();
         } catch (java.io.IOException ex) {
-            logger.log(Level.FINE, "Socket setup error", ex); 
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
-                            + ": unable to obtain socket InputStream: "
-                            + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            logger.log(Level.FINE, "Socket setup error", ex);
+            throw asCommFailure(ex, MinorSocket, "unable to obtain socket InputStream");
         }
 
         //
         // Since the Constructor of TransportInfo uses this object create
         // it after all members are initialized
         //
-        info_ = new TransportInfo_impl(this, connector, lm);
+        info_ = new TransportInfo_impl(this, lm);
     }
 
-    public Transport_impl(org.apache.yoko.orb.OCI.Acceptor acceptor,
-            java.net.Socket socket, ListenerMap lm) {
+    public Transport_impl(Acceptor acceptor, Socket socket, ListenerMap lm) {
         socket_ = socket;
         shutdown_ = false;
         
@@ -507,14 +438,8 @@
             in_ = socket_.getInputStream();
             out_ = socket_.getOutputStream();
         } catch (java.io.IOException ex) {
-            logger.log(Level.FINE, "Socket setup error", ex); 
-            throw (org.omg.CORBA.COMM_FAILURE)new org.omg.CORBA.COMM_FAILURE(
-                    org.apache.yoko.orb.OB.MinorCodes
-                            .describeCommFailure(org.apache.yoko.orb.OB.MinorCodes.MinorSocket)
-                            + ": unable to obtain socket InputStream: "
-                            + ex.getMessage(),
-                    org.apache.yoko.orb.OB.MinorCodes.MinorSocket,
-                    org.omg.CORBA.CompletionStatus.COMPLETED_NO).initCause(ex);
+            logger.log(Level.FINE, "Socket setup error", ex);
+            throw asCommFailure(ex, MinorSocket, "unable to obtain socket InputStream");
         }
 
         //
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Util.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Util.java
index 142bd55..3eb6804 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Util.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/IIOP/Util.java
@@ -19,18 +19,40 @@
 
 import org.apache.yoko.orb.CORBA.InputStream;
 import org.apache.yoko.orb.CORBA.OutputStream;
+import org.apache.yoko.orb.OCI.Buffer;
+import org.apache.yoko.orb.OCI.ProfileInfo;
+import org.apache.yoko.orb.OCI.ProfileInfoHolder;
+import org.apache.yoko.orb.OCI.ProfileInfoSeqHolder;
+import org.omg.CORBA.Any;
+import org.omg.CSIIOP.CompoundSecMech;
+import org.omg.CSIIOP.CompoundSecMechList;
+import org.omg.CSIIOP.CompoundSecMechListHelper;
+import org.omg.CSIIOP.TAG_CSI_SEC_MECH_LIST;
+import org.omg.CSIIOP.TAG_TLS_SEC_TRANS;
+import org.omg.CSIIOP.TLS_SEC_TRANS;
+import org.omg.CSIIOP.TLS_SEC_TRANSHelper;
+import org.omg.CSIIOP.TransportAddress;
+import org.omg.IIOP.ProfileBody_1_0;
+import org.omg.IIOP.ProfileBody_1_0Helper;
+import org.omg.IOP.*;
+import org.omg.IOP.CodecPackage.FormatMismatch;
+import org.omg.IOP.CodecPackage.TypeMismatch;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 final public class Util {
-    static public org.omg.IOP.IOR createIOR(String host, int port, String id,
-            org.apache.yoko.orb.OCI.ProfileInfo profileInfo) {
-        org.omg.IOP.IOR ior = new org.omg.IOP.IOR();
+    static public IOR createIOR(String host, int port, String id, ProfileInfo profileInfo) {
+        IOR ior = new IOR();
         ior.type_id = id;
         ior.profiles = new org.omg.IOP.TaggedProfile[1];
         ior.profiles[0] = new org.omg.IOP.TaggedProfile();
-        ior.profiles[0].tag = org.omg.IOP.TAG_INTERNET_IOP.value;
+        ior.profiles[0].tag = TAG_INTERNET_IOP.value;
 
         if (profileInfo.major == 1 && profileInfo.minor == 0) {
-            org.omg.IIOP.ProfileBody_1_0 body = new org.omg.IIOP.ProfileBody_1_0();
+            ProfileBody_1_0 body = new ProfileBody_1_0();
             body.iiop_version = new org.omg.IIOP.Version((byte) 1, (byte) 0);
             body.host = host;
             if (port >= 0x8000)
@@ -38,10 +60,10 @@
             else
                 body.port = (short) port;
             body.object_key = profileInfo.key;
-            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
+            Buffer buf = new Buffer();
             OutputStream out = new OutputStream(buf);
             out._OB_writeEndian();
-            org.omg.IIOP.ProfileBody_1_0Helper.write(out, body);
+            ProfileBody_1_0Helper.write(out, body);
             ior.profiles[0].profile_data = new byte[buf.length()];
             System.arraycopy(buf.data(), 0, ior.profiles[0].profile_data, 0,
                     buf.length());
@@ -56,7 +78,7 @@
                 body.port = (short) port;
             body.object_key = profileInfo.key;
             body.components = profileInfo.components;
-            org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer();
+            Buffer buf = new Buffer();
             OutputStream out = new OutputStream(buf);
             out._OB_writeEndian();
             org.omg.IIOP.ProfileBody_1_1Helper.write(out, body);
@@ -68,40 +90,38 @@
         return ior;
     }
 
-    static public org.omg.IOP.IOR createIOR(org.omg.IOP.IOR ior, String id,
-            byte[] key) {
+    static public IOR createIOR(IOR ior, String id, byte[] key) {
         //
         // Extract the IIOP profile information from the provided IOR
         //
         int profile;
         for (profile = 0; profile < ior.profiles.length; profile++)
-            if (ior.profiles[profile].tag == org.omg.IOP.TAG_INTERNET_IOP.value)
+            if (ior.profiles[profile].tag == TAG_INTERNET_IOP.value)
                 break;
 
         // TODO: Internal error?
         org.apache.yoko.orb.OB.Assert._OB_assert(profile < ior.profiles.length);
 
-        org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
+        Buffer buf = new Buffer(
                 ior.profiles[profile].profile_data,
                 ior.profiles[profile].profile_data.length);
-        InputStream in = new InputStream(buf, 0, false, null, 0);
+        InputStream in = new InputStream(buf, 0, false, null, null);
         in._OB_readEndian();
-        org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
+        ProfileBody_1_0 body = ProfileBody_1_0Helper
                 .read(in);
 
-        org.apache.yoko.orb.OCI.ProfileInfo profileInfo = new org.apache.yoko.orb.OCI.ProfileInfo();
+        ProfileInfo profileInfo = new ProfileInfo();
         profileInfo.key = key;
         profileInfo.major = body.iiop_version.major;
         profileInfo.minor = body.iiop_version.minor;
-        profileInfo.components = new org.omg.IOP.TaggedComponent[0];
+        profileInfo.components = new TaggedComponent[0];
         return createIOR(body.host, body.port, id, profileInfo);
     }
 
-    static public boolean extractProfileInfo(org.omg.IOP.IOR ior,
-            org.apache.yoko.orb.OCI.ProfileInfoHolder profileInfo) {
-        org.apache.yoko.orb.OCI.ProfileInfoSeqHolder profileInfoSeq = new org.apache.yoko.orb.OCI.ProfileInfoSeqHolder();
-        profileInfoSeq.value = new org.apache.yoko.orb.OCI.ProfileInfo[0];
-        extractAllProfileInfos(ior, profileInfoSeq, false, null, 0, false);
+    static public boolean extractProfileInfo(IOR ior, ProfileInfoHolder profileInfo) {
+        ProfileInfoSeqHolder profileInfoSeq = new ProfileInfoSeqHolder();
+        profileInfoSeq.value = new ProfileInfo[0];
+        extractAllProfileInfos(ior, profileInfoSeq, false, null, 0, false, null);
         if (profileInfoSeq.value.length > 0) {
             profileInfo.value = profileInfoSeq.value[0];
             return true;
@@ -110,8 +130,7 @@
         return false;
     }
 
-    static public boolean hostMatch(String host1, String host2,
-            boolean loopbackMatches) {
+    static public boolean hostMatch(String host1, String host2, boolean matchLoopback) {
         //
         // Direct host name comparison
         //
@@ -122,11 +141,9 @@
             // addresses to be really sure if the hosts differ
             //
             try {
-                java.net.InetAddress addr1 = java.net.InetAddress
-                        .getByName(host1);
+                InetAddress addr1 = InetAddress.getByName(host1);
 
-                java.net.InetAddress addr2 = java.net.InetAddress
-                        .getByName(host2);
+                InetAddress addr2 = InetAddress.getByName(host2);
 
                 if (!addr1.equals(addr2)) {
                     //
@@ -134,9 +151,8 @@
                     // the key if the profile body contains the
                     // loopback address?
                     //
-                    if (loopbackMatches) {
-                        java.net.InetAddress loopback = java.net.InetAddress
-                                .getByName("127.0.0.1");
+                    if (matchLoopback) {
+                        InetAddress loopback = InetAddress.getByName("127.0.0.1");
 
                         if (!addr2.equals(loopback))
                             return false;
@@ -154,86 +170,44 @@
         return true;
     }
 
-    static public void extractAllProfileInfos(org.omg.IOP.IOR ior,
-            org.apache.yoko.orb.OCI.ProfileInfoSeqHolder profileInfoSeq,
-            boolean performMatch, String host, int port, boolean loopbackMatches) {
-        short portNo;
-        if (port >= 0x8000) {
-            portNo = (short) (port - 0xffff - 1);
-        }
-        else {
-            portNo = (short) port;
-        }
+    static public void extractAllProfileInfos(IOR ior, ProfileInfoSeqHolder profileInfoSeq,
+            boolean performMatch, String host, int port, boolean matchLoopback, Codec codec) {
+        short portNo = (short) port;
 
-        java.util.Vector vec = new java.util.Vector();
+        List<ProfileInfo> list = new ArrayList<>();
+
         for (int i = 0; i < ior.profiles.length; i++) {
-            if (ior.profiles[i].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
-                //
-                // Get the IIOP profile body
-                //
-                byte[] data = ior.profiles[i].profile_data;
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
-                        data, data.length);
-                InputStream in = new InputStream(buf, 0, false, null, 0);
-                in._OB_readEndian();
-                org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
-                        .read(in);
+            if (ior.profiles[i].tag != TAG_INTERNET_IOP.value) continue;
+            //
+            // Get the IIOP profile body
+            //
+            byte[] data = ior.profiles[i].profile_data;
+            Buffer buf = new Buffer(data, data.length);
+            InputStream in = new InputStream(buf, 0, false, null, null);
+            in._OB_readEndian();
+            ProfileBody_1_0 body = ProfileBody_1_0Helper.read(in);
 
-                //
-                // Read components if the IIOP version is > 1.0
-                //
-                org.omg.IOP.TaggedComponent[] components;
-                if (body.iiop_version.major > 1 || body.iiop_version.minor > 0) {
-                    int len = in.read_ulong();
-                    components = new org.omg.IOP.TaggedComponent[len];
-                    for (int j = 0; j < len; j++) {
-                        components[j] = org.omg.IOP.TaggedComponentHelper.read(in);
-                    }
-                } else {
-                    components = new org.omg.IOP.TaggedComponent[0];
+            //
+            // Read components if the IIOP version is > 1.0
+            //
+            TaggedComponent[] components;
+            if (body.iiop_version.major > 1 || body.iiop_version.minor > 0) {
+                int len = in.read_ulong();
+                components = new TaggedComponent[len];
+                for (int j = 0; j < len; j++) {
+                    components[j] = TaggedComponentHelper.read(in);
                 }
+            } else {
+                components = new TaggedComponent[0];
+            }
 
-                if (performMatch) {
-                    //
-                    // Check primary host/port
-                    //
-                    boolean match = false;
-                    if (portNo == body.port
-                            && hostMatch(host, body.host, loopbackMatches)) {
-                        match = true;
-                    }
-
-                    //
-                    // Check alternate host/port
-                    //
-                    if (!match) {
-                        for (int j = 0; j < components.length && !match; j++) {
-                            if (components[j].tag == org.omg.IOP.TAG_ALTERNATE_IIOP_ADDRESS.value) {
-                                byte[] d = components[j].component_data;
-                                org.apache.yoko.orb.OCI.Buffer b = new org.apache.yoko.orb.OCI.Buffer(
-                                        d, d.length);
-                                InputStream s = new InputStream(b, 0, false,
-                                        null, 0);
-                                s._OB_readEndian();
-                                String altHost = s.read_string();
-                                short altPort = s.read_ushort();
-                                if (portNo == altPort
-                                        && hostMatch(host, altHost,
-                                                loopbackMatches)) {
-                                    match = true;
-                                }
-                            }
-                        }
-                    }
-
-                    if (!match)
-                        continue;
-                }
-
-                //
-                // OK, found a match
-                //
-                org.apache.yoko.orb.OCI.ProfileInfo profileInfo = new org.apache.yoko.orb.OCI.ProfileInfo();
+            // add this profile to the list unless
+            // A) the caller requested matching
+            // B) the profile doesn't match the supplied host and port
+            if (!!!performMatch
+                    || hostAndPortMatch(host, portNo, body.host, body.port, matchLoopback)
+                    || taggedComponentsMatch(components, host, portNo, codec, matchLoopback)) {
+                ProfileInfo profileInfo = new ProfileInfo();
                 profileInfo.key = body.object_key;
                 profileInfo.minor = body.iiop_version.minor;
                 profileInfo.major = body.iiop_version.major;
@@ -241,46 +215,84 @@
                 profileInfo.index = i;
                 profileInfo.components = components;
 
-                vec.addElement(profileInfo);
+                list.add(profileInfo);
             }
         }
 
-        if (vec.size() > 0) {
-            int len = profileInfoSeq.value.length;
-            if (len == 0) {
-                profileInfoSeq.value = new org.apache.yoko.orb.OCI.ProfileInfo[vec
-                        .size()];
-                vec.copyInto(profileInfoSeq.value);
-            } else {
-                org.apache.yoko.orb.OCI.ProfileInfo[] arr = new org.apache.yoko.orb.OCI.ProfileInfo[len
-                        + vec.size()];
-                System.arraycopy(profileInfoSeq.value, 0, arr, 0, len);
-                for (int i = 0; i < vec.size(); i++) {
-                    arr[len + i] = (org.apache.yoko.orb.OCI.ProfileInfo) vec.elementAt(i);
-                }
-                profileInfoSeq.value = arr;
-            }
+        if (!!!list.isEmpty()) {
+            List<ProfileInfo> bigList = new ArrayList<>(Arrays.asList(profileInfoSeq.value));
+            bigList.addAll(list);
+            profileInfoSeq.value = bigList.toArray(profileInfoSeq.value);
         }
     }
 
-    static public boolean equivalent(org.omg.IOP.IOR ior1, org.omg.IOP.IOR ior2) {
+    private static boolean hostAndPortMatch(String host, short portNo, String bodyHost, short bodyPort, boolean matchLoopback) {
+        return portNo == bodyPort && hostMatch(host, bodyHost, matchLoopback);
+    }
+
+    private static boolean taggedComponentsMatch(TaggedComponent[] components, String host, short port, Codec codec, boolean matchLoopback) {
+        for (final TaggedComponent component : components) {
+            if (component.tag == TAG_ALTERNATE_IIOP_ADDRESS.value) {
+                byte[] d = component.component_data;
+                Buffer b = new Buffer(d, d.length);
+                InputStream s = new InputStream(b, 0, false, null, null);
+                s._OB_readEndian();
+                String altHost = s.read_string();
+                short altPort = s.read_ushort();
+                if (hostAndPortMatch(host, port, altHost, altPort, matchLoopback)) {
+                    return true;
+                }
+            } else if (component.tag == TAG_CSI_SEC_MECH_LIST.value) {
+                Any any;
+                try {
+                    any = codec.decode_value(component.component_data, CompoundSecMechListHelper.type());
+                    CompoundSecMechList csml = CompoundSecMechListHelper.extract(any);
+
+                    for (CompoundSecMech csm : csml.mechanism_list) {
+                        TaggedComponent tc = csm.transport_mech;
+                        if (tc.tag == TAG_TLS_SEC_TRANS.value) {
+                            Any tstAny = codec.decode_value(tc.component_data, TLS_SEC_TRANSHelper.type());
+                            TLS_SEC_TRANS tst = TLS_SEC_TRANSHelper.extract(tstAny);
+                            TransportAddress[] transportAddresses = tst.addresses;
+                            if (transportAddressesMatch(transportAddresses, host, port, matchLoopback))
+                                return true;
+                        }
+                    }
+                } catch (FormatMismatch | TypeMismatch ignored) {
+                }
+            }
+        }
+        return false;
+    }
+
+    private static boolean transportAddressesMatch(TransportAddress[] addrs, String host, short port, boolean loopbackMatches) {
+        for (TransportAddress addr: addrs) {
+            final short addrPort = addr.port;
+            if (hostAndPortMatch(host, port, addr.host_name, addrPort, loopbackMatches)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    static public boolean equivalent(IOR ior1, IOR ior2) {
         int p1, p2, b1, b2;
         int cnt1 = 0, cnt2 = 0;
-        org.omg.IIOP.ProfileBody_1_0[] bodies1;
-        org.omg.IIOP.ProfileBody_1_0[] bodies2;
+        ProfileBody_1_0[] bodies1;
+        ProfileBody_1_0[] bodies2;
 
         //
         // Calculate number of IIOP profiles in ior1
         //
         for (p1 = 0; p1 < ior1.profiles.length; p1++)
-            if (ior1.profiles[p1].tag == org.omg.IOP.TAG_INTERNET_IOP.value)
+            if (ior1.profiles[p1].tag == TAG_INTERNET_IOP.value)
                 cnt1++;
 
         //
         // Calculate number of IIOP profiles in ior2
         //
         for (p2 = 0; p2 < ior2.profiles.length; p2++)
-            if (ior2.profiles[p2].tag == org.omg.IOP.TAG_INTERNET_IOP.value)
+            if (ior2.profiles[p2].tag == TAG_INTERNET_IOP.value)
                 cnt2++;
 
         //
@@ -293,15 +305,15 @@
         //
         // Create an array with all IIOP profile bodies of ior1
         //
-        bodies1 = new org.omg.IIOP.ProfileBody_1_0[cnt1];
+        bodies1 = new ProfileBody_1_0[cnt1];
         for (p1 = 0, b1 = 0; p1 < ior1.profiles.length; p1++)
-            if (ior1.profiles[p1].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
+            if (ior1.profiles[p1].tag == TAG_INTERNET_IOP.value) {
                 byte[] data = ior1.profiles[p1].profile_data;
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
+                Buffer buf = new Buffer(
                         data, data.length);
-                InputStream in = new InputStream(buf, 0, false, null, 0);
+                InputStream in = new InputStream(buf, 0, false, null, null);
                 in._OB_readEndian();
-                bodies1[b1++] = org.omg.IIOP.ProfileBody_1_0Helper.read(in);
+                bodies1[b1++] = ProfileBody_1_0Helper.read(in);
             }
 
         if (b1 != cnt1)
@@ -310,15 +322,15 @@
         //
         // Create an array with all IIOP profile bodies of ior2
         //
-        bodies2 = new org.omg.IIOP.ProfileBody_1_0[cnt2];
+        bodies2 = new ProfileBody_1_0[cnt2];
         for (p2 = 0, b2 = 0; p2 < ior2.profiles.length; p2++)
-            if (ior2.profiles[p2].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
+            if (ior2.profiles[p2].tag == TAG_INTERNET_IOP.value) {
                 byte[] data = ior2.profiles[p2].profile_data;
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
+                Buffer buf = new Buffer(
                         data, data.length);
-                InputStream in = new InputStream(buf, 0, false, null, 0);
+                InputStream in = new InputStream(buf, 0, false, null, null);
                 in._OB_readEndian();
-                bodies2[b2++] = org.omg.IIOP.ProfileBody_1_0Helper.read(in);
+                bodies2[b2++] = ProfileBody_1_0Helper.read(in);
             }
 
         if (b2 != cnt2)
@@ -360,8 +372,8 @@
         return true;
     }
 
-    static boolean compareBodies(org.omg.IIOP.ProfileBody_1_0 body1,
-            org.omg.IIOP.ProfileBody_1_0 body2) {
+    static boolean compareBodies(ProfileBody_1_0 body1,
+            ProfileBody_1_0 body2) {
         //
         // Compare versions
         //
@@ -395,10 +407,10 @@
             // addresses to be really sure if the hosts differ
             //
             try {
-                java.net.InetAddress addr1 = java.net.InetAddress
+                InetAddress addr1 = InetAddress
                         .getByName(body1.host);
 
-                java.net.InetAddress addr2 = java.net.InetAddress
+                InetAddress addr2 = InetAddress
                         .getByName(body2.host);
 
                 if (!addr1.equals(addr2))
@@ -420,33 +432,30 @@
     //
     // Calculate a hash for an IOR containing IIOP profiles
     //
-    static public int hash(org.omg.IOP.IOR ior, int maximum) {
+    static public int hash(IOR ior, int maximum) {
         int hash = 0;
 
-        for (int i = 0; i < ior.profiles.length; i++) {
-            if (ior.profiles[i].tag == org.omg.IOP.TAG_INTERNET_IOP.value) {
-                //
-                // Get the first IIOP profile body
-                //
-                byte[] data = ior.profiles[i].profile_data;
-                org.apache.yoko.orb.OCI.Buffer buf = new org.apache.yoko.orb.OCI.Buffer(
-                        data, data.length);
-                InputStream in = new InputStream(buf, 0, false, null, 0);
-                in._OB_readEndian();
-                org.omg.IIOP.ProfileBody_1_0 body = org.omg.IIOP.ProfileBody_1_0Helper
-                        .read(in);
+        for (TaggedProfile profile : ior.profiles) {
+            if (profile.tag == TAG_INTERNET_IOP.value) continue;
+            //
+            // Get the first IIOP profile body
+            //
+            byte[] data = profile.profile_data;
+            Buffer buf = new Buffer(data, data.length);
+            InputStream in = new InputStream(buf, 0, false, null, null);
+            in._OB_readEndian();
+            ProfileBody_1_0 body = ProfileBody_1_0Helper.read(in);
 
-                //
-                // Add port to hash
-                //
-                hash ^= body.port;
+            //
+            // Add port to hash
+            //
+            hash ^= body.port;
 
-                //
-                // Add object key to hash
-                //
-                for (int j = 0; j + 1 < body.object_key.length; j += 2)
-                    hash ^= body.object_key[j + 1] * 256 + body.object_key[j];
-            }
+            //
+            // Add object key to hash
+            //
+            for (int j = 0; j + 1 < body.object_key.length; j += 2)
+                hash ^= body.object_key[j + 1] * 256 + body.object_key[j];
         }
 
         return hash % (maximum + 1);
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/TransportInfoOperations.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/TransportInfoOperations.java
index c2f423a..5f26fda 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/TransportInfoOperations.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/TransportInfoOperations.java
@@ -53,32 +53,10 @@
     //
     // IDL:orb.yoko.apache.org/OCI/TransportInfo/connector_info:1.0
     //
-    /**
-     *
-     * The ConnectorInfo object for the Connector that created the
-     * Transport object that this TransportInfo object belongs to.
-     * If the Transport for this TransportInfo was not created by a
-     * Connector, this attribute is set to the nil object reference.
-     *
-     **/
-
-    ConnectorInfo
-    connector_info();
 
     //
     // IDL:orb.yoko.apache.org/OCI/TransportInfo/acceptor_info:1.0
     //
-    /**
-     *
-     * The AcceptorInfo object for the Acceptor that created the
-     * Transport object that this TransportInfo object belongs to.
-     * If the Transport for this TransportInfo was not created by an
-     * Acceptor, this attribute is set to the nil object reference.
-     *
-     **/
-
-    AcceptorInfo
-    acceptor_info();
 
     //
     // IDL:orb.yoko.apache.org/OCI/TransportInfo/origin:1.0
@@ -118,33 +96,10 @@
     //
     // IDL:orb.yoko.apache.org/OCI/TransportInfo/add_close_cb:1.0
     //
-    /**
-     *
-     * Add a callback that is called before a connection is closed. If
-     * the callback has already been registered, this method has no
-     * effect.
-     *
-     * @param cb The callback to add.
-     *
-     **/
-
-    void
-    add_close_cb(CloseCB cb);
 
     //
     // IDL:orb.yoko.apache.org/OCI/TransportInfo/remove_close_cb:1.0
     //
-    /**
-     *
-     * Remove a close callback. If the callback was not registered,
-     * this method has no effect.
-     *
-     * @param cb The callback to remove.
-     *
-     **/
-
-    void
-    remove_close_cb(CloseCB cb);
 
     //
     // IDL:orb.yoko.apache.org/OCI/TransportInfo/get_service_contexts:1.0
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/iiop.java b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/iiop.java
index e3ae54a..2f43cc7 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/OCI/iiop.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/OCI/iiop.java
@@ -17,10 +17,11 @@
 
 package org.apache.yoko.orb.OCI;
 
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
+import org.apache.yoko.orb.OB.AssertionFailed;
 import org.apache.yoko.orb.OCI.IIOP.ConnectionHelper;
+import org.apache.yoko.orb.OCI.IIOP.ExtendedConnectionHelper;
 import org.apache.yoko.osgi.ProviderLocator;
 
 public class iiop implements PluginInit {
@@ -51,21 +52,32 @@
         //
         args.value = parse_args(args.value, props);
 
-        ConnectionHelper helper = null;
-
         try {
             // get the appropriate class for the loading.
             ClassLoader loader = Thread.currentThread().getContextClassLoader();
 
             Class c = ProviderLocator.loadClass(connectionHelper, getClass(), loader);
-            helper = (org.apache.yoko.orb.OCI.IIOP.ConnectionHelper) c.newInstance();
-            // give this a chance to initializer
-            helper.init(orb, helperArgs);
+            Object o = c.newInstance();
+            if (o instanceof org.apache.yoko.orb.OCI.IIOP.ConnectionHelper) {
+                ConnectionHelper helper = (org.apache.yoko.orb.OCI.IIOP.ConnectionHelper) o;
+                // give this a chance to initializer
+                helper.init(orb, helperArgs);
+                return new org.apache.yoko.orb.OCI.IIOP.Plugin_impl(orb, helper);
+            } else if (o instanceof org.apache.yoko.orb.OCI.IIOP.ExtendedConnectionHelper) {
+                ExtendedConnectionHelper helper = (org.apache.yoko.orb.OCI.IIOP.ExtendedConnectionHelper) o;
+                // give this a chance to initializer
+                helper.init(orb, helperArgs);
+                return new org.apache.yoko.orb.OCI.IIOP.Plugin_impl(orb, helper);
+            }
+            throw new AssertionFailed("connection helper class " + connectionHelper + " does not implement ConnectionHelper or ExtendedConnectionHelper");
+        } catch (AssertionFailed af) {
+            throw af;
+        } catch (org.omg.CORBA.INITIALIZE i) {
+            throw i;
         } catch (Exception ex) {
             throw new org.omg.CORBA.INITIALIZE("unable to load IIOP ConnectionHelper plug-in `" + connectionHelper + "': " + ex.getMessage());
         }
 
-        return new org.apache.yoko.orb.OCI.IIOP.Plugin_impl(orb, helper);
     }
 
     //
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 de842e6..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
@@ -17,6 +17,11 @@
 
 package org.apache.yoko.orb.PortableInterceptor;
 
+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 {
     //
@@ -361,23 +366,26 @@
         argStrategy_.setArgsAvail(true);
         argStrategy_.setExceptAvail(true);
 
-        java.util.Enumeration e = interceptors.elements();
-        while (e.hasMoreElements()) {
-            org.omg.PortableInterceptor.ClientRequestInterceptor interceptor = (org.omg.PortableInterceptor.ClientRequestInterceptor) e
-                    .nextElement();
-            try {
-                interceptor.send_request(this);
-                interceptors_.addElement(interceptor);
-            } catch (org.omg.CORBA.SystemException ex) {
-                status_ = org.omg.PortableInterceptor.SYSTEM_EXCEPTION.value;
-                receivedException_ = ex;
-                _OB_reply();
-            } catch (org.omg.PortableInterceptor.ForwardRequest ex) {
-                status_ = org.omg.PortableInterceptor.LOCATION_FORWARD.value;
-                org.apache.yoko.orb.CORBA.Delegate p = (org.apache.yoko.orb.CORBA.Delegate) (((org.omg.CORBA.portable.ObjectImpl) ex.forward)
-                        ._get_delegate());
-                forwardReference_ = p._OB_IOR();
-                _OB_reply();
+        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
+                        .nextElement();
+                try {
+                    interceptor.send_request(this);
+                    interceptors_.addElement(interceptor);
+                } catch (org.omg.CORBA.SystemException ex) {
+                    status_ = org.omg.PortableInterceptor.SYSTEM_EXCEPTION.value;
+                    receivedException_ = ex;
+                    _OB_reply();
+                } catch (org.omg.PortableInterceptor.ForwardRequest ex) {
+                    status_ = org.omg.PortableInterceptor.LOCATION_FORWARD.value;
+                    org.apache.yoko.orb.CORBA.Delegate p = (org.apache.yoko.orb.CORBA.Delegate) (((org.omg.CORBA.portable.ObjectImpl) ex.forward)
+                            ._get_delegate());
+                    forwardReference_ = p._OB_IOR();
+                    _OB_reply();
+                }
             }
         }
 
@@ -393,49 +401,52 @@
             current_._OB_pushSlotData(currentSlots_);
         }
 
-        int curr = interceptors_.size() - 1;
-        while (!interceptors_.isEmpty()) {
-            try {
-                org.omg.PortableInterceptor.ClientRequestInterceptor i = (org.omg.PortableInterceptor.ClientRequestInterceptor) interceptors_
-                        .elementAt(curr);
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
+            int curr = interceptors_.size() - 1;
+            while (!interceptors_.isEmpty()) {
+                try {
+                    org.omg.PortableInterceptor.ClientRequestInterceptor i = (org.omg.PortableInterceptor.ClientRequestInterceptor) interceptors_
+                            .elementAt(curr);
 
-                if (status_ == org.omg.PortableInterceptor.SUCCESSFUL.value) {
-                    //
-                    // The result, arguments are available
-                    //
-                    argStrategy_.setResultAvail(true);
+                    if (status_ == org.omg.PortableInterceptor.SUCCESSFUL.value) {
+                        //
+                        // The result, arguments are available
+                        //
+                        argStrategy_.setResultAvail(true);
 
-                    i.receive_reply(this);
-                } else if (status_ == org.omg.PortableInterceptor.SYSTEM_EXCEPTION.value
-                        || status_ == org.omg.PortableInterceptor.USER_EXCEPTION.value) {
-                    //
-                    // The result, arguments not available
-                    //
-                    argStrategy_.setResultAvail(false);
-                    argStrategy_.setArgsAvail(false);
+                        i.receive_reply(this);
+                    } else if (status_ == org.omg.PortableInterceptor.SYSTEM_EXCEPTION.value
+                            || status_ == org.omg.PortableInterceptor.USER_EXCEPTION.value) {
+                        //
+                        // The result, arguments not available
+                        //
+                        argStrategy_.setResultAvail(false);
+                        argStrategy_.setArgsAvail(false);
 
-                    i.receive_exception(this);
-                } else {
-                    //
-                    // The result, arguments not available
-                    //
-                    argStrategy_.setResultAvail(false);
-                    argStrategy_.setArgsAvail(false);
+                        i.receive_exception(this);
+                    } else {
+                        //
+                        // The result, arguments not available
+                        //
+                        argStrategy_.setResultAvail(false);
+                        argStrategy_.setArgsAvail(false);
 
-                    i.receive_other(this);
+                        i.receive_other(this);
+                    }
+                } catch (org.omg.CORBA.SystemException ex) {
+                    status_ = org.omg.PortableInterceptor.SYSTEM_EXCEPTION.value;
+                    receivedException_ = ex;
+                    receivedId_ = null;
+                } catch (org.omg.PortableInterceptor.ForwardRequest ex) {
+                    status_ = org.omg.PortableInterceptor.LOCATION_FORWARD.value;
+                    org.apache.yoko.orb.CORBA.Delegate p = (org.apache.yoko.orb.CORBA.Delegate) (((org.omg.CORBA.portable.ObjectImpl) ex.forward)
+                            ._get_delegate());
+                    forwardReference_ = p._OB_IOR();
                 }
-            } catch (org.omg.CORBA.SystemException ex) {
-                status_ = org.omg.PortableInterceptor.SYSTEM_EXCEPTION.value;
-                receivedException_ = ex;
-                receivedId_ = null;
-            } catch (org.omg.PortableInterceptor.ForwardRequest ex) {
-                status_ = org.omg.PortableInterceptor.LOCATION_FORWARD.value;
-                org.apache.yoko.orb.CORBA.Delegate p = (org.apache.yoko.orb.CORBA.Delegate) (((org.omg.CORBA.portable.ObjectImpl) ex.forward)
-                        ._get_delegate());
-                forwardReference_ = p._OB_IOR();
+                interceptors_.removeElementAt(curr);
+                --curr;
             }
-            interceptors_.removeElementAt(curr);
-            --curr;
         }
 
         //
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 b0ea93c..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
@@ -17,6 +17,11 @@
 
 package org.apache.yoko.orb.PortableInterceptor;
 
+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 {
     //
@@ -377,7 +382,8 @@
         argStrategy_.setArgsAvail(false);
         argStrategy_.setExceptAvail(false);
 
-        try {
+        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
@@ -405,7 +411,8 @@
 
         status_ = NO_REPLY;
 
-        try {
+        try (CmsfOverride cmsfo = CmsfThreadLocal.override();
+             YasfOverride yasfo = YasfThreadLocal.override()) {
             java.util.Enumeration e = interceptors_.elements();
             while (e.hasMoreElements()) {
                 ((org.omg.PortableInterceptor.ServerRequestInterceptor) (e
@@ -431,14 +438,17 @@
         //
         servant_ = null;
 
-        int curr = interceptors_.size() - 1;
-        while (!interceptors_.isEmpty()) {
-            org.omg.PortableInterceptor.ServerRequestInterceptor i = (org.omg.PortableInterceptor.ServerRequestInterceptor) interceptors_
-                    .elementAt(curr);
-            interceptors_.removeElementAt(curr);
-            --curr;
+        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_
+                        .elementAt(curr);
+                interceptors_.removeElementAt(curr);
+                --curr;
 
-            i.send_reply(this);
+                i.send_reply(this);
+            }
         }
 
         //
@@ -464,7 +474,8 @@
         //
         servant_ = null;
 
-        try {
+        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);
@@ -506,7 +517,8 @@
         //
         servant_ = null;
 
-        try {
+        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/activator/Activator.java b/yoko-core/src/main/java/org/apache/yoko/orb/activator/Activator.java
new file mode 100644
index 0000000..a6a2d0d
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/activator/Activator.java
@@ -0,0 +1,16 @@
+package org.apache.yoko.orb.activator;
+
+import org.apache.yoko.osgi.locator.activator.AbstractBundleActivator;
+
+public class Activator extends AbstractBundleActivator {
+
+    public Activator() {
+        super(new Info[] {new Info("org.apache.yoko.orb.CORBA.ORB", "org.apache.yoko.orb.CORBA.ORB", 1),
+                new Info("org.apache.yoko.orb.CORBA.ORBSingleton", "org.apache.yoko.orb.CORBA.ORBSingleton", 1)
+        },
+                new Info[] {new Info("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB", 1),
+                new Info("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton", 1)
+        });
+    }
+
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfClientInterceptor.java b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfClientInterceptor.java
new file mode 100644
index 0000000..a1a6913
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfClientInterceptor.java
@@ -0,0 +1,76 @@
+package org.apache.yoko.orb.cmsf;
+
+import static org.apache.yoko.orb.OB.MinorCodes.MinorInvalidComponentId;
+import static org.apache.yoko.orb.cmsf.CmsfVersion.CMSFv1;
+import static org.apache.yoko.orb.cmsf.CmsfVersion.CMSFv2;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.yoko.util.cmsf.CmsfThreadLocal;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.LocalObject;
+import org.omg.IOP.TAG_RMI_CUSTOM_MAX_STREAM_FORMAT;
+import org.omg.IOP.TaggedComponent;
+import org.omg.PortableInterceptor.ClientRequestInfo;
+import org.omg.PortableInterceptor.ClientRequestInterceptor;
+import org.omg.PortableInterceptor.ForwardRequest;
+
+public final class CmsfClientInterceptor extends LocalObject implements ClientRequestInterceptor {
+    private static final String NAME = CmsfClientInterceptor.class.getName();
+
+    @Override
+    public void send_request(ClientRequestInfo ri) throws ForwardRequest {
+        CmsfVersion cmsf = CMSFv1;
+        try {
+            TaggedComponent tc = ri.get_effective_component(TAG_RMI_CUSTOM_MAX_STREAM_FORMAT.value);
+            cmsf = CmsfVersion.readData(tc.component_data);
+        } catch (BAD_PARAM e) {
+            if (e.minor != MinorInvalidComponentId) {
+                throw e;
+            }
+        }
+        CmsfThreadLocal.push(cmsf.getValue());
+        
+        if (CmsfVersion.ENABLED) ri.add_request_service_context(CMSFv2.getSc(), false);
+    }
+
+    @Override
+    public void send_poll(ClientRequestInfo ri) {
+    }
+
+    @Override
+    public void receive_reply(ClientRequestInfo ri) {
+        CmsfThreadLocal.pop();
+    }
+
+    @Override
+    public void receive_exception(ClientRequestInfo ri) throws ForwardRequest {
+        CmsfThreadLocal.pop();
+    }
+
+    @Override
+    public void receive_other(ClientRequestInfo ri) throws ForwardRequest {
+        CmsfThreadLocal.pop();
+    }
+
+    @Override
+    public String name() {
+        return NAME;
+    }
+
+    @Override
+    public void destroy() {
+    }
+    
+    private void readObject(ObjectInputStream ios) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+    
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfIORInterceptor.java b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfIORInterceptor.java
new file mode 100644
index 0000000..1c5ca4b
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfIORInterceptor.java
@@ -0,0 +1,38 @@
+package org.apache.yoko.orb.cmsf;
+
+import static org.apache.yoko.orb.cmsf.CmsfVersion.CMSFv2;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.omg.CORBA.LocalObject;
+import org.omg.PortableInterceptor.IORInfo;
+import org.omg.PortableInterceptor.IORInterceptor;
+
+public final class CmsfIORInterceptor extends LocalObject implements IORInterceptor {
+    private static final String NAME = CmsfIORInterceptor.class.getName();
+
+    @Override
+    public void establish_components(IORInfo info) {
+        if (CmsfVersion.ENABLED) info.add_ior_component(CMSFv2.getTc());
+    }
+
+    @Override
+    public String name() {
+        return NAME;
+    }
+
+    @Override
+    public void destroy() {
+    }
+    
+    private void readObject(ObjectInputStream ios) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+    
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfServerInterceptor.java b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfServerInterceptor.java
new file mode 100644
index 0000000..123a044
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfServerInterceptor.java
@@ -0,0 +1,102 @@
+package org.apache.yoko.orb.cmsf;
+
+import static org.apache.yoko.orb.OB.MinorCodes.MinorInvalidServiceContextId;
+import static org.apache.yoko.orb.cmsf.CmsfVersion.CMSFv1;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.yoko.orb.OB.IORUtil;
+import org.apache.yoko.util.cmsf.CmsfThreadLocal;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.INTERNAL;
+import org.omg.CORBA.LocalObject;
+import org.omg.IOP.RMICustomMaxStreamFormat;
+import org.omg.IOP.ServiceContext;
+import org.omg.PortableInterceptor.ForwardRequest;
+import org.omg.PortableInterceptor.InvalidSlot;
+import org.omg.PortableInterceptor.ServerRequestInfo;
+import org.omg.PortableInterceptor.ServerRequestInterceptor;
+
+public final class CmsfServerInterceptor extends LocalObject implements ServerRequestInterceptor {
+    private static final Logger LOGGER = Logger.getLogger(CmsfServerInterceptor.class.getName());
+    private static final String NAME = CmsfServerInterceptor.class.getName();
+
+    private final int slotId;
+    
+    public CmsfServerInterceptor(int slotId) {
+        this.slotId = slotId;
+    }
+
+    @Override
+    public void receive_request_service_contexts(ServerRequestInfo ri) throws ForwardRequest {
+        CmsfThreadLocal.reset();
+        CmsfVersion cmsf = CMSFv1;
+        try {
+            ServiceContext sc = ri.get_request_service_context(RMICustomMaxStreamFormat.value);
+            cmsf = CmsfVersion.readData(sc.context_data);
+            if (LOGGER.isLoggable(Level.FINEST))
+                LOGGER.finest(String.format("Using custom marshal stream format version: %s, retrieved from bytes: %s",
+                    cmsf, IORUtil.dump_octets(sc.context_data)));
+        } catch (BAD_PARAM e) {
+            if (e.minor != MinorInvalidServiceContextId) {
+                throw e;
+            }
+        }
+        try {
+            ri.set_slot(slotId, cmsf.getAny());
+        } catch (InvalidSlot e) {
+            throw (INTERNAL)(new INTERNAL(e.getMessage())).initCause(e);
+        }
+    }
+
+    @Override
+    public void receive_request(ServerRequestInfo ri) throws ForwardRequest {
+    }
+    
+    private void setupCmsfThreadLocalValue(ServerRequestInfo ri) {
+        CmsfVersion cmsf = CMSFv1;
+        try {
+            cmsf = CmsfVersion.readAny(ri.get_slot(slotId));
+        } catch (InvalidSlot e) {
+            throw (INTERNAL)(new INTERNAL(e.getMessage())).initCause(e);
+        }
+        CmsfThreadLocal.push(cmsf.getValue());
+    }
+
+    @Override
+    public void send_reply(ServerRequestInfo ri) {
+        setupCmsfThreadLocalValue(ri);
+    }
+
+    @Override
+    public void send_exception(ServerRequestInfo ri) throws ForwardRequest {
+        setupCmsfThreadLocalValue(ri);
+    }
+
+    @Override
+    public void send_other(ServerRequestInfo ri) throws ForwardRequest {
+        setupCmsfThreadLocalValue(ri);
+    }
+
+    @Override
+    public String name() {
+        return NAME;
+    }
+
+    @Override
+    public void destroy() {
+    }
+    
+    private void readObject(ObjectInputStream ios) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+    
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfVersion.java b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfVersion.java
new file mode 100644
index 0000000..552c942
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/cmsf/CmsfVersion.java
@@ -0,0 +1,83 @@
+package org.apache.yoko.orb.cmsf;
+
+import java.io.IOException;
+import java.util.Arrays;
+
+import org.apache.yoko.orb.OCI.Buffer;
+import org.omg.CORBA.Any;
+import org.omg.CORBA.INTERNAL;
+import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.ORB;
+import org.omg.IOP.RMICustomMaxStreamFormat;
+import org.omg.IOP.ServiceContext;
+import org.omg.IOP.TAG_RMI_CUSTOM_MAX_STREAM_FORMAT;
+import org.omg.IOP.TaggedComponent;
+
+public enum CmsfVersion {
+    CMSFv1(1), CMSFv2(2);
+    public static final boolean ENABLED = true;
+    private final byte value;
+    private final TaggedComponent tc;
+    private final ServiceContext sc;
+    private final Any any;
+    
+    private CmsfVersion(int value) {
+        this((byte)(value & 0xff));
+    }
+    
+    private CmsfVersion(byte value) {
+        this.value = value;
+        final byte[] data = genData(value);
+        this.tc = new TaggedComponent(TAG_RMI_CUSTOM_MAX_STREAM_FORMAT.value, data.clone());
+        this.sc = new ServiceContext(RMICustomMaxStreamFormat.value, data);
+        this.any = ORB.init().create_any();
+        this.any.insert_octet((byte)value);
+    }
+    
+    byte getValue() {
+        return value;
+    }
+    
+    TaggedComponent getTc() {
+        return tc;
+    }
+    
+    ServiceContext getSc() {
+        return sc;
+    }
+    
+    Any getAny() {
+        return any;
+    }
+
+    static CmsfVersion readAny(Any any) {
+        if (any == null) return CMSFv1;
+        return (any.extract_octet() >= 2) ? CMSFv2 : CMSFv1;
+    }
+    
+    static CmsfVersion readData(byte[] data) {
+        if (data == null) return CMSFv1;
+        int cmsf = 1;
+        Buffer buf = new Buffer(data, data.length);
+        try (org.apache.yoko.orb.CORBA.InputStream in = 
+                new org.apache.yoko.orb.CORBA.InputStream(buf, 0, false)) {
+            in._OB_readEndian();
+            cmsf = in.read_octet();
+        } catch (Exception e) {
+            throw (MARSHAL)(new MARSHAL(e.getMessage())).initCause(e);
+        }
+        return (cmsf >= 2) ? CMSFv2 : CMSFv1;
+    }
+    
+    private static byte[] genData(byte value) {
+        Buffer buf = new Buffer(2);
+        try (org.apache.yoko.orb.CORBA.OutputStream out = 
+                new org.apache.yoko.orb.CORBA.OutputStream(buf)) {
+            out._OB_writeEndian();
+            out.write_octet(value);
+            return Arrays.copyOf(buf.data(), buf.length());
+        } catch (IOException e) {
+            throw (INTERNAL)(new INTERNAL(e.getMessage())).initCause(e);
+        }
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/csi/SecurityContext.java b/yoko-core/src/main/java/org/apache/yoko/orb/csi/SecurityContext.java
index 932aa83..d501f28 100644
--- a/yoko-core/src/main/java/org/apache/yoko/orb/csi/SecurityContext.java
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/csi/SecurityContext.java
@@ -21,6 +21,7 @@
 import javax.security.auth.login.LoginException;
 
 import java.security.AccessController;
+
 import org.apache.yoko.orb.util.GetSystemPropertyAction;
 import org.apache.yoko.osgi.ProviderLocator;
 
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/NameServiceInitializer.java b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/NameServiceInitializer.java
new file mode 100644
index 0000000..ef9049b
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/NameServiceInitializer.java
@@ -0,0 +1,155 @@
+package org.apache.yoko.orb.spi.naming;
+
+import static org.apache.yoko.orb.spi.naming.RemoteAccess.*;
+
+import java.util.Arrays;
+
+import org.apache.yoko.orb.CosNaming.tnaming2.NamingContextImpl;
+import org.apache.yoko.orb.OB.BootLocator;
+import org.apache.yoko.orb.OB.BootManagerPackage.NotFound;
+import org.omg.CORBA.BooleanHolder;
+import org.omg.CORBA.INITIALIZE;
+import org.omg.CORBA.LocalObject;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.ObjectHolder;
+import org.omg.CORBA.Policy;
+import org.omg.PortableInterceptor.ORBInitInfo;
+import org.omg.PortableInterceptor.ORBInitializer;
+import org.omg.PortableServer.IdAssignmentPolicyValue;
+import org.omg.PortableServer.LifespanPolicyValue;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.Servant;
+import org.omg.PortableServer.ServantRetentionPolicyValue;
+import org.omg.PortableServer.POAPackage.AdapterAlreadyExists;
+import org.omg.PortableServer.POAPackage.AdapterNonExistent;
+import org.omg.PortableServer.POAPackage.InvalidPolicy;
+
+public class NameServiceInitializer extends LocalObject implements ORBInitializer {
+    /** The property name to use to initialize an ORB with this initializer. */
+    public static final String NS_ORB_INIT_PROP = ORBInitializer.class.getName() + "Class." + NameServiceInitializer.class.getName();
+    /**
+     * The name of this name service, as used with <code>corbaloc:</code> URLs
+     * and with calls to {@link ORB#resolve_initial_references(String)}.
+     */
+    public static final String SERVICE_NAME = "NameService";
+
+    /**
+     * The POA name this name service will use to activate contexts.
+     * The name service will first try <code>rootPoa.find_POA()</code>
+     * to find the POA with this name. If that returns null, it will
+     * call <code>rootPoa.create_POA()</code> to create the POA with
+     * this name.
+     */
+    public static final String POA_NAME = "NameServicePOA";
+
+    /**
+     * The policies required for the NameService POA. Users providing
+     * the NameService POA must include these policies when creating
+     * the POA. If creation is to be left to this initializer, these
+     * policies will be used automatically.
+     * @param rootPOA the root POA for the ORB in use
+     * @return a new Policy array object, owned by the caller
+     */
+    public static final Policy[] createPOAPolicies(POA rootPOA) {
+        return new Policy[] {
+                rootPOA.create_lifespan_policy(LifespanPolicyValue.TRANSIENT),
+                rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID),
+                rootPOA.create_servant_retention_policy(ServantRetentionPolicyValue.RETAIN)
+        };
+    }
+
+    /**
+     * The ORB argument that specifies remote accessibility of this name service.
+     * The next argument must be one of these literal string values:
+     * <ul>
+     *   <li><code>"</code>{@link #readOnly}<code>"</code></li>
+     *   <li><code>"</code>{@link #readWrite}<code>"</code></li>
+     * </ul>
+     */
+    public static final String NS_REMOTE_ACCESS_ARG = "-YokoNameServiceRemoteAccess";
+
+    abstract static class BootLocatorImpl extends LocalObject implements BootLocator {}
+
+    private static final long serialVersionUID = 1L;
+
+    private RemoteAccess remoteAccess = readWrite;
+
+    @Override
+    public void pre_init(ORBInitInfo info) {
+        try {
+            final NamingContextImpl local = new NamingContextImpl();
+            info.register_initial_reference(SERVICE_NAME, local);
+            String[] args = info.arguments();
+            // iterate over all BUT THE LAST ARG
+            for (int i = 0; i < args.length - 1; i++) {
+                switch (args[i]) {
+                    case NS_REMOTE_ACCESS_ARG:
+                        i++;
+                        this.remoteAccess = RemoteAccess.valueOf(args[i]);
+                }
+            }
+
+        } catch (Exception e) {
+            throw (INITIALIZE) (new INITIALIZE().initCause(e));
+        }
+    }
+
+    @Override
+    public void post_init(ORBInitInfo info) {
+        try {
+
+            final POA rootPOA = (POA) info.resolve_initial_references("RootPOA");
+            final NamingContextImpl local = (NamingContextImpl) info.resolve_initial_references("NameService");
+            final String serviceName = getServiceName(info);
+
+            final org.apache.yoko.orb.OB.BootManager bootManager = org.apache.yoko.orb.OB.BootManagerHelper.narrow(info
+                    .resolve_initial_references("BootManager"));
+            final byte[] objectId = serviceName.getBytes();
+            bootManager.set_locator(new BootLocatorImpl() {
+                @Override
+                public void locate(byte[] oid, ObjectHolder obj, BooleanHolder add) throws NotFound {
+                    if (!!!Arrays.equals(oid, objectId))
+                        throw new NotFound(new String(oid));
+
+                    try {
+                        rootPOA.the_POAManager().activate();
+
+                        final POA nameServicePOA = findOrCreatePOA(rootPOA);
+                        nameServicePOA.the_POAManager().activate();
+
+                        final Servant nameServant = local.getServant(nameServicePOA, remoteAccess);
+
+                        // return the context stub via the object holder
+                        obj.value = nameServant._this_object();
+                        // return true via the boolean holder
+                        // to tell the boot manager to re-use
+                        // this result so we only get called once
+                        add.value = true;
+                    } catch (Exception e) {
+                        throw (NotFound) (new NotFound("Unexpected").initCause(e));
+                    }
+                }
+
+                private POA findOrCreatePOA(final POA rootPOA) throws AdapterAlreadyExists, InvalidPolicy {
+                    try {
+                        return rootPOA.find_POA(POA_NAME, true);
+                    } catch (AdapterNonExistent e) {
+                        final Policy[] policies = createPOAPolicies(rootPOA);
+                        return rootPOA.create_POA(POA_NAME, null, policies);
+                    }
+                }
+            });
+        } catch (Exception e) {
+            throw (INITIALIZE) (new INITIALIZE().initCause(e));
+        }
+    }
+
+    private String getServiceName(ORBInitInfo info) {
+        for (String arg : info.arguments()) {
+            if (arg.startsWith("ORBNameService=")) {
+                return arg.substring("ORBNameService=".length());
+            }
+        }
+        return "NameService";
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/RemoteAccess.java b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/RemoteAccess.java
new file mode 100644
index 0000000..a4c8bc3
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/RemoteAccess.java
@@ -0,0 +1,11 @@
+package org.apache.yoko.orb.spi.naming;
+
+import org.omg.CosNaming.NamingContext;
+
+/** The remote access settings for a name service. */
+public enum RemoteAccess{
+    /** Remote clients can perform operations on {@link NamingContext} that do not alter the state of the name service.*/
+    readOnly, 
+    /** Remote clients can perform all operations on {@link NamingContext} objects from this name service.*/
+    readWrite
+}
\ No newline at end of file
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/Resolvable.java b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/Resolvable.java
new file mode 100644
index 0000000..63eda2c
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/Resolvable.java
@@ -0,0 +1,8 @@
+package org.apache.yoko.orb.spi.naming;
+
+import org.omg.CORBA.Object;
+
+public interface Resolvable extends Object {
+
+	org.omg.CORBA.Object resolve(); // This is the factory method
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/Resolver.java b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/Resolver.java
new file mode 100644
index 0000000..7c4c9ab
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/spi/naming/Resolver.java
@@ -0,0 +1,5 @@
+package org.apache.yoko.orb.spi.naming;
+
+import org.omg.CORBA.LocalObject;
+
+public abstract class Resolver extends LocalObject implements Resolvable {}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoLock.java b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoLock.java
new file mode 100644
index 0000000..c2dbf5d
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoLock.java
@@ -0,0 +1,51 @@
+package org.apache.yoko.orb.util;
+
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.Lock;
+
+public class AutoLock implements AutoCloseable {
+    final AtomicReference<Lock> lockRef;
+    final Lock downgradeLock;
+    final int downgradeHeld;
+
+    AutoLock(Lock lock) {
+        this(lock, null, 0);
+    }
+
+    AutoLock(Lock lock, Lock downgradeLock, int downgradeHeld) {
+        lockRef = new AtomicReference<>(lock);
+        this.downgradeLock = downgradeLock;
+        this.downgradeHeld = downgradeHeld;
+        for (int i = downgradeHeld; i > 0; i--) {
+            downgradeLock.unlock();
+        }
+        lock.lock();
+    }
+
+    @Override
+    public void close() {
+        Lock lock = lockRef.getAndSet(null);
+        if (lock == null)
+            return;
+        for (int i = 0; i < downgradeHeld; i++) {
+            downgradeLock.lock();
+        }
+        lock.unlock();
+    }
+
+    public Condition newCondition() {
+        return lockRef.get().newCondition();
+    }
+
+    public boolean downgrade() {
+        if (downgradeLock == null)
+            return false;
+        Lock oldLock = lockRef.getAndSet(downgradeLock);
+        if (oldLock == downgradeLock)
+            return false;
+        downgradeLock.lock();
+        oldLock.unlock();
+        return true;
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoReadWriteLock.java b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoReadWriteLock.java
new file mode 100644
index 0000000..f9b47d0
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/util/AutoReadWriteLock.java
@@ -0,0 +1,15 @@
+package org.apache.yoko.orb.util;
+
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+public class AutoReadWriteLock {
+    private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
+    
+    public AutoLock getReadLock() {
+        return new AutoLock(lock.readLock());
+    }
+
+    public AutoLock getWriteLock() {
+        return new AutoLock(lock.writeLock(), lock.readLock(), lock.getReadHoldCount());
+    }
+}
diff --git a/yoko-core/src/main/java/org/apache/yoko/orb/util/UnmodifiableEnumMap.java b/yoko-core/src/main/java/org/apache/yoko/orb/util/UnmodifiableEnumMap.java
new file mode 100644
index 0000000..f241a93
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/util/UnmodifiableEnumMap.java
@@ -0,0 +1,45 @@
+package org.apache.yoko.orb.util;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class UnmodifiableEnumMap<K extends Enum<K>, V> extends EnumMap<K, V> {
+    private static final long serialVersionUID = 1L;
+
+    public UnmodifiableEnumMap(Class<K> keyType) {
+        super(keyType);
+        // initialise all values up front to avoid races later
+        for(K key : keyType.getEnumConstants())
+            super.put(key, computeValueFor(key));
+    }
+
+    protected abstract V computeValueFor(K key);
+
+    @Override
+    public final V remove(Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final V put(K key, V value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final void putAll(Map<? extends K, ? extends V> m) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final Set<K> keySet() {
+        return Collections.unmodifiableSet(super.keySet());
+    }
+
+    @Override
+    public final Collection<V> values() {
+        return Collections.unmodifiableCollection(super.values());
+    }
+}
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
new file mode 100644
index 0000000..dc434a0
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfClientInterceptor.java
@@ -0,0 +1,62 @@
+package org.apache.yoko.orb.yasf;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+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;
+import org.omg.PortableInterceptor.ForwardRequest;
+
+public class YasfClientInterceptor extends LocalObject implements ClientRequestInterceptor {
+    private static final String NAME = YasfClientInterceptor.class.getName();
+
+    @Override
+    public void send_request(ClientRequestInfo ri) throws ForwardRequest {
+        byte[] yasfData = YasfHelper.readData(ri);
+
+        YasfThreadLocal.push(Yasf.toSet(yasfData));
+
+        YasfHelper.addSc(ri, Yasf.supported());
+    }
+
+    @Override
+    public void send_poll(ClientRequestInfo ri) {
+    }
+
+    @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
+    public String name() {
+        return NAME;
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+    private void readObject(ObjectInputStream ios) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+}
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
new file mode 100644
index 0000000..ec3976a
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfIORInterceptor.java
@@ -0,0 +1,37 @@
+package org.apache.yoko.orb.yasf;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+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;
+
+public class YasfIORInterceptor extends LocalObject implements IORInterceptor {
+    private static final String NAME = YasfIORInterceptor.class.getName();
+
+    @Override
+    public void establish_components(IORInfo info) {
+        YasfHelper.addTc(info, Yasf.supported());
+    }
+
+    @Override
+    public String name() {
+        return NAME;
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+    private void readObject(ObjectInputStream ios) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+}
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
new file mode 100644
index 0000000..352d70e
--- /dev/null
+++ b/yoko-core/src/main/java/org/apache/yoko/orb/yasf/YasfServerInterceptor.java
@@ -0,0 +1,72 @@
+package org.apache.yoko.orb.yasf;
+
+import java.io.IOException;
+import java.io.NotSerializableException;
+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;
+import org.omg.PortableInterceptor.ServerRequestInterceptor;
+
+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
+    public void receive_request(ServerRequestInfo ri) throws ForwardRequest {
+    }
+
+    @Override
+    public void send_reply(ServerRequestInfo ri) {
+        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 {
+        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 {
+        YasfThreadLocal.push(Yasf.toSet(YasfHelper.getSlot(slotId, ri)));
+        // Adding for diagnostic purposes
+        YasfHelper.addSc(ri, Yasf.supported());
+    }
+
+    @Override
+    public String name() {
+        return NAME;
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+    private void readObject(ObjectInputStream ios) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        throw new NotSerializableException(NAME);
+    }
+}
diff --git a/yoko-core/src/main/resources/OSGI-INF/blueprint/provider.xml b/yoko-core/src/main/resources/OSGI-INF/blueprint/provider.xml
deleted file mode 100644
index f811366..0000000
--- a/yoko-core/src/main/resources/OSGI-INF/blueprint/provider.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
--->
-<!--
-
-  blueprint configuration for jndi providers
-  -->
-
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
-    <reference id="register" interface="org.apache.yoko.osgi.locator.Register" component-name="yokoRegistryBean"/>
-
-    <bean class="org.apache.yoko.osgi.locator.ServiceBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>org.omg.CORBA.ORBClass</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.orb.CORBA.ORB</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="register"/>
-        </argument>
-    </bean>
-    <bean class="org.apache.yoko.osgi.locator.ServiceBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>org.omg.CORBA.ORBSingletonClass</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.orb.CORBA.ORBSingleton</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="register"/>
-        </argument>
-    </bean>
-
-    <bean class="org.apache.yoko.osgi.locator.ProviderBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>org.apache.yoko.orb.CORBA.ORB</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.orb.CORBA.ORB</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="register"/>
-        </argument>
-    </bean>
-    <bean class="org.apache.yoko.osgi.locator.ProviderBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>org.apache.yoko.orb.CORBA.ORBSingleton</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.orb.CORBA.ORBSingleton</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="register"/>
-        </argument>
-    </bean>
-
-
-</blueprint>
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectBasic.java b/yoko-core/src/test/java/ORBTest/TestObjectBasic.java
index baf8460..b8fcf90 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectBasic.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectBasic.java
@@ -17,7 +17,10 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
+
 import ORBTest_Basic.*;
 
 public class TestObjectBasic extends test.common.TestBase implements TestObject {
@@ -60,178 +63,178 @@
             short ret;
             ti.attrShort((short) -32768);
             ret = ti.attrShort();
-            TEST(ret == -32768);
+            assertTrue(ret == -32768);
 
             ti.attrShort((short) 32767);
             ret = ti.attrShort();
-            TEST(ret == 32767);
+            assertTrue(ret == 32767);
 
             ShortHolder inOut = new ShortHolder((short) 20);
             ShortHolder out = new ShortHolder();
             ret = ti.opShort((short) 10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             int ret;
             ti.attrLong(-2147483647 - 1);
             ret = ti.attrLong();
-            TEST(ret == -2147483647 - 1);
+            assertTrue(ret == -2147483647 - 1);
 
             ti.attrLong(2147483647);
             ret = ti.attrLong();
-            TEST(ret == 2147483647);
+            assertTrue(ret == 2147483647);
 
             IntHolder inOut = new IntHolder(20);
             IntHolder out = new IntHolder();
             ret = ti.opLong(10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             short ret;
             ti.attrUShort((short) 65535);
             ret = ti.attrUShort();
-            TEST(ret == (short) 65535);
+            assertTrue(ret == (short) 65535);
 
             ShortHolder inOut = new ShortHolder((short) 20);
             ShortHolder out = new ShortHolder();
             ret = ti.opUShort((short) 10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             int ret;
             ti.attrULong(2147483647);
             ret = ti.attrULong();
-            TEST(ret == 2147483647);
+            assertTrue(ret == 2147483647);
 
             IntHolder inOut = new IntHolder(20);
             IntHolder out = new IntHolder();
             ret = ti.opULong(10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             float ret;
             ti.attrFloat(3.40282347E+38F);
             ret = ti.attrFloat();
-            TEST(ret == 3.40282347E+38F);
+            assertTrue(ret == 3.40282347E+38F);
 
             ti.attrFloat(1.17549435E-38F);
             ret = ti.attrFloat();
-            TEST(ret == 1.17549435E-38F);
+            assertTrue(ret == 1.17549435E-38F);
 
             FloatHolder inOut = new FloatHolder(20);
             FloatHolder out = new FloatHolder();
             ret = ti.opFloat(10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             double ret;
             ti.attrDouble(1.7976931348623157E+308);
             ret = ti.attrDouble();
-            TEST(ret == 1.7976931348623157E+308);
+            assertTrue(ret == 1.7976931348623157E+308);
 
             ti.attrDouble(2.2250738585072014E-308);
             ret = ti.attrDouble();
-            TEST(ret == 2.2250738585072014E-308);
+            assertTrue(ret == 2.2250738585072014E-308);
 
             DoubleHolder inOut = new DoubleHolder(20);
             DoubleHolder out = new DoubleHolder();
             ret = ti.opDouble(10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             boolean ret;
             ti.attrBoolean(true);
             ret = ti.attrBoolean();
-            TEST(ret == true);
+            assertTrue(ret == true);
 
             ti.attrBoolean(false);
             ret = ti.attrBoolean();
-            TEST(ret == false);
+            assertTrue(ret == false);
 
             BooleanHolder inOut = new BooleanHolder(true);
             BooleanHolder out = new BooleanHolder();
             ret = ti.opBoolean(true, inOut, out);
-            TEST(ret == true);
-            TEST(inOut.value == true);
-            TEST(out.value == true);
+            assertTrue(ret == true);
+            assertTrue(inOut.value == true);
+            assertTrue(out.value == true);
 
             inOut.value = true;
             ret = ti.opBoolean(false, inOut, out);
-            TEST(ret == false);
-            TEST(inOut.value == false);
-            TEST(out.value == false);
+            assertTrue(ret == false);
+            assertTrue(inOut.value == false);
+            assertTrue(out.value == false);
 
             inOut.value = false;
             ret = ti.opBoolean(true, inOut, out);
-            TEST(ret == false);
-            TEST(inOut.value == false);
-            TEST(out.value == false);
+            assertTrue(ret == false);
+            assertTrue(inOut.value == false);
+            assertTrue(out.value == false);
         }
 
         {
             char ret;
             ti.attrChar('a');
             ret = ti.attrChar();
-            TEST(ret == 'a');
+            assertTrue(ret == 'a');
             ti.attrChar((char) 224);
             ret = ti.attrChar();
-            TEST(ret == (char) 224);
+            assertTrue(ret == (char) 224);
 
             CharHolder inOut = new CharHolder((char) 1);
             CharHolder out = new CharHolder();
             ret = ti.opChar('a', inOut, out);
-            TEST(ret == 'b');
-            TEST(inOut.value == 'b');
-            TEST(out.value == 'b');
+            assertTrue(ret == 'b');
+            assertTrue(inOut.value == 'b');
+            assertTrue(out.value == 'b');
         }
 
         {
             byte ret;
             ti.attrOctet((byte) 0xff);
             ret = ti.attrOctet();
-            TEST(ret == (byte) 0xff);
+            assertTrue(ret == (byte) 0xff);
 
             ti.attrOctet((byte) 0);
             ret = ti.attrOctet();
-            TEST(ret == (byte) 0);
+            assertTrue(ret == (byte) 0);
 
             ByteHolder inOut = new ByteHolder((byte) 20);
             ByteHolder out = new ByteHolder();
             ret = ti.opOctet((byte) 10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             String ret;
             ti.attrString("Hello");
             ret = ti.attrString();
-            TEST(ret.equals("Hello"));
+            assertTrue(ret.equals("Hello"));
 
             StringHolder inOut = new StringHolder("world!");
             StringHolder out = new StringHolder();
             ret = ti.opString("Hello, ", inOut, out);
-            TEST(ret.equals("Hello, world!"));
-            TEST(out.value.equals("Hello, world!"));
+            assertTrue(ret.equals("Hello, world!"));
+            assertTrue(out.value.equals("Hello, world!"));
         }
 
         {
@@ -248,7 +251,7 @@
                     ret = ti.attrAny();
                     String s;
                     s = ret.extract_string();
-                    TEST(s.equals("abc"));
+                    assertTrue(s.equals("abc"));
                 }
 
                 {
@@ -257,7 +260,7 @@
                     ret = ti.attrAny();
                     int d;
                     d = ret.extract_long();
-                    TEST(d == 3);
+                    assertTrue(d == 3);
                 }
 
                 {
@@ -266,7 +269,7 @@
                     ret = ti.attrAny();
                     TestEnum e;
                     e = TestEnumHelper.extract(ret);
-                    TEST(e == TestEnum.TestEnum3);
+                    assertTrue(e == TestEnum.TestEnum3);
                 }
 
                 {
@@ -280,9 +283,9 @@
                     vStructRet = VariableStructHelper.extract(ret);
                     vStructInOut = VariableStructHelper.extract(inOut.value);
                     vStructOut = VariableStructHelper.extract(out.value);
-                    TEST(vStructRet.s.equals("xyz"));
-                    TEST(vStructInOut.s.equals("xyz"));
-                    TEST(vStructOut.s.equals("xyz"));
+                    assertTrue(vStructRet.s.equals("xyz"));
+                    assertTrue(vStructInOut.s.equals("xyz"));
+                    assertTrue(vStructOut.s.equals("xyz"));
                 }
 
                 {
@@ -296,12 +299,12 @@
                     fUnionRet = FixedUnionHelper.extract(ret);
                     fUnionInOut = FixedUnionHelper.extract(inOut.value);
                     fUnionOut = FixedUnionHelper.extract(out.value);
-                    TEST(fUnionRet.discriminator() == 1);
-                    TEST(fUnionInOut.discriminator() == 1);
-                    TEST(fUnionOut.discriminator() == 1);
-                    TEST(fUnionRet.l() == 1);
-                    TEST(fUnionInOut.l() == 1);
-                    TEST(fUnionOut.l() == 1);
+                    assertTrue(fUnionRet.discriminator() == 1);
+                    assertTrue(fUnionInOut.discriminator() == 1);
+                    assertTrue(fUnionOut.discriminator() == 1);
+                    assertTrue(fUnionRet.l() == 1);
+                    assertTrue(fUnionInOut.l() == 1);
+                    assertTrue(fUnionOut.l() == 1);
                 }
 
                 {
@@ -315,9 +318,9 @@
                     vUnionRet = VariableUnionHelper.extract(ret);
                     vUnionInOut = VariableUnionHelper.extract(ret);
                     vUnionOut = VariableUnionHelper.extract(ret);
-                    TEST(!vUnionRet.discriminator());
-                    TEST(!vUnionInOut.discriminator());
-                    TEST(!vUnionOut.discriminator());
+                    assertTrue(!vUnionRet.discriminator());
+                    assertTrue(!vUnionInOut.discriminator());
+                    assertTrue(!vUnionOut.discriminator());
                 }
 
                 {
@@ -327,12 +330,12 @@
                     org.omg.CORBA.Object extract_obj = ret.extract_Object();
                     ORBTest_Basic.Intf ti2 = (ORBTest_Basic.IntfHelper
                             .extract(ret));
-                    TEST(ti._hash(1000) == ti2._hash(1000));
-                    TEST(ti._is_equivalent(ti2));
-                    TEST(ti._hash(1111) == extract_obj._hash(1111));
-                    TEST(ti._is_equivalent(extract_obj));
-                    TEST(extract_obj._hash(1234) == ti2._hash(1234));
-                    TEST(extract_obj._is_equivalent(ti2));
+                    assertTrue(ti._hash(1000) == ti2._hash(1000));
+                    assertTrue(ti._is_equivalent(ti2));
+                    assertTrue(ti._hash(1111) == extract_obj._hash(1111));
+                    assertTrue(ti._is_equivalent(extract_obj));
+                    assertTrue(extract_obj._hash(1234) == ti2._hash(1234));
+                    assertTrue(extract_obj._is_equivalent(ti2));
                 }
 
                 {
@@ -341,9 +344,9 @@
                     ti.attrAny(any);
                     ret = ti.attrAny();
                     char[] ret_char_seq = CharSeqHelper.extract(any);
-                    TEST(ret_char_seq.length == 4);
+                    assertTrue(ret_char_seq.length == 4);
                     for (int idx = 0; idx < 4; ++idx)
-                        TEST(char_seq[idx] == ret_char_seq[idx]);
+						assertTrue(char_seq[idx] == ret_char_seq[idx]);
                 }
 
                 {
@@ -352,9 +355,9 @@
                     ti.attrAny(any);
                     ret = ti.attrAny();
                     char[] ret_wchar_seq = WCharSeqHelper.extract(any);
-                    TEST(ret_wchar_seq.length == 4);
+                    assertTrue(ret_wchar_seq.length == 4);
                     for (int idx = 0; idx < 4; ++idx)
-                        TEST(wchar_seq[idx] == ret_wchar_seq[idx]);
+						assertTrue(wchar_seq[idx] == ret_wchar_seq[idx]);
                 }
             }
         }
@@ -363,37 +366,37 @@
             TestEnum ret;
             ti.attrTestEnum(TestEnum.TestEnum2);
             ret = ti.attrTestEnum();
-            TEST(ret == TestEnum.TestEnum2);
+            assertTrue(ret == TestEnum.TestEnum2);
 
             ti.attrTestEnum(TestEnum.TestEnum3);
             ret = ti.attrTestEnum();
-            TEST(ret == TestEnum.TestEnum3);
+            assertTrue(ret == TestEnum.TestEnum3);
 
             TestEnumHolder inOut = new TestEnumHolder(TestEnum.TestEnum2);
             TestEnumHolder out = new TestEnumHolder();
             ret = ti.opTestEnum(TestEnum.TestEnum3, inOut, out);
-            TEST(ret == TestEnum.TestEnum3);
-            TEST(inOut.value == TestEnum.TestEnum3);
-            TEST(out.value == TestEnum.TestEnum3);
+            assertTrue(ret == TestEnum.TestEnum3);
+            assertTrue(inOut.value == TestEnum.TestEnum3);
+            assertTrue(out.value == TestEnum.TestEnum3);
         }
 
         {
             ORBTest_Basic.Intf ret;
             ti.attrIntf(ti);
             ret = ti.attrIntf();
-            TEST(ret._hash(999) == ti._hash(999));
-            TEST(ret._is_equivalent(ti));
+            assertTrue(ret._hash(999) == ti._hash(999));
+            assertTrue(ret._is_equivalent(ti));
 
             ORBTest_Basic.IntfHolder inOut = (new ORBTest_Basic.IntfHolder(
                     (ORBTest_Basic.Intf) (ti._duplicate())));
             ORBTest_Basic.IntfHolder out = new ORBTest_Basic.IntfHolder();
             ret = ti.opIntf(ti, inOut, out);
-            TEST(ret._hash(1001) == ti._hash(1001));
-            TEST(ret._is_equivalent(ti));
-            TEST(inOut.value._hash(5000) == ti._hash(5000));
-            TEST(inOut.value._is_equivalent(ti));
-            TEST(out.value._hash(2000) == ti._hash(2000));
-            TEST(out.value._is_equivalent(ti));
+            assertTrue(ret._hash(1001) == ti._hash(1001));
+            assertTrue(ret._is_equivalent(ti));
+            assertTrue(inOut.value._hash(5000) == ti._hash(5000));
+            assertTrue(inOut.value._is_equivalent(ti));
+            assertTrue(out.value._hash(2000) == ti._hash(2000));
+            assertTrue(out.value._is_equivalent(ti));
         }
 
         {
@@ -404,20 +407,20 @@
             FixedStruct ret;
             ti.attrFixedStruct(st);
             ret = ti.attrFixedStruct();
-            TEST(ret.s == st.s);
-            TEST(ret.l == st.l);
+            assertTrue(ret.s == st.s);
+            assertTrue(ret.l == st.l);
 
             FixedStructHolder inOut = new FixedStructHolder(new FixedStruct());
             inOut.value.s = 10000;
             inOut.value.l = 100000;
             FixedStructHolder out = new FixedStructHolder();
             ret = ti.opFixedStruct(st, inOut, out);
-            TEST(ret.s == st.s);
-            TEST(ret.l == st.l);
-            TEST(inOut.value.s == st.s);
-            TEST(out.value.l == st.l);
-            TEST(inOut.value.s == st.s);
-            TEST(out.value.l == st.l);
+            assertTrue(ret.s == st.s);
+            assertTrue(ret.l == st.l);
+            assertTrue(inOut.value.s == st.s);
+            assertTrue(out.value.l == st.l);
+            assertTrue(inOut.value.s == st.s);
+            assertTrue(out.value.l == st.l);
         }
 
         {
@@ -427,16 +430,16 @@
             VariableStruct ret;
             ti.attrVariableStruct(st);
             ret = ti.attrVariableStruct();
-            TEST(ret.s.equals(st.s));
+            assertTrue(ret.s.equals(st.s));
 
             VariableStructHolder inOut = new VariableStructHolder(
                     new VariableStruct());
             inOut.value.s = "bla";
             VariableStructHolder out = new VariableStructHolder();
             ret = ti.opVariableStruct(st, inOut, out);
-            TEST(ret.s.equals(st.s));
-            TEST(inOut.value.s.equals(st.s));
-            TEST(out.value.s.equals(st.s));
+            assertTrue(ret.s.equals(st.s));
+            assertTrue(inOut.value.s.equals(st.s));
+            assertTrue(out.value.s.equals(st.s));
         }
 
         {
@@ -446,8 +449,8 @@
             FixedUnion ret;
             ti.attrFixedUnion(un);
             ret = ti.attrFixedUnion();
-            TEST(ret.discriminator() == 1);
-            TEST(ret.l() == 1);
+            assertTrue(ret.discriminator() == 1);
+            assertTrue(ret.l() == 1);
 
             un.b((short) 999, true);
             FixedUnionHolder inOut = new FixedUnionHolder();
@@ -455,12 +458,12 @@
             inOut.value.l(100);
             FixedUnionHolder out = new FixedUnionHolder();
             ret = ti.opFixedUnion(un, inOut, out);
-            TEST(ret.discriminator() == 999);
-            TEST(ret.b() == true);
-            TEST(out.value.discriminator() == 999);
-            TEST(out.value.b() == true);
-            TEST(inOut.value.discriminator() == 999);
-            TEST(inOut.value.b() == true);
+            assertTrue(ret.discriminator() == 999);
+            assertTrue(ret.b() == true);
+            assertTrue(out.value.discriminator() == 999);
+            assertTrue(out.value.b() == true);
+            assertTrue(inOut.value.discriminator() == 999);
+            assertTrue(inOut.value.b() == true);
 
             FixedStruct st = new FixedStruct();
             st.s = 10101;
@@ -469,15 +472,15 @@
             inOut.value = new FixedUnion();
             inOut.value.l(100);
             ret = ti.opFixedUnion(un, inOut, out);
-            TEST(ret.discriminator() == 3);
-            TEST(ret.st().s == 10101);
-            TEST(ret.st().l == -10101);
-            TEST(out.value.discriminator() == 3);
-            TEST(out.value.st().s == 10101);
-            TEST(out.value.st().l == -10101);
-            TEST(inOut.value.discriminator() == 3);
-            TEST(inOut.value.st().s == 10101);
-            TEST(inOut.value.st().l == -10101);
+            assertTrue(ret.discriminator() == 3);
+            assertTrue(ret.st().s == 10101);
+            assertTrue(ret.st().l == -10101);
+            assertTrue(out.value.discriminator() == 3);
+            assertTrue(out.value.st().s == 10101);
+            assertTrue(out.value.st().l == -10101);
+            assertTrue(inOut.value.discriminator() == 3);
+            assertTrue(inOut.value.st().s == 10101);
+            assertTrue(inOut.value.st().l == -10101);
         }
 
         {
@@ -489,7 +492,7 @@
             VariableUnion ret;
             ti.attrVariableUnion(un);
             ret = ti.attrVariableUnion();
-            TEST(ret.st().s.equals("$$$"));
+            assertTrue(ret.st().s.equals("$$$"));
 
             un.ti(ti);
             VariableUnionHolder inOut = new VariableUnionHolder(
@@ -497,12 +500,12 @@
             VariableUnionHolder out = new VariableUnionHolder();
             inOut.value.st(st);
             ret = ti.opVariableUnion(un, inOut, out);
-            TEST(ret.ti()._hash(1000) == ti._hash(1000));
-            TEST(ret.ti()._is_equivalent(ti));
-            TEST(inOut.value.ti()._hash(5000) == ti._hash(5000));
-            TEST(inOut.value.ti()._is_equivalent(ti));
-            TEST(out.value.ti()._hash(2000) == ti._hash(2000));
-            TEST(out.value.ti()._is_equivalent(ti));
+            assertTrue(ret.ti()._hash(1000) == ti._hash(1000));
+            assertTrue(ret.ti()._is_equivalent(ti));
+            assertTrue(inOut.value.ti()._hash(5000) == ti._hash(5000));
+            assertTrue(inOut.value.ti()._is_equivalent(ti));
+            assertTrue(out.value.ti()._hash(2000) == ti._hash(2000));
+            assertTrue(out.value.ti()._is_equivalent(ti));
         }
 
         {
@@ -514,34 +517,34 @@
             String[] ret;
             ti.attrStringSequence(seq);
             ret = ti.attrStringSequence();
-            TEST(ret.length == 3);
-            TEST(ret[0].equals("!!!"));
-            TEST(ret[1].equals("@@@"));
-            TEST(ret[2].equals("###"));
+            assertTrue(ret.length == 3);
+            assertTrue(ret[0].equals("!!!"));
+            assertTrue(ret[1].equals("@@@"));
+            assertTrue(ret[2].equals("###"));
 
             StringSequenceHolder inOut = new StringSequenceHolder(new String[2]);
             inOut.value[0] = "%";
             inOut.value[1] = "^^";
             StringSequenceHolder out = new StringSequenceHolder();
             ret = ti.opStringSequence(seq, inOut, out);
-            TEST(ret.length == 5);
-            TEST(ret[0].equals("!!!"));
-            TEST(ret[1].equals("@@@"));
-            TEST(ret[2].equals("###"));
-            TEST(ret[3].equals("%"));
-            TEST(ret[4].equals("^^"));
-            TEST(inOut.value.length == 5);
-            TEST(inOut.value[0].equals("!!!"));
-            TEST(inOut.value[1].equals("@@@"));
-            TEST(inOut.value[2].equals("###"));
-            TEST(inOut.value[3].equals("%"));
-            TEST(inOut.value[4].equals("^^"));
-            TEST(out.value.length == 5);
-            TEST(out.value[0].equals("!!!"));
-            TEST(out.value[1].equals("@@@"));
-            TEST(out.value[2].equals("###"));
-            TEST(out.value[3].equals("%"));
-            TEST(out.value[4].equals("^^"));
+            assertTrue(ret.length == 5);
+            assertTrue(ret[0].equals("!!!"));
+            assertTrue(ret[1].equals("@@@"));
+            assertTrue(ret[2].equals("###"));
+            assertTrue(ret[3].equals("%"));
+            assertTrue(ret[4].equals("^^"));
+            assertTrue(inOut.value.length == 5);
+            assertTrue(inOut.value[0].equals("!!!"));
+            assertTrue(inOut.value[1].equals("@@@"));
+            assertTrue(inOut.value[2].equals("###"));
+            assertTrue(inOut.value[3].equals("%"));
+            assertTrue(inOut.value[4].equals("^^"));
+            assertTrue(out.value.length == 5);
+            assertTrue(out.value[0].equals("!!!"));
+            assertTrue(out.value[1].equals("@@@"));
+            assertTrue(out.value[2].equals("###"));
+            assertTrue(out.value[3].equals("%"));
+            assertTrue(out.value[4].equals("^^"));
         }
 
         {
@@ -557,7 +560,7 @@
             for (i = 0; i < 2; i++)
                 for (j = 0; j < 3; j++)
                     for (k = 0; k < 4; k++) {
-                        TEST(ar[i][j][k] == ret[i][j][k]);
+                        assertTrue(ar[i][j][k] == ret[i][j][k]);
                     }
 
             FixedArrayHolder inOut = new FixedArrayHolder(new short[2][3][4]);
@@ -570,9 +573,9 @@
             for (i = 0; i < 2; i++)
                 for (j = 0; j < 3; j++)
                     for (k = 0; k < 4; k++) {
-                        TEST(ar[i][j][k] == ret[i][j][k]);
-                        TEST(ar[i][j][k] == inOut.value[i][j][k]);
-                        TEST(ar[i][j][k] == out.value[i][j][k]);
+                        assertTrue(ar[i][j][k] == ret[i][j][k]);
+                        assertTrue(ar[i][j][k] == inOut.value[i][j][k]);
+                        assertTrue(ar[i][j][k] == out.value[i][j][k]);
                     }
         }
 
@@ -584,7 +587,7 @@
             ret = ti.attrVariableArray();
             for (i = 0; i < 2; i++)
                 for (j = 0; j < 3; j++) {
-                    TEST((ar[i][j].equals(ret[i][j])));
+                    assertTrue((ar[i][j].equals(ret[i][j])));
                 }
 
             VariableArrayHolder inOut = new VariableArrayHolder(
@@ -596,9 +599,9 @@
             ret = ti.opVariableArray(ar, inOut, out);
             for (i = 0; i < 2; i++)
                 for (j = 0; j < 3; j++) {
-                    TEST(ar[i][j].equals(ret[i][j]));
-                    TEST(ar[i][j].equals(inOut.value[i][j]));
-                    TEST(ar[i][j].equals(out.value[i][j]));
+                    assertTrue(ar[i][j].equals(ret[i][j]));
+                    assertTrue(ar[i][j].equals(inOut.value[i][j]));
+                    assertTrue(ar[i][j].equals(out.value[i][j]));
                 }
         }
 
@@ -635,7 +638,7 @@
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++)
                         for (k = 0; k < 4; k++) {
-                            TEST(seq[l][i][j][k] == ret[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == ret[l][i][j][k]);
                         }
 
             FixedArraySequenceHolder inOut = new FixedArraySequenceHolder(
@@ -650,26 +653,26 @@
 
             ret = ti.opFixedArraySequence(seq, inOut, out);
 
-            TEST(ret.length == 7);
-            TEST(inOut.value.length == 7);
-            TEST(out.value.length == 7);
+            assertTrue(ret.length == 7);
+            assertTrue(inOut.value.length == 7);
+            assertTrue(out.value.length == 7);
 
             for (l = 0; l < 3; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++)
                         for (k = 0; k < 4; k++) {
-                            TEST(seq[l][i][j][k] == ret[l][i][j][k]);
-                            TEST(seq[l][i][j][k] == inOut.value[l][i][j][k]);
-                            TEST(seq[l][i][j][k] == out.value[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == ret[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == inOut.value[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == out.value[l][i][j][k]);
                         }
 
             for (l = 0; l < 4; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++)
                         for (k = 0; k < 4; k++) {
-                            TEST(ret[3 + l][i][j][k] == i + j + k + l);
-                            TEST(inOut.value[3 + l][i][j][k] == i + j + k + l);
-                            TEST(out.value[3 + l][i][j][k] == i + j + k + l);
+                            assertTrue(ret[3 + l][i][j][k] == i + j + k + l);
+                            assertTrue(inOut.value[3 + l][i][j][k] == i + j + k + l);
+                            assertTrue(out.value[3 + l][i][j][k] == i + j + k + l);
                         }
         }
 
@@ -690,7 +693,7 @@
             for (l = 0; l < 2; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++) {
-                        TEST(seq[l][i][j].equals(ret[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(ret[l][i][j]));
                     }
 
             VariableArraySequenceHolder inOut = new VariableArraySequenceHolder(
@@ -704,24 +707,24 @@
 
             ret = ti.opVariableArraySequence(seq, inOut, out);
 
-            TEST(ret.length == 6);
-            TEST(inOut.value.length == 6);
-            TEST(out.value.length == 6);
+            assertTrue(ret.length == 6);
+            assertTrue(inOut.value.length == 6);
+            assertTrue(out.value.length == 6);
 
             for (l = 0; l < 2; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++) {
-                        TEST(seq[l][i][j].equals(ret[l][i][j]));
-                        TEST(seq[l][i][j].equals(inOut.value[l][i][j]));
-                        TEST(seq[l][i][j].equals(out.value[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(ret[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(inOut.value[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(out.value[l][i][j]));
                     }
 
             for (l = 0; l < 4; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++) {
-                        TEST(ret[2 + l][i][j].equals("***"));
-                        TEST(inOut.value[2 + l][i][j].equals("***"));
-                        TEST(out.value[2 + l][i][j].equals("***"));
+                        assertTrue(ret[2 + l][i][j].equals("***"));
+                        assertTrue(inOut.value[2 + l][i][j].equals("***"));
+                        assertTrue(out.value[2 + l][i][j].equals("***"));
                     }
         }
 
@@ -758,7 +761,7 @@
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++)
                         for (k = 0; k < 4; k++) {
-                            TEST(seq[l][i][j][k] == ret[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == ret[l][i][j][k]);
                         }
 
             FixedArrayBoundSequenceHolder inOut = new FixedArrayBoundSequenceHolder(
@@ -773,26 +776,26 @@
 
             ret = ti.opFixedArrayBoundSequence(seq, inOut, out);
 
-            TEST(ret.length == 7);
-            TEST(inOut.value.length == 7);
-            TEST(out.value.length == 7);
+            assertTrue(ret.length == 7);
+            assertTrue(inOut.value.length == 7);
+            assertTrue(out.value.length == 7);
 
             for (l = 0; l < 3; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++)
                         for (k = 0; k < 4; k++) {
-                            TEST(seq[l][i][j][k] == ret[l][i][j][k]);
-                            TEST(seq[l][i][j][k] == inOut.value[l][i][j][k]);
-                            TEST(seq[l][i][j][k] == out.value[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == ret[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == inOut.value[l][i][j][k]);
+                            assertTrue(seq[l][i][j][k] == out.value[l][i][j][k]);
                         }
 
             for (l = 0; l < 4; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++)
                         for (k = 0; k < 4; k++) {
-                            TEST(ret[3 + l][i][j][k] == i + j + k + l);
-                            TEST(inOut.value[3 + l][i][j][k] == i + j + k + l);
-                            TEST(out.value[3 + l][i][j][k] == i + j + k + l);
+                            assertTrue(ret[3 + l][i][j][k] == i + j + k + l);
+                            assertTrue(inOut.value[3 + l][i][j][k] == i + j + k + l);
+                            assertTrue(out.value[3 + l][i][j][k] == i + j + k + l);
                         }
         }
 
@@ -813,7 +816,7 @@
             for (l = 0; l < 2; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++) {
-                        TEST(seq[l][i][j].equals(ret[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(ret[l][i][j]));
                     }
 
             VariableArrayBoundSequenceHolder inOut = new VariableArrayBoundSequenceHolder(
@@ -827,31 +830,31 @@
 
             ret = ti.opVariableArrayBoundSequence(seq, inOut, out);
 
-            TEST(ret.length == 6);
-            TEST(inOut.value.length == 6);
-            TEST(out.value.length == 6);
+            assertTrue(ret.length == 6);
+            assertTrue(inOut.value.length == 6);
+            assertTrue(out.value.length == 6);
 
             for (l = 0; l < 2; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++) {
-                        TEST(seq[l][i][j].equals(ret[l][i][j]));
-                        TEST(seq[l][i][j].equals(inOut.value[l][i][j]));
-                        TEST(seq[l][i][j].equals(out.value[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(ret[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(inOut.value[l][i][j]));
+                        assertTrue(seq[l][i][j].equals(out.value[l][i][j]));
                     }
 
             for (l = 0; l < 4; l++)
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++) {
-                        TEST(ret[2 + l][i][j].equals("***"));
-                        TEST(inOut.value[2 + l][i][j].equals("***"));
-                        TEST(out.value[2 + l][i][j].equals("***"));
+                        assertTrue(ret[2 + l][i][j].equals("***"));
+                        assertTrue(inOut.value[2 + l][i][j].equals("***"));
+                        assertTrue(out.value[2 + l][i][j].equals("***"));
                     }
         }
 
         {
             try {
                 ti.opVoidEx();
-                TEST(false);
+                assertTrue(false);
             } catch (ExVoid ex) {
             }
         }
@@ -862,9 +865,9 @@
 
             try {
                 ti.opShortEx((short) 10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExShort ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -874,9 +877,9 @@
 
             try {
                 ti.opLongEx(10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExLong ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -886,9 +889,9 @@
 
             try {
                 ti.opUShortEx((short) 10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExUShort ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -898,9 +901,9 @@
 
             try {
                 ti.opULongEx(10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExULong ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -910,9 +913,9 @@
 
             try {
                 ti.opFloatEx(10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExFloat ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -922,9 +925,9 @@
 
             try {
                 ti.opDoubleEx(10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExDouble ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -934,9 +937,9 @@
 
             try {
                 ti.opBooleanEx(true, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExBoolean ex) {
-                TEST(ex.value == true);
+                assertTrue(ex.value == true);
             }
         }
 
@@ -946,9 +949,9 @@
 
             try {
                 ti.opCharEx('a', inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExChar ex) {
-                TEST(ex.value == 'b');
+                assertTrue(ex.value == 'b');
             }
         }
 
@@ -958,9 +961,9 @@
 
             try {
                 ti.opOctetEx((byte) 10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExOctet ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -970,9 +973,9 @@
 
             try {
                 ti.opStringEx("Hello, ", inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExString ex) {
-                TEST(ex.value.equals("Hello, world!"));
+                assertTrue(ex.value.equals("Hello, world!"));
             }
         }
 
@@ -986,11 +989,11 @@
 
             try {
                 ti.opAnyEx(any, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExAny ex) {
                 VariableStruct vStructRet;
                 vStructRet = VariableStructHelper.extract(any);
-                TEST(vStructRet.s.equals("xyz"));
+                assertTrue(vStructRet.s.equals("xyz"));
             }
         }
 
@@ -1001,9 +1004,9 @@
 
             try {
                 ti.opTestEnumEx(TestEnum.TestEnum3, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExTestEnum ex) {
-                TEST(ex.value == TestEnum.TestEnum3);
+                assertTrue(ex.value == TestEnum.TestEnum3);
             }
         }
 
@@ -1014,10 +1017,10 @@
 
             try {
                 ti.opIntfEx(ti, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ORBTest_Basic.ExIntf ex) {
-                TEST(ex.value._hash(1000) == ti._hash(1000));
-                TEST(ex.value._is_equivalent(ti));
+                assertTrue(ex.value._hash(1000) == ti._hash(1000));
+                assertTrue(ex.value._is_equivalent(ti));
             }
         }
 
@@ -1032,10 +1035,10 @@
 
             try {
                 ti.opFixedStructEx(st, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExFixedStruct ex) {
-                TEST(ex.value.s == st.s);
-                TEST(ex.value.l == st.l);
+                assertTrue(ex.value.s == st.s);
+                assertTrue(ex.value.l == st.l);
             }
         }
 
@@ -1049,9 +1052,9 @@
 
             try {
                 ti.opVariableStructEx(st, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExVariableStruct ex) {
-                TEST(ex.value.s.equals(st.s));
+                assertTrue(ex.value.s.equals(st.s));
             }
         }
 
@@ -1064,10 +1067,10 @@
 
             try {
                 ti.opFixedUnionEx(un, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExFixedUnion ex) {
-                TEST(ex.value.discriminator() == 999);
-                TEST(ex.value.b() == true);
+                assertTrue(ex.value.discriminator() == 999);
+                assertTrue(ex.value.b() == true);
             }
         }
 
@@ -1083,10 +1086,10 @@
 
             try {
                 ti.opVariableUnionEx(un, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExVariableUnion ex) {
-                TEST(ex.value.ti()._hash(2000) == ti._hash(2000));
-                TEST(ex.value.ti()._is_equivalent(ti));
+                assertTrue(ex.value.ti()._hash(2000) == ti._hash(2000));
+                assertTrue(ex.value.ti()._is_equivalent(ti));
             }
         }
 
@@ -1103,14 +1106,14 @@
 
             try {
                 ti.opStringSequenceEx(seq, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExStringSequence ex) {
-                TEST(ex.value.length == 5);
-                TEST(ex.value[0].equals("!!!"));
-                TEST(ex.value[1].equals("@@@"));
-                TEST(ex.value[2].equals("###"));
-                TEST(ex.value[3].equals("%"));
-                TEST(ex.value[4].equals("^^"));
+                assertTrue(ex.value.length == 5);
+                assertTrue(ex.value[0].equals("!!!"));
+                assertTrue(ex.value[1].equals("@@@"));
+                assertTrue(ex.value[2].equals("###"));
+                assertTrue(ex.value[3].equals("%"));
+                assertTrue(ex.value[4].equals("^^"));
             }
         }
 
@@ -1131,12 +1134,12 @@
 
             try {
                 ti.opFixedArrayEx(ar, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExFixedArray ex) {
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++)
                         for (k = 0; k < 4; k++) {
-                            TEST(ar[i][j][k] == ex.value[i][j][k]);
+                            assertTrue(ar[i][j][k] == ex.value[i][j][k]);
                         }
             }
         }
@@ -1154,11 +1157,11 @@
 
             try {
                 ti.opVariableArrayEx(ar, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExVariableArray ex) {
                 for (i = 0; i < 2; i++)
                     for (j = 0; j < 3; j++) {
-                        TEST(ar[i][j].equals(ex.value[i][j]));
+                        assertTrue(ar[i][j].equals(ex.value[i][j]));
                     }
             }
         }
@@ -1200,22 +1203,22 @@
 
             try {
                 ret = ti.opFixedArraySequenceEx(seq, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExFixedArraySequence ex) {
-                TEST(ex.value.length == 7);
+                assertTrue(ex.value.length == 7);
 
                 for (l = 0; l < 3; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++)
                             for (k = 0; k < 4; k++) {
-                                TEST(seq[l][i][j][k] == ex.value[l][i][j][k]);
+                                assertTrue(seq[l][i][j][k] == ex.value[l][i][j][k]);
                             }
 
                 for (l = 0; l < 4; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++)
                             for (k = 0; k < 4; k++) {
-                                TEST(ex.value[3 + l][i][j][k] == i + j + k + l);
+                                assertTrue(ex.value[3 + l][i][j][k] == i + j + k + l);
                             }
             }
         }
@@ -1241,20 +1244,20 @@
 
             try {
                 ret = ti.opVariableArraySequenceEx(seq, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExVariableArraySequence ex) {
-                TEST(ex.value.length == 6);
+                assertTrue(ex.value.length == 6);
 
                 for (l = 0; l < 2; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++) {
-                            TEST(seq[l][i][j].equals(ex.value[l][i][j]));
+                            assertTrue(seq[l][i][j].equals(ex.value[l][i][j]));
                         }
 
                 for (l = 0; l < 4; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++) {
-                            TEST(ex.value[2 + l][i][j].equals("***"));
+                            assertTrue(ex.value[2 + l][i][j].equals("***"));
                         }
 
             }
@@ -1297,21 +1300,21 @@
 
             try {
                 ret = ti.opFixedArrayBoundSequenceEx(seq, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExFixedArrayBoundSequence ex) {
-                TEST(ex.value.length == 7);
+                assertTrue(ex.value.length == 7);
 
                 for (l = 0; l < 3; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++)
                             for (k = 0; k < 4; k++)
-                                TEST(seq[l][i][j][k] == ex.value[l][i][j][k]);
+								assertTrue(seq[l][i][j][k] == ex.value[l][i][j][k]);
 
                 for (l = 0; l < 4; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++)
                             for (k = 0; k < 4; k++)
-                                TEST(ex.value[3 + l][i][j][k] == i + j + k + l);
+								assertTrue(ex.value[3 + l][i][j][k] == i + j + k + l);
             }
         }
 
@@ -1336,33 +1339,33 @@
 
             try {
                 ret = ti.opVariableArrayBoundSequenceEx(seq, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ExVariableArrayBoundSequence ex) {
-                TEST(ex.value.length == 6);
+                assertTrue(ex.value.length == 6);
 
                 for (l = 0; l < 2; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++)
-                            TEST(seq[l][i][j].equals(ex.value[l][i][j]));
+							assertTrue(seq[l][i][j].equals(ex.value[l][i][j]));
 
                 for (l = 0; l < 4; l++)
                     for (i = 0; i < 2; i++)
                         for (j = 0; j < 3; j++)
-                            TEST(ex.value[2 + l][i][j].equals("***"));
+							assertTrue(ex.value[2 + l][i][j].equals("***"));
             }
         }
         {
             try {
                 ti.opExRecursiveStruct();
-                TEST(false);
+                assertTrue(false);
             } catch (ORBTest_Basic.ExRecursiveStruct ex) {
-                TEST(ex.us == 1);
-                TEST(ex.rs.s.equals("test"));
-                TEST(ex.rs.i == 2);
-                TEST(ex.rs.rs.length == 1);
-                TEST(ex.rs.rs[0].s.equals("ORBTest_Basic_RecursiveStruct"));
-                TEST(ex.rs.rs[0].i == 111);
-                TEST(ex.rs.rs[0].rs.length == 0);
+                assertTrue(ex.us == 1);
+                assertTrue(ex.rs.s.equals("test"));
+                assertTrue(ex.rs.i == 2);
+                assertTrue(ex.rs.rs.length == 1);
+                assertTrue(ex.rs.rs[0].s.equals("ORBTest_Basic_RecursiveStruct"));
+                assertTrue(ex.rs.rs[0].i == 111);
+                assertTrue(ex.rs.rs[0].rs.length == 0);
             }
         }
     }
@@ -1399,7 +1402,7 @@
             if (request.env().exception() != null)
                 throw (SystemException) request.env().exception();
             ret = request.return_value().extract_short();
-            TEST(ret == (short) -32768);
+            assertTrue(ret == (short) -32768);
 
             request = ti._request("_set_attrShort");
             request.add_in_arg().insert_short((short) 32767);
@@ -1412,7 +1415,7 @@
             if (request.env().exception() != null)
                 throw (SystemException) request.env().exception();
             ret = request.return_value().extract_short();
-            TEST(ret == (short) 32767);
+            assertTrue(ret == (short) 32767);
 
             request = ti._request("opShort");
             request.add_in_arg().insert_short((short) 10);
@@ -1427,9 +1430,9 @@
             inOut = inOutAny.extract_short();
             out = outAny.extract_short();
             ret = request.return_value().extract_short();
-            TEST(ret == 30);
-            TEST(inOut == 30);
-            TEST(out == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut == 30);
+            assertTrue(out == 30);
         }
 
         {
@@ -1450,7 +1453,7 @@
             if (request.env().exception() != null)
                 throw (SystemException) request.env().exception();
             ret = request.return_value().extract_double();
-            TEST(ret == 1.7976931348623157E+308);
+            assertTrue(ret == 1.7976931348623157E+308);
 
             request = ti._request("_set_attrDouble");
             request.add_in_arg().insert_double(2.2250738585072014E-308);
@@ -1463,7 +1466,7 @@
             if (request.env().exception() != null)
                 throw (SystemException) request.env().exception();
             ret = request.return_value().extract_double();
-            TEST(ret == 2.2250738585072014E-308);
+            assertTrue(ret == 2.2250738585072014E-308);
 
             request = ti._request("opDouble");
             request.add_in_arg().insert_double(10.0);
@@ -1478,9 +1481,9 @@
             inOut = inOutAny.extract_double();
             out = outAny.extract_double();
             ret = request.return_value().extract_double();
-            TEST(ret == 30);
-            TEST(inOut == 30);
-            TEST(out == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut == 30);
+            assertTrue(out == 30);
         }
 
         {
@@ -1501,7 +1504,7 @@
             if (request.env().exception() != null)
                 throw (SystemException) request.env().exception();
             ret = request.return_value().extract_string();
-            TEST(ret.equals("Hello"));
+            assertTrue(ret.equals("Hello"));
 
             request = ti._request("opString");
             request.add_in_arg().insert_string("Hello, ");
@@ -1516,8 +1519,8 @@
             inOut = inOutAny.extract_string();
             out = outAny.extract_string();
             ret = request.return_value().extract_string();
-            TEST(ret.equals("Hello, world!"));
-            TEST(out.equals("Hello, world!"));
+            assertTrue(ret.equals("Hello, world!"));
+            assertTrue(out.equals("Hello, world!"));
         }
 
         {
@@ -1540,10 +1543,10 @@
             if (request.env().exception() != null)
                 throw (SystemException) request.env().exception();
             ret = StringSequenceHelper.extract(request.return_value());
-            TEST(ret.length == 3);
-            TEST(ret[0].equals("!!!"));
-            TEST(ret[1].equals("@@@"));
-            TEST(ret[2].equals("###"));
+            assertTrue(ret.length == 3);
+            assertTrue(ret[0].equals("!!!"));
+            assertTrue(ret[1].equals("@@@"));
+            assertTrue(ret[2].equals("###"));
 
             inOut = new String[2];
             inOut[0] = "%";
@@ -1561,24 +1564,24 @@
             ret = StringSequenceHelper.extract(request.return_value());
             inOut = StringSequenceHelper.extract(inOutAny);
             out = StringSequenceHelper.extract(outAny);
-            TEST(ret.length == 5);
-            TEST(ret[0].equals("!!!"));
-            TEST(ret[1].equals("@@@"));
-            TEST(ret[2].equals("###"));
-            TEST(ret[3].equals("%"));
-            TEST(ret[4].equals("^^"));
-            TEST(inOut.length == 5);
-            TEST(inOut[0].equals("!!!"));
-            TEST(inOut[1].equals("@@@"));
-            TEST(inOut[2].equals("###"));
-            TEST(inOut[3].equals("%"));
-            TEST(inOut[4].equals("^^"));
-            TEST(out.length == 5);
-            TEST(out[0].equals("!!!"));
-            TEST(out[1].equals("@@@"));
-            TEST(out[2].equals("###"));
-            TEST(out[3].equals("%"));
-            TEST(out[4].equals("^^"));
+            assertTrue(ret.length == 5);
+            assertTrue(ret[0].equals("!!!"));
+            assertTrue(ret[1].equals("@@@"));
+            assertTrue(ret[2].equals("###"));
+            assertTrue(ret[3].equals("%"));
+            assertTrue(ret[4].equals("^^"));
+            assertTrue(inOut.length == 5);
+            assertTrue(inOut[0].equals("!!!"));
+            assertTrue(inOut[1].equals("@@@"));
+            assertTrue(inOut[2].equals("###"));
+            assertTrue(inOut[3].equals("%"));
+            assertTrue(inOut[4].equals("^^"));
+            assertTrue(out.length == 5);
+            assertTrue(out[0].equals("!!!"));
+            assertTrue(out[1].equals("@@@"));
+            assertTrue(out[2].equals("###"));
+            assertTrue(out[3].equals("%"));
+            assertTrue(out[4].equals("^^"));
         }
 
         {
@@ -1599,10 +1602,10 @@
             try {
                 request.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
             ret = request.return_value().extract_char();
-            TEST(ret == 'a');
+            assertTrue(ret == 'a');
 
             request = ti._request("opChar");
             request.add_in_arg().insert_char('a');
@@ -1615,14 +1618,14 @@
             try {
                 request.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
             inOut = inOutAny.extract_char();
             out = outAny.extract_char();
             ret = request.return_value().extract_char();
-            TEST(ret == 'b');
-            TEST(inOut == 'b');
-            TEST(out == 'b');
+            assertTrue(ret == 'b');
+            assertTrue(inOut == 'b');
+            assertTrue(out == 'b');
         }
 
         {
@@ -1647,12 +1650,12 @@
             try {
                 request.get_response();
             } catch (org.omg.CORBA.WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
             ret = VariableArrayHelper.extract(request.return_value());
             for (i = 0; i < 2; i++)
                 for (j = 0; j < 3; j++) {
-                    TEST(ar[i][j].equals(ret[i][j]));
+                    assertTrue(ar[i][j].equals(ret[i][j]));
                 }
 
             String[][] ar2 = { { "abc", "abc", "abc" }, { "abc", "abc", "abc" } };
@@ -1670,33 +1673,33 @@
             try {
                 request.get_response();
             } catch (org.omg.CORBA.WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
             ret = VariableArrayHelper.extract(request.return_value());
             inOut = VariableArrayHelper.extract(inOutAny);
             out = VariableArrayHelper.extract(outAny);
             for (i = 0; i < 2; i++)
                 for (j = 0; j < 3; j++) {
-                    TEST(ar[i][j].equals(ret[i][j]));
-                    TEST(ar[i][j].equals(inOut[i][j]));
-                    TEST(ar[i][j].equals(out[i][j]));
+                    assertTrue(ar[i][j].equals(ret[i][j]));
+                    assertTrue(ar[i][j].equals(inOut[i][j]));
+                    assertTrue(ar[i][j].equals(out[i][j]));
                 }
         }
 
         try {
             m_orb.poll_next_response();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
             // Expected
         }
 
         try {
             m_orb.get_next_response();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
             // Expected
         } catch (org.omg.CORBA.WrongTransaction ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         {
@@ -1709,35 +1712,35 @@
 
             try {
                 request.invoke();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.send_oneway();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.send_deferred();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.poll_response();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.get_response();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             } catch (org.omg.CORBA.WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
         }
 
@@ -1748,36 +1751,36 @@
 
             try {
                 request.poll_response();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.get_response();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             } catch (org.omg.CORBA.WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             request.send_deferred();
 
             try {
                 request.invoke();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.send_oneway();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.send_deferred();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
@@ -1785,22 +1788,22 @@
             try {
                 request.get_response();
             } catch (org.omg.CORBA.WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 request.poll_response();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             }
             try {
                 request.get_response();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER ex) {
                 // Expected
             } catch (org.omg.CORBA.WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
         }
 
@@ -1829,11 +1832,11 @@
                 try {
                     request = m_orb.get_next_response();
                 } catch (org.omg.CORBA.WrongTransaction ex) {
-                    TEST(false);
+                    assertTrue(false);
                 }
 
                 short ret = request.return_value().extract_ushort();
-                TEST(ret == (short) 1234);
+                assertTrue(ret == (short) 1234);
             }
         }
 
@@ -1875,36 +1878,36 @@
             try {
                 request5.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
             inOut = inOutAny.extract_float();
             out = outAny.extract_float();
             ret = request5.return_value().extract_float();
-            TEST(ret == 30);
-            TEST(inOut == 30);
-            TEST(out == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut == 30);
+            assertTrue(out == 30);
 
             try {
                 request2.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
             ret = request2.return_value().extract_float();
-            TEST(ret == 1);
+            assertTrue(ret == 1);
 
             try {
                 request4.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
             ret = request4.return_value().extract_float();
-            TEST(ret == -1);
+            assertTrue(ret == -1);
 
             try {
                 request1.get_response();
                 request3.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
         }
 
@@ -1918,7 +1921,7 @@
                 request.invoke();
                 ex = request.env().exception();
                 UNKNOWN dummy = (UNKNOWN) ex;
-                TEST(dummy != null);
+                assertTrue(dummy != null);
             } catch (UNKNOWN e) {
                 // expected in JDK 1.2
             }
@@ -1929,7 +1932,7 @@
             ex = request.env().exception();
             UnknownUserException uex;
             uex = (UnknownUserException) ex;
-            TEST(uex != null);
+            assertTrue(uex != null);
             ExVoid iex;
             iex = ExVoidHelper.extract(uex.except);
         }
@@ -1947,10 +1950,10 @@
             Exception ex = request.env().exception();
             UnknownUserException uex;
             uex = (UnknownUserException) ex;
-            TEST(uex != null);
+            assertTrue(uex != null);
             ExShort iex;
             iex = ExShortHelper.extract(uex.except);
-            TEST(iex.value == 30);
+            assertTrue(iex.value == 30);
         }
 
         {
@@ -1966,10 +1969,10 @@
             Exception ex = request.env().exception();
             UnknownUserException uex;
             uex = (UnknownUserException) ex;
-            TEST(uex != null);
+            assertTrue(uex != null);
             ExDouble iex;
             iex = ExDoubleHelper.extract(uex.except);
-            TEST(iex.value == 30);
+            assertTrue(iex.value == 30);
         }
 
         {
@@ -1992,15 +1995,15 @@
             Exception ex = request.env().exception();
             UnknownUserException uex;
             uex = (UnknownUserException) ex;
-            TEST(uex != null);
+            assertTrue(uex != null);
             ExStringSequence iex;
             iex = ExStringSequenceHelper.extract(uex.except);
-            TEST(iex.value.length == 5);
-            TEST(iex.value[0].equals("!!!"));
-            TEST(iex.value[1].equals("@@@"));
-            TEST(iex.value[2].equals("###"));
-            TEST(iex.value[3].equals("%"));
-            TEST(iex.value[4].equals("^^"));
+            assertTrue(iex.value.length == 5);
+            assertTrue(iex.value[0].equals("!!!"));
+            assertTrue(iex.value[1].equals("@@@"));
+            assertTrue(iex.value[2].equals("###"));
+            assertTrue(iex.value[3].equals("%"));
+            assertTrue(iex.value[4].equals("^^"));
         }
 
         {
@@ -2011,17 +2014,17 @@
             Exception ex = request.env().exception();
             UnknownUserException uex;
             uex = (UnknownUserException) ex;
-            TEST(uex != null);
+            assertTrue(uex != null);
             ORBTest_Basic.ExRecursiveStruct iex;
             iex = ORBTest_Basic.ExRecursiveStructHelper.extract(uex.except);
 
-            TEST(iex.us == 1);
-            TEST(iex.rs.s.equals("test"));
-            TEST(iex.rs.i == 2);
-            TEST(iex.rs.rs.length == 1);
-            TEST(iex.rs.rs[0].s.equals("ORBTest_Basic_RecursiveStruct"));
-            TEST(iex.rs.rs[0].i == 111);
-            TEST(iex.rs.rs[0].rs.length == 0);
+            assertTrue(iex.us == 1);
+            assertTrue(iex.rs.s.equals("test"));
+            assertTrue(iex.rs.i == 2);
+            assertTrue(iex.rs.rs.length == 1);
+            assertTrue(iex.rs.rs[0].s.equals("ORBTest_Basic_RecursiveStruct"));
+            assertTrue(iex.rs.rs[0].i == 111);
+            assertTrue(iex.rs.rs[0].rs.length == 0);
         }
     }
 }
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectContext.java b/yoko-core/src/test/java/ORBTest/TestObjectContext.java
index 84aaeb1..b26a093 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectContext.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectContext.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectContext extends test.common.TestBase implements
@@ -59,7 +61,7 @@
 
             try {
                 seq = ti.opContext("*", ctx);
-                TEST(false);
+                assertTrue(false);
             } catch (BAD_CONTEXT ex) {
                 // Expected
             }
@@ -97,35 +99,35 @@
             ctx.set_one_value("YYY", any);
 
             seq = ti.opContext("*", ctx);
-            TEST(seq.length == 3 * 2);
+            assertTrue(seq.length == 3 * 2);
             for (i = 0; i < seq.length; i += 2) {
                 if (seq[i].equals("A"))
-                    TEST(seq[i + 1].equals("A1"));
+					assertTrue(seq[i + 1].equals("A1"));
 
                 if (seq[i].equals("AAA"))
-                    TEST(seq[i + 1].equals("A2"));
+					assertTrue(seq[i + 1].equals("A2"));
 
                 if (seq[i].equals("X"))
-                    TEST(seq[i + 1].equals("X1"));
+					assertTrue(seq[i + 1].equals("X1"));
             }
 
             seq = ti.opContext("A*", ctx);
-            TEST(seq.length == 2 * 2);
+            assertTrue(seq.length == 2 * 2);
             for (i = 0; i < seq.length; i += 2) {
                 if (seq[i].equals("A"))
-                    TEST(seq[i + 1].equals("A1"));
+					assertTrue(seq[i + 1].equals("A1"));
 
                 if (seq[i].equals("AAA"))
-                    TEST(seq[i + 1].equals("A2"));
+					assertTrue(seq[i + 1].equals("A2"));
             }
 
             seq = ti.opContext("AA*", ctx);
-            TEST(seq.length == 1 * 2);
-            TEST(seq[0].equals("AAA") && seq[1].equals("A2"));
+            assertTrue(seq.length == 1 * 2);
+            assertTrue(seq[0].equals("AAA") && seq[1].equals("A2"));
 
             seq = ti.opContext("A", ctx);
-            TEST(seq.length == 1 * 2);
-            TEST(seq[0].equals("A") && seq[1].equals("A1"));
+            assertTrue(seq.length == 1 * 2);
+            assertTrue(seq[0].equals("A") && seq[1].equals("A1"));
 
             ctx2 = ctx.create_child("child");
 
@@ -139,22 +141,22 @@
             ctx2.set_one_value("X", any);
 
             seq = ti.opContext("*", ctx2);
-            TEST(seq.length == 5 * 2);
+            assertTrue(seq.length == 5 * 2);
             for (i = 0; i < seq.length; i += 2) {
                 if (seq[i].equals("A"))
-                    TEST(seq[i + 1].equals("A1"));
+					assertTrue(seq[i + 1].equals("A1"));
 
                 if (seq[i].equals("AAA"))
-                    TEST(seq[i + 1].equals("A2"));
+					assertTrue(seq[i + 1].equals("A2"));
 
                 if (seq[i].equals("C"))
-                    TEST(seq[i + 1].equals("C1"));
+					assertTrue(seq[i + 1].equals("C1"));
 
                 if (seq[i].equals("CCC"))
-                    TEST(seq[i + 1].equals("C2"));
+					assertTrue(seq[i + 1].equals("C2"));
 
                 if (seq[i].equals("X"))
-                    TEST(seq[i + 1].equals("X1-1"));
+					assertTrue(seq[i + 1].equals("X1-1"));
             }
         }
     }
@@ -182,7 +184,7 @@
             try {
                 request.invoke();
                 Exception ex = request.env().exception();
-                TEST(ex != null);
+                assertTrue(ex != null);
                 BAD_CONTEXT bex = (BAD_CONTEXT) ex;
             } catch (BAD_CONTEXT ex) {
                 // Expected (if yoko.m_orb.raise_dii_exceptions = true)
@@ -236,16 +238,16 @@
             seq = (ORBTest_Context.StringSequenceHelper.extract(request
                     .return_value()));
 
-            TEST(seq.length == 3 * 2);
+            assertTrue(seq.length == 3 * 2);
             for (i = 0; i < seq.length; i += 2) {
                 if (seq[i].equals("A"))
-                    TEST(seq[i + 1].equals("A1"));
+					assertTrue(seq[i + 1].equals("A1"));
 
                 if (seq[i].equals("AAA"))
-                    TEST(seq[i + 1].equals("A2"));
+					assertTrue(seq[i + 1].equals("A2"));
 
                 if (seq[i].equals("X"))
-                    TEST(seq[i + 1].equals("X1"));
+					assertTrue(seq[i + 1].equals("X1"));
             }
 
             request = ti._request("opContext");
@@ -262,13 +264,13 @@
             seq = (ORBTest_Context.StringSequenceHelper.extract(request
                     .return_value()));
 
-            TEST(seq.length == 2 * 2);
+            assertTrue(seq.length == 2 * 2);
             for (i = 0; i < seq.length; i += 2) {
                 if (seq[i].equals("A"))
-                    TEST(seq[i + 1].equals("A1"));
+					assertTrue(seq[i + 1].equals("A1"));
 
                 if (seq[i].equals("AAA"))
-                    TEST(seq[i + 1].equals("A2"));
+					assertTrue(seq[i + 1].equals("A2"));
             }
 
             request = ti._request("opContext");
@@ -285,8 +287,8 @@
             seq = (ORBTest_Context.StringSequenceHelper.extract(request
                     .return_value()));
 
-            TEST(seq.length == 1 * 2);
-            TEST(seq[0].equals("AAA") && seq[1].equals("A2"));
+            assertTrue(seq.length == 1 * 2);
+            assertTrue(seq[0].equals("AAA") && seq[1].equals("A2"));
 
             request = ti._request("opContext");
             request.contexts().add("A*");
@@ -302,8 +304,8 @@
             seq = (ORBTest_Context.StringSequenceHelper.extract(request
                     .return_value()));
 
-            TEST(seq.length == 1 * 2);
-            TEST(seq[0].equals("A") && seq[1].equals("A1"));
+            assertTrue(seq.length == 1 * 2);
+            assertTrue(seq[0].equals("A") && seq[1].equals("A1"));
         }
     }
 }
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectExceptions.java b/yoko-core/src/test/java/ORBTest/TestObjectExceptions.java
index fea6b5a..05cf6f5 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectExceptions.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectExceptions.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectExceptions extends test.common.TestBase implements
@@ -51,170 +53,170 @@
 
         try {
             ti.op_UNKNOWN_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (UNKNOWN ex) {
-            TEST(ex.minor == 1);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 1);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_BAD_PARAM_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (BAD_PARAM ex) {
-            TEST(ex.minor == 2);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 2);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_NO_MEMORY_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_MEMORY ex) {
-            TEST(ex.minor == 3);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 3);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_IMP_LIMIT_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (IMP_LIMIT ex) {
-            TEST(ex.minor == 4);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 4);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_COMM_FAILURE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (COMM_FAILURE ex) {
-            TEST(ex.minor == 5);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 5);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_INV_OBJREF_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INV_OBJREF ex) {
-            TEST(ex.minor == 6);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 6);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_NO_PERMISSION_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_PERMISSION ex) {
-            TEST(ex.minor == 7);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 7);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_INTERNAL_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INTERNAL ex) {
-            TEST(ex.minor == 8);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 8);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_MARSHAL_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (MARSHAL ex) {
-            TEST(ex.minor == 9);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 9);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_INITIALIZE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INITIALIZE ex) {
-            TEST(ex.minor == 10);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 10);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_NO_IMPLEMENT_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_IMPLEMENT ex) {
-            TEST(ex.minor == 11);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 11);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_BAD_TYPECODE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (BAD_TYPECODE ex) {
-            TEST(ex.minor == 12);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 12);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_BAD_OPERATION_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (BAD_OPERATION ex) {
-            TEST(ex.minor == 13);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 13);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_NO_RESOURCES_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_RESOURCES ex) {
-            TEST(ex.minor == 14);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 14);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_NO_RESPONSE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_RESPONSE ex) {
-            TEST(ex.minor == 15);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 15);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_BAD_INV_ORDER_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (BAD_INV_ORDER ex) {
-            TEST(ex.minor == 17);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 17);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_TRANSIENT_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (TRANSIENT ex) {
-            TEST(ex.minor == 18);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 18);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_OBJ_ADAPTER_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (OBJ_ADAPTER ex) {
-            TEST(ex.minor == 24);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 24);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_DATA_CONVERSION_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (DATA_CONVERSION ex) {
-            TEST(ex.minor == 25);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 25);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_OBJECT_NOT_EXIST_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (OBJECT_NOT_EXIST ex) {
-            TEST(ex.minor == 26);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 26);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_INV_POLICY_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INV_POLICY ex) {
-            TEST(ex.minor == 30);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 30);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
     }
 
@@ -227,12 +229,12 @@
             request = ti._request("op_BAD_PARAM_Ex");
             request.invoke();
             Exception ex = request.env().exception();
-            TEST(ex != null);
+            assertTrue(ex != null);
             BAD_PARAM bp = (BAD_PARAM) ex;
             throw bp;
         } catch (BAD_PARAM ex) {
-            TEST(ex.minor == 2);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 2);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
     }
 }
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_0.java b/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_0.java
index 54fc53b..f472164 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_0.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_0.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectExceptionsExt_2_0 extends test.common.TestBase implements
@@ -52,74 +54,74 @@
 
         try {
             ti.op_PERSIST_STORE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (PERSIST_STORE ex) {
-            TEST(ex.minor == 16);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 16);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_FREE_MEM_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (FREE_MEM ex) {
-            TEST(ex.minor == 19);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 19);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_INV_IDENT_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INV_IDENT ex) {
-            TEST(ex.minor == 20);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 20);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_INV_FLAG_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INV_FLAG ex) {
-            TEST(ex.minor == 21);
-            TEST(ex.completed == CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(ex.minor == 21);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_MAYBE);
         }
 
         try {
             ti.op_INTF_REPOS_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INTF_REPOS ex) {
-            TEST(ex.minor == 22);
-            TEST(ex.completed == CompletionStatus.COMPLETED_YES);
+            assertTrue(ex.minor == 22);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_YES);
         }
 
         try {
             ti.op_BAD_CONTEXT_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (BAD_CONTEXT ex) {
-            TEST(ex.minor == 23);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 23);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_TRANSACTION_REQUIRED_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (TRANSACTION_REQUIRED ex) {
-            TEST(ex.minor == 27);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 27);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_TRANSACTION_ROLLEDBACK_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (TRANSACTION_ROLLEDBACK ex) {
-            TEST(ex.minor == 28);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 28);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_INVALID_TRANSACTION_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (INVALID_TRANSACTION ex) {
-            TEST(ex.minor == 29);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 29);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
     }
 
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_3.java b/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_3.java
index 843acdb..c256df7 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_3.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectExceptionsExt_2_3.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectExceptionsExt_2_3 extends test.common.TestBase implements
@@ -52,50 +54,50 @@
 
         try {
             ti.op_CODESET_INCOMPATIBLE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (CODESET_INCOMPATIBLE ex) {
-            TEST(ex.minor == 31);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 31);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_REBIND_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (REBIND ex) {
-            TEST(ex.minor == 32);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 32);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_TIMEOUT_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (TIMEOUT ex) {
-            TEST(ex.minor == 33);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 33);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_TRANSACTION_UNAVAILABLE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (TRANSACTION_UNAVAILABLE ex) {
-            TEST(ex.minor == 34);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 34);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_TRANSACTION_MODE_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (TRANSACTION_MODE ex) {
-            TEST(ex.minor == 35);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 35);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
 
         try {
             ti.op_BAD_QOS_Ex();
-            TEST(false);
+            assertTrue(false);
         } catch (BAD_QOS ex) {
-            TEST(ex.minor == 36);
-            TEST(ex.completed == CompletionStatus.COMPLETED_NO);
+            assertTrue(ex.minor == 36);
+            assertTrue(ex.completed == CompletionStatus.COMPLETED_NO);
         }
     }
 
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectFixed.java b/yoko-core/src/test/java/ORBTest/TestObjectFixed.java
index acf3ec0..98d7b1a 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectFixed.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectFixed.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectFixed extends test.common.TestBase implements TestObject {
@@ -54,17 +56,17 @@
             b = new java.math.BigDecimal("0.00000000");
             ti.attrFixed(b);
             ret = ti.attrFixed();
-            TEST(ret.equals(b));
+            assertTrue(ret.equals(b));
 
             b = new java.math.BigDecimal("1234567890.12345670");
             ti.attrFixed(b);
             ret = ti.attrFixed();
-            TEST(ret.equals(b));
+            assertTrue(ret.equals(b));
 
             b = new java.math.BigDecimal("-9876543210.87654320");
             ti.attrFixed(b);
             ret = ti.attrFixed();
-            TEST(ret.equals(b));
+            assertTrue(ret.equals(b));
 
             FixedHolder inOut = new FixedHolder(new java.math.BigDecimal(
                     "20.00000000"));
@@ -72,9 +74,9 @@
             ret = ti.opFixed(new java.math.BigDecimal("10.00000000"), inOut,
                     out);
             b = new java.math.BigDecimal("30.00000000");
-            TEST(ret.equals(b));
-            TEST(inOut.value.equals(b));
-            TEST(out.value.equals(b));
+            assertTrue(ret.equals(b));
+            assertTrue(inOut.value.equals(b));
+            assertTrue(out.value.equals(b));
         }
     }
 
@@ -100,7 +102,7 @@
         if (request.env().exception() != null)
             throw (SystemException) request.env().exception();
         ret = request.return_value().extract_fixed();
-        TEST(ret.equals(new java.math.BigDecimal("1234567890.12345670")));
+        assertTrue(ret.equals(new java.math.BigDecimal("1234567890.12345670")));
 
         request = ti._request("opFixed");
         request.add_in_arg().insert_fixed(
@@ -119,8 +121,8 @@
         inOut.value = inOutAny.extract_fixed();
         out.value = outAny.extract_fixed();
         ret = request.return_value().extract_fixed();
-        TEST(ret.equals(new java.math.BigDecimal("30.00000000")));
-        TEST(inOut.value.equals(new java.math.BigDecimal("30.00000000")));
-        TEST(out.value.equals(new java.math.BigDecimal("30.00000000")));
+        assertTrue(ret.equals(new java.math.BigDecimal("30.00000000")));
+        assertTrue(inOut.value.equals(new java.math.BigDecimal("30.00000000")));
+        assertTrue(out.value.equals(new java.math.BigDecimal("30.00000000")));
     }
 }
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectLongLong.java b/yoko-core/src/test/java/ORBTest/TestObjectLongLong.java
index d7e4169..a19f26f 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectLongLong.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectLongLong.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectLongLong extends test.common.TestBase implements
@@ -53,32 +55,32 @@
             long ret;
             ti.attrLongLong(-9223372036854775807L - 1);
             ret = ti.attrLongLong();
-            TEST(ret == -9223372036854775807L - 1);
+            assertTrue(ret == -9223372036854775807L - 1);
 
             ti.attrLongLong(9223372036854775807L);
             ret = ti.attrLongLong();
-            TEST(ret == 9223372036854775807L);
+            assertTrue(ret == 9223372036854775807L);
 
             LongHolder inOut = new LongHolder(20);
             LongHolder out = new LongHolder();
             ret = ti.opLongLong(10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
             long ret;
             ti.attrULongLong(9223372036854775807L);
             ret = ti.attrULongLong();
-            TEST(ret == 9223372036854775807L);
+            assertTrue(ret == 9223372036854775807L);
 
             LongHolder inOut = new LongHolder(20);
             LongHolder out = new LongHolder();
             ret = ti.opULongLong(10, inOut, out);
-            TEST(ret == 30);
-            TEST(inOut.value == 30);
-            TEST(out.value == 30);
+            assertTrue(ret == 30);
+            assertTrue(inOut.value == 30);
+            assertTrue(out.value == 30);
         }
 
         {
@@ -87,9 +89,9 @@
 
             try {
                 ti.opLongLongEx(10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ORBTest_LongLong.ExLongLong ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
@@ -99,9 +101,9 @@
 
             try {
                 ti.opULongLongEx(10, inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ORBTest_LongLong.ExULongLong ex) {
-                TEST(ex.value == 30);
+                assertTrue(ex.value == 30);
             }
         }
 
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectStubTimeout.java b/yoko-core/src/test/java/ORBTest/TestObjectStubTimeout.java
index 4f8830b..be9d0c5 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectStubTimeout.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectStubTimeout.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectStubTimeout extends test.common.TestBase implements
@@ -69,7 +71,7 @@
             pl[0] = (m_orb.create_policy(
                     org.apache.yoko.orb.OB.TIMEOUT_POLICY_ID.value, any));
         } catch (PolicyError e) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
@@ -86,7 +88,7 @@
 
         try {
             ti.sleep_twoway(3);
-            TEST(false);
+            assertTrue(false);
         } catch (NO_RESPONSE ex) {
         }
 
@@ -114,7 +116,7 @@
         try {
             ti.sleep_twoway(0);
         } catch (NO_RESPONSE ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
diff --git a/yoko-core/src/test/java/ORBTest/TestObjectWChar.java b/yoko-core/src/test/java/ORBTest/TestObjectWChar.java
index 6f9e0cd..3756415 100644
--- a/yoko-core/src/test/java/ORBTest/TestObjectWChar.java
+++ b/yoko-core/src/test/java/ORBTest/TestObjectWChar.java
@@ -17,6 +17,8 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestObjectWChar extends test.common.TestBase implements TestObject {
@@ -51,20 +53,20 @@
             char ret;
             ti.attrWChar('a');
             ret = ti.attrWChar();
-            TEST(ret == 'a');
+            assertTrue(ret == 'a');
             ti.attrWChar((char) 224);
             ret = ti.attrWChar();
-            TEST(ret == (char) 224);
+            assertTrue(ret == (char) 224);
             ti.attrWChar((char) 0x20ac);
             ret = ti.attrWChar();
-            TEST(ret == (char) 0x20ac);
+            assertTrue(ret == (char) 0x20ac);
 
             CharHolder inOut = new CharHolder((char) 1);
             CharHolder out = new CharHolder();
             ret = ti.opWChar('a', inOut, out);
-            TEST(ret == 'b');
-            TEST(inOut.value == 'b');
-            TEST(out.value == 'b');
+            assertTrue(ret == 'b');
+            assertTrue(inOut.value == 'b');
+            assertTrue(out.value == 'b');
         }
 
         {
@@ -72,17 +74,17 @@
 
             ti.attrWString("");
             ret = ti.attrWString();
-            TEST(ret.equals(""));
+            assertTrue(ret.equals(""));
 
             ti.attrWString("Hello");
             ret = ti.attrWString();
-            TEST(ret.equals("Hello"));
+            assertTrue(ret.equals("Hello"));
 
             StringHolder inOut = new StringHolder("world!");
             StringHolder out = new StringHolder();
             ret = ti.opWString("Hello, ", inOut, out);
-            TEST(ret.equals("Hello, world!"));
-            TEST(out.value.equals("Hello, world!"));
+            assertTrue(ret.equals("Hello, world!"));
+            assertTrue(out.value.equals("Hello, world!"));
         }
 
         {
@@ -91,9 +93,9 @@
 
             try {
                 ti.opWCharEx('a', inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ORBTest_WChar.ExWChar ex) {
-                TEST(ex.value == 'b');
+                assertTrue(ex.value == 'b');
             }
         }
 
@@ -103,9 +105,9 @@
 
             try {
                 ti.opWStringEx("Hello, ", inOut, out);
-                TEST(false);
+                assertTrue(false);
             } catch (ORBTest_WChar.ExWString ex) {
-                TEST(ex.value.equals("Hello, world!"));
+                assertTrue(ex.value.equals("Hello, world!"));
             }
         }
 
diff --git a/yoko-core/src/test/java/ORBTest/TestPolicyIntf.java b/yoko-core/src/test/java/ORBTest/TestPolicyIntf.java
index 358a683..6c9e0b6 100644
--- a/yoko-core/src/test/java/ORBTest/TestPolicyIntf.java
+++ b/yoko-core/src/test/java/ORBTest/TestPolicyIntf.java
@@ -17,23 +17,22 @@
 
 package ORBTest;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.ORB;
 import org.omg.CORBA.ORBPackage.InvalidName;
 import org.omg.CORBA.Any;
 import org.omg.CORBA.BAD_PARAM;
-
 import org.omg.CORBA.Policy;
 import org.omg.CORBA.PolicyManager;
 import org.omg.CORBA.PolicyManagerHelper;
 import org.omg.CORBA.SetOverrideType;
 import org.omg.CORBA.PolicyError;
 import org.omg.CORBA.InvalidPolicies;
-
 import org.apache.yoko.orb.OB.RetryPolicy;
 import org.apache.yoko.orb.OB.RetryPolicyHelper;
 import org.apache.yoko.orb.OB.TimeoutPolicy;
 import org.apache.yoko.orb.OB.TimeoutPolicyHelper;
-
 import org.apache.yoko.orb.OB.MinorCodes;
 
 import ORBTest_Basic.*;
@@ -45,10 +44,10 @@
             pm = PolicyManagerHelper.narrow(orb
                     .resolve_initial_references("ORBPolicyManager"));
         } catch (InvalidName ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
-        TEST(pm != null);
+        assertTrue(pm != null);
 
         int[] policyTypes = new int[0];
         Policy[] origPolicies = pm.get_policy_overrides(policyTypes);
@@ -63,19 +62,19 @@
                 pm.set_policy_overrides(pl, SetOverrideType.ADD_OVERRIDE);
 
             } catch (PolicyError ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (InvalidPolicies ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             policyTypes = new int[1];
             policyTypes[0] = org.apache.yoko.orb.OB.RETRY_POLICY_ID.value;
             Policy[] policy = pm.get_policy_overrides(policyTypes);
-            TEST(policy.length == 1
-                    && policy[0].policy_type() == org.apache.yoko.orb.OB.RETRY_POLICY_ID.value);
+            assertTrue(policy.length == 1
+			&& policy[0].policy_type() == org.apache.yoko.orb.OB.RETRY_POLICY_ID.value);
 
             RetryPolicy p = RetryPolicyHelper.narrow(policy[0]);
-            TEST(p.retry_mode() == org.apache.yoko.orb.OB.RETRY_ALWAYS.value);
+            assertTrue(p.retry_mode() == org.apache.yoko.orb.OB.RETRY_ALWAYS.value);
         }
 
         {
@@ -93,9 +92,9 @@
                 pm.set_policy_overrides(pl, SetOverrideType.ADD_OVERRIDE);
 
             } catch (PolicyError ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (InvalidPolicies ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             policyTypes = new int[2];
@@ -103,7 +102,7 @@
             policyTypes[1] = org.apache.yoko.orb.OB.TIMEOUT_POLICY_ID.value;
 
             Policy[] policies = pm.get_policy_overrides(policyTypes);
-            TEST(policies.length == 2);
+            assertTrue(policies.length == 2);
 
             for (int i = 0; i < policies.length; ++i) {
                 switch (policies[i].policy_type()) {
@@ -111,10 +110,10 @@
                     try {
                         RetryPolicy policy = RetryPolicyHelper
                                 .narrow(policies[i]);
-                        TEST(policy != null);
-                        TEST(policy.retry_mode() == org.apache.yoko.orb.OB.RETRY_STRICT.value);
+                        assertTrue(policy != null);
+                        assertTrue(policy.retry_mode() == org.apache.yoko.orb.OB.RETRY_STRICT.value);
                     } catch (BAD_PARAM ex) {
-                        TEST(false);
+                        assertTrue(false);
                     }
                     break;
                 }
@@ -122,16 +121,16 @@
                     try {
                         TimeoutPolicy policy = TimeoutPolicyHelper
                                 .narrow(policies[i]);
-                        TEST(policy != null);
-                        TEST(policy.value() == 3000);
+                        assertTrue(policy != null);
+                        assertTrue(policy.value() == 3000);
                     } catch (BAD_PARAM ex) {
-                        TEST(false);
+                        assertTrue(false);
                     }
                     break;
                 }
                 default:
-                    TEST(("org.omg.CORBA.PolicyManager.get_policy_overrides()"
-                            + " returned policies with unexpected types") == null);
+                    assertTrue(("org.omg.CORBA.PolicyManager.get_policy_overrides()"
+					+ " returned policies with unexpected types") == null);
                 }
             }
         }
@@ -146,14 +145,14 @@
                 pl[1] = orb.create_policy(
                         org.apache.yoko.orb.OB.RETRY_POLICY_ID.value, any);
                 pm.set_policy_overrides(pl, SetOverrideType.ADD_OVERRIDE);
-                TEST(("org.omg.CORBA.PolicyManager.set_policy_overrides() "
-                        + "BAD_PARAM(30, COMPLETED_NO) expected") == null);
+                assertTrue(("org.omg.CORBA.PolicyManager.set_policy_overrides() "
+				+ "BAD_PARAM(30, COMPLETED_NO) expected") == null);
             } catch (PolicyError ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (InvalidPolicies ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (BAD_PARAM ex) {
-                TEST(ex.minor == MinorCodes.MinorDuplicatePolicyType);
+                assertTrue(ex.minor == MinorCodes.MinorDuplicatePolicyType);
             }
 
             //
@@ -165,11 +164,11 @@
                         SetOverrideType.SET_OVERRIDE);
 
             } catch (InvalidPolicies ex) {
-                TEST(false);
+                assertTrue(false);
             }
             policyTypes = new int[0];
             Policy[] current = pm.get_policy_overrides(policyTypes);
-            TEST(current.length == origPolicies.length);
+            assertTrue(current.length == origPolicies.length);
             for (int i = 0; i < current.length; ++i) {
                 boolean matched = false;
                 for (int j = 0; j < origPolicies.length; ++j) {
@@ -179,7 +178,7 @@
                         break;
                     }
                 }
-                TEST(matched);
+                assertTrue(matched);
             }
         }
 
diff --git a/yoko-core/src/test/java/org/apache/yoko/AbstractMatrixOrbTestBase.java b/yoko-core/src/test/java/org/apache/yoko/AbstractMatrixOrbTestBase.java
index 2ecc108..a513407 100644
--- a/yoko-core/src/test/java/org/apache/yoko/AbstractMatrixOrbTestBase.java
+++ b/yoko-core/src/test/java/org/apache/yoko/AbstractMatrixOrbTestBase.java
@@ -19,6 +19,7 @@
 package org.apache.yoko;
 
 import java.io.File;
+import java.util.Arrays;
 
 import junit.framework.TestSuite;
 /**
@@ -54,22 +55,19 @@
         runServerClientTest(serverClass, serverArgs, clientClass, clientArgs);
     }
                 
-    public static TestSuite generateTestSuite(String serverClass, String clientClass, 
-                                              File waitForFile) {
+    public static TestSuite generateTestSuite(String serverClass, String clientClass, File waitForFile) {
         return generateTestSuite(serverClass, defaultServers, clientClass, defaultClients, waitForFile);
     }
         
-    public static TestSuite generateTestSuite(String serverClass, String[][] servers,
-                                              String clientClass, String[][] clients, File waitForFile) {
+    public static TestSuite generateTestSuite(String serverClass, String[][] servers, String clientClass, String[][] clients, File waitForFile) {
         TestSuite suite = new TestSuite();
-        for(int serverNo = 0; serverNo < servers.length; serverNo++) {
-            for(int clientNo = 0; clientNo < clients.length; clientNo++) {
+        for(String[] serverArgs: servers) {
+            for(String[] clientArgs: clients) {
                 AbstractMatrixOrbTestBase test = new AbstractMatrixOrbTestBase("test"); 
-                test.init(serverClass, servers[serverNo], clientClass, clients[clientNo], waitForFile);
+                test.init(serverClass, serverArgs, clientClass, clientArgs, waitForFile);
                 suite.addTest(test);
             }
         }
         return suite;
-                
     }
 }
diff --git a/yoko-core/src/test/java/org/apache/yoko/AbstractOrbTestBase.java b/yoko-core/src/test/java/org/apache/yoko/AbstractOrbTestBase.java
index b0f652d..ee97b45 100644
--- a/yoko-core/src/test/java/org/apache/yoko/AbstractOrbTestBase.java
+++ b/yoko-core/src/test/java/org/apache/yoko/AbstractOrbTestBase.java
@@ -18,17 +18,20 @@
 
 package org.apache.yoko;
 
+import static java.util.concurrent.TimeUnit.SECONDS;
+
 import java.io.File;
 import java.rmi.registry.Registry;
-import java.util.Iterator;
 import java.util.Map.Entry;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import junit.framework.TestCase;
 
 import org.apache.yoko.processmanager.JavaProcess;
 import org.apache.yoko.processmanager.ProcessManager;
 
-import junit.framework.TestCase;
-import junit.framework.TestSuite;
-
 /**
  * Superclass for ORB tests. Takes care of setting up a a server process and a client process.
  * It also sets the java.endorsed.dirs property and launches the client process.
@@ -61,8 +64,7 @@
         JavaProcess[] processes = new JavaProcess[] {server, client};
         for(int i = 0; i < processes.length; i++) {
             JavaProcess process = processes[i];
-            for(Iterator it = System.getProperties().entrySet().iterator(); it.hasNext();) {
-                Entry entry = (Entry) it.next();
+            for(Entry<?, ?> entry: System.getProperties().entrySet()) {
                 String key = entry.getKey().toString();
                 if(key.startsWith(process.getName() + ":")){
                     int pos = key.indexOf(':') + 1;
@@ -82,50 +84,59 @@
             getWaitForFile().delete();
         }
     }
+    
+    protected void runServerClientTest(Class<?> serverClass, Class<?> clientClass, String...commonArgs) throws Exception {
+        runServerClientTest(serverClass.getName(), commonArgs, clientClass.getName(), commonArgs);
+    }
+    
     protected void runServerClientTest(String serverClass, String clientClass) throws Exception {
         runServerClientTest(serverClass, new String[0], clientClass, new String[0]);
     }
     protected void runServerClientTest(String serverClass, String[] serverArgs, 
                                        String clientClass, String[] clientArgs) throws Exception {
         server.launch();
-        Thread serverThread = server.invokeMainAsync(serverClass, serverArgs);
+        Future<Void> serverFuture = server.invokeMainAsync(serverClass, serverArgs);
         waitForFile();
-        // TODO: Need to find a better way, this slows down testing unneccesarily,
-        // and is somewhat non-robust.
-        Thread.sleep(1000);
         client.invokeMain(clientClass, clientArgs);
-        serverThread.join(10000);
+        try {
+            serverFuture.get(2, SECONDS);
+        } catch (TimeoutException e) {
+            System.out.println("Ignoring server exception: " + e);
+        }
         server.exit(0);
-                
     }
         
-    public void setWaitForFile(File file) {
-        this.waitForFile = file;
+    public void setWaitForFile(String file) {
+        this.waitForFile = new File(file);
     }
         
-    public File getWaitForFile() {
+    public final File getWaitForFile() {
         return waitForFile;
     }
         
     protected void waitForFile() {
+        File file = getWaitForFile();
+        if(file != null) {
+            waitFor(file, waitForFileTimeout);
+        }
+    }
+
+    public static void waitFor(File file, int timeout) throws Error {
         long timeBefore = System.currentTimeMillis();
-        if(getWaitForFile() != null) {
-            while(true) {
+        do {
                 try {
-                    if(getWaitForFile().exists()) {
+                if(file.exists()) {
                         break;
                     }
                     Thread.sleep(50);
-                    if(System.currentTimeMillis() > timeBefore + waitForFileTimeout) {
-                        fail("The file " + getWaitForFile() + 
-                             "was not created within " + waitForFileTimeout + "ms");
+                if(System.currentTimeMillis() > timeBefore + timeout) {
+                    fail("The file " + file + " was not created within " + timeout + "ms");
                     }
                 }
                 catch(InterruptedException e) {
                     throw new Error(e);
                 }
-                getWaitForFile().deleteOnExit();
-            }
-        }
+        } while(true);
+        file.deleteOnExit();
     }           
 }
diff --git a/yoko-core/src/test/java/org/apache/yoko/CodeSetTest.java b/yoko-core/src/test/java/org/apache/yoko/CodeSetTest.java
index 5699c87..8b6e87e 100755
--- a/yoko-core/src/test/java/org/apache/yoko/CodeSetTest.java
+++ b/yoko-core/src/test/java/org/apache/yoko/CodeSetTest.java
@@ -24,7 +24,7 @@
 
     public void setUp() throws Exception {
         super.setUp();
-        setWaitForFile(new java.io.File(OUTPUT_FILE));
+        setWaitForFile(OUTPUT_FILE);
     }
         
     public void testStandardCodeSet() throws Exception {
diff --git a/yoko-core/src/test/java/org/apache/yoko/ConnectionCachingTest.java b/yoko-core/src/test/java/org/apache/yoko/ConnectionCachingTest.java
new file mode 100644
index 0000000..230c4e4
--- /dev/null
+++ b/yoko-core/src/test/java/org/apache/yoko/ConnectionCachingTest.java
@@ -0,0 +1,203 @@
+package org.apache.yoko;
+
+import org.apache.yoko.orb.OBPortableServer.POA;
+import org.apache.yoko.orb.OBPortableServer.POAHelper;
+import org.apache.yoko.orb.OBPortableServer.POAManager;
+import org.apache.yoko.orb.OBPortableServer.POAManagerHelper;
+import org.apache.yoko.orb.OCI.Acceptor;
+import org.apache.yoko.orb.OCI.IIOP.AcceptorInfo;
+import org.apache.yoko.orb.OCI.IIOP.AcceptorInfoHelper;
+import org.apache.yoko.orb.spi.naming.NameServiceInitializer;
+import org.apache.yoko.orb.spi.naming.RemoteAccess;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.omg.CORBA.BAD_OPERATION;
+import org.omg.CORBA.LocalObject;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.ResponseHandler;
+import org.omg.CORBA_2_3.portable.InputStream;
+import org.omg.CosNaming.*;
+import org.omg.PortableInterceptor.*;
+import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
+import test.util.Skellington;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.Properties;
+
+import static javax.rmi.PortableRemoteObject.narrow;
+
+public class ConnectionCachingTest {
+    private static final NameComponent[] OBJECT_NAME = { new NameComponent("object", "")};
+    ORB serverORB;
+    ORB clientORB;
+
+    @Before
+    public void setup() throws Exception {
+        serverORB = Util.createServerOrb();
+        clientORB = Util.createClientORB(serverORB);
+        // make a GIOP 1.0 call first
+        NamingContext ctx = NamingContextHelper.narrow(clientORB.string_to_object(Util.getNameServerUrl(serverORB)));
+        ctx.new_context();
+    }
+
+    @Test
+    public void testSingleNull() throws Exception {
+        Assert.assertEquals(null, newRemoteImpl(clientORB).bounce(null));
+    }
+
+    @Test
+    public void testSingleNullSameOrb() throws Exception {
+        Assert.assertEquals(null, newRemoteImpl(serverORB).bounce(null));
+    }
+
+    @Test
+    public void testSingleEmptyString() throws Exception {
+        Assert.assertEquals("", newRemoteImpl(clientORB).bounce(""));
+    }
+
+    @Test
+    public void testSingleEmptyStringSameOrb() throws Exception {
+        Assert.assertEquals("", newRemoteImpl(serverORB).bounce(""));
+    }
+
+    @Test
+    public void testSingleNonEmptyString() throws Exception {
+        Assert.assertEquals("hello", newRemoteImpl(clientORB).bounce("hello"));
+    }
+
+    @Test
+    public void testSingleNonEmptyStringSameOrb() throws Exception {
+        Assert.assertEquals("hello", newRemoteImpl(serverORB).bounce("hello"));
+    }
+
+    @Test
+    public void testLotsOfInvocations() throws Exception {
+        Assert.assertEquals(null, newRemoteImpl(clientORB).bounce(null));
+        Assert.assertEquals("", newRemoteImpl(clientORB).bounce(""));
+        Assert.assertEquals("a", newRemoteImpl(clientORB).bounce("a"));
+        Assert.assertEquals("ab", newRemoteImpl(clientORB).bounce("ab"));
+        Assert.assertEquals("abc", newRemoteImpl(clientORB).bounce("abc"));
+        Assert.assertEquals("abcd", newRemoteImpl(clientORB).bounce("abcd"));
+        Assert.assertEquals("abcde", newRemoteImpl(clientORB).bounce("abcde"));
+    }
+
+    @Test
+    public void testLotsOfInvocationsSameOrb() throws Exception {
+        Assert.assertEquals(null, newRemoteImpl(serverORB).bounce(null));
+        Assert.assertEquals("", newRemoteImpl(serverORB).bounce(""));
+        Assert.assertEquals("a", newRemoteImpl(serverORB).bounce("a"));
+        Assert.assertEquals("ab", newRemoteImpl(serverORB).bounce("ab"));
+        Assert.assertEquals("abc", newRemoteImpl(serverORB).bounce("abc"));
+        Assert.assertEquals("abcd", newRemoteImpl(serverORB).bounce("abcd"));
+        Assert.assertEquals("abcde", newRemoteImpl(serverORB).bounce("abcde"));
+    }
+
+    private TheInterface newRemoteImpl(ORB callerOrb) throws Exception {
+        TheImpl theImpl = new TheImpl();
+        theImpl.publish(serverORB);
+        // bind it into the naming context
+        Util.getNameService(serverORB).rebind(OBJECT_NAME, theImpl.thisObject());
+        // look it up from the caller orb
+        Object stub = Util.getNameService(callerOrb).resolve(OBJECT_NAME);
+        return (TheInterface)narrow(stub, TheInterface.class);
+    }
+
+    public interface TheInterface extends Remote {
+        String bounce(String text) throws RemoteException;
+    }
+
+    private static class TheImpl extends Skellington implements TheInterface {
+        @Override
+        protected OutputStream dispatch(String method, InputStream in, ResponseHandler reply) throws RemoteException {
+            switch (method) {
+                case "bounce":
+                    String result = bounce((String) in.read_value(String.class));
+                    OutputStream out = reply.createReply();
+                    ((org.omg.CORBA_2_3.portable.OutputStream) out).write_value(result, String.class);
+                    return out;
+                default:
+                    throw new BAD_OPERATION();
+            }
+        }
+
+        @Override
+        public String bounce(String s) {return s;}
+    }
+
+    public static class DummyInterceptor extends LocalObject implements ORBInitializer, ServerRequestInterceptor {
+
+        @Override
+        public String name() {
+            return "DummyInterceptor";
+        }
+
+        @Override
+        public void destroy() {}
+
+        @Override
+        public void pre_init(ORBInitInfo info) {}
+
+        @Override
+        public void post_init(ORBInitInfo info) {
+            try {
+                info.add_server_request_interceptor(this);
+            } catch (DuplicateName duplicateName) {
+                throw new Error(duplicateName);
+            }
+        }
+
+        @Override
+        public void receive_request_service_contexts(ServerRequestInfo ri) throws ForwardRequest {}
+
+        @Override
+        public void receive_request(ServerRequestInfo ri) throws ForwardRequest {}
+
+        @Override
+        public void send_reply(ServerRequestInfo ri) {}
+
+        @Override
+        public void send_exception(ServerRequestInfo ri) throws ForwardRequest {}
+
+        @Override
+        public void send_other(ServerRequestInfo ri) throws ForwardRequest {}
+    }
+
+
+    private static class Util {
+
+        private static int getPort(ORB orb) throws Exception {
+            POA rootPoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+            POAManager poaMgr = POAManagerHelper.narrow(rootPoa.the_POAManager());
+            for (Acceptor acceptor : poaMgr.get_acceptors()) {
+                AcceptorInfo info = AcceptorInfoHelper.narrow(acceptor.get_info());
+                if (info != null) return (char) info.port();
+            }
+            throw new Error("No IIOP Acceptor found");
+        }
+
+        private static String getNameServerUrl(ORB orb) throws Exception {
+            return "corbaname::localhost:" + getPort(orb);
+        }
+
+        private static ORB createServerOrb() throws Exception {
+            Properties serverProps = new Properties();
+            serverProps.put(NameServiceInitializer.NS_ORB_INIT_PROP, "");
+            serverProps.put(NameServiceInitializer.NS_REMOTE_ACCESS_ARG, RemoteAccess.readWrite.toString());
+            serverProps.put(ORBInitializer.class.getName() + "Class." + DummyInterceptor.class.getName(), "");
+            ORB orb =  ORB.init((String[])null, serverProps);
+            POAHelper.narrow(orb.resolve_initial_references("RootPOA")).the_POAManager().activate();
+            return orb;
+        }
+
+        private static ORB createClientORB(ORB targetORB) throws Exception {
+            return ORB.init(new String[]{"-ORBInitRef", "NameService=" + getNameServerUrl(targetORB)}, null);
+        }
+
+        private static NamingContextExt getNameService(ORB orb) throws Exception {
+            return NamingContextExtHelper.narrow(orb.resolve_initial_references("NameService"));
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/org/apache/yoko/ConnectionCleanupTest.java b/yoko-core/src/test/java/org/apache/yoko/ConnectionCleanupTest.java
new file mode 100644
index 0000000..564abfc
--- /dev/null
+++ b/yoko-core/src/test/java/org/apache/yoko/ConnectionCleanupTest.java
@@ -0,0 +1,150 @@
+package org.apache.yoko;
+
+import static javax.rmi.PortableRemoteObject.narrow;
+
+import org.apache.yoko.orb.OBPortableServer.POAHelper;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.omg.CORBA.BAD_OPERATION;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.ResponseHandler;
+import org.omg.CORBA_2_3.portable.InputStream;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
+import org.omg.PortableServer.POAPackage.ServantAlreadyActive;
+import org.omg.PortableServer.POAPackage.WrongPolicy;
+import test.util.MultiException;
+import test.util.Skellington;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.*;
+import java.util.concurrent.*;
+
+public class ConnectionCleanupTest {
+    ORB serverORB;
+    ORB clientORB;
+
+    @Before
+    public void setup() throws Exception {
+        serverORB = ORB.init((String[])null, null);
+        clientORB = ORB.init((String[])null, null);
+    }
+
+    @Test
+    public void testOneClient() throws Exception {
+        newRemoteImpl().gcAndSleep(1000);
+    }
+
+    private TheInterface newRemoteImpl() {
+        try {
+            return (TheInterface)narrow(clientORB.string_to_object(new TheImpl().publish(serverORB)), TheInterface.class);
+        } catch (InvalidName | AdapterInactive | WrongPolicy | ServantAlreadyActive e) {
+            e.printStackTrace();
+            throw new AssertionError(e);
+        }
+    }
+
+    @Test
+    public void testRecursiveClient() throws Exception {
+        newRemoteImpl().gcAndSleepRecursive(10000, 100);
+    }
+
+    //@Test
+    public void doNotTestOneHundredClients() throws Throwable {
+        // To avoid multiple threads initializing the singleton at once
+        // during the first call to PRO.narrow() force it to be called
+        // once before the other threads start.
+        testOneClient();
+        // OK - now do a hundred threads.
+        List<Future<Throwable>> futures = new ArrayList<>();
+        ExecutorService xs = Executors.newFixedThreadPool(100);
+        final CyclicBarrier cb = new CyclicBarrier(101);
+        for (int i = 0; i < 100; i++) {
+            futures.add(xs.submit(new Callable<Throwable>() {
+                @Override
+                public Throwable call() throws Exception {
+                    try {
+                        cb.await();
+                        recurse(10); // use recursion so stack trace tells us how far in we failed
+                        return null;
+                    } catch (Throwable t) {
+                        return t;
+                    }
+                }
+                private void recurse(int times) throws Exception {
+                    testOneClient();
+                    if (times > 0) recurse(times - 1);
+                }
+            }));
+        }
+        cb.await();
+
+        MultiException me = new MultiException(futures);
+        if (me.isEmpty()) return;
+        throw me;
+    }
+
+
+    public interface TheInterface extends Remote {
+        void gcAndSleep(long millis) throws RemoteException;
+        void gcAndSleepRecursive(long millis, int depth) throws RemoteException;
+    }
+
+    private class TheImpl extends Skellington implements TheInterface {
+        @Override
+        public void gcAndSleep(long millis) {
+            //forceGarbageCollection();
+            try {
+                Thread.sleep(millis);
+            } catch (InterruptedException ignored) {}
+        }
+
+        @Override
+        public void gcAndSleepRecursive(long millis, int depth) throws RemoteException  {
+            if (depth == 1)
+                newRemoteImpl().gcAndSleep(millis);
+            else
+                newRemoteImpl().gcAndSleepRecursive(millis, depth - 1);
+        }
+
+        @Override
+        protected OutputStream dispatch(String method, InputStream in, ResponseHandler reply) throws RemoteException {
+            switch (method) {
+                case "gcAndSleep":
+                    gcAndSleep(in.read_longlong());
+                    return reply.createReply();
+                case "gcAndSleepRecursive":
+                    gcAndSleepRecursive(in.read_longlong(), in.read_long());
+                    return reply.createReply();
+                default:
+                    throw new BAD_OPERATION();
+            }
+        }
+    }
+
+    private static long forceGarbageCollection() {
+        List<byte[]> extents = new ArrayList<>();
+        long tally = 0;
+        // allocate as much as possible, halve the size and try again
+        for (int i = 30; i >= 0; i--) {
+            try {
+                do {
+                    int alloc = 1 << i;
+                    extents.add(new byte[alloc]);
+                    tally += alloc;
+                } while (true);
+            } catch (OutOfMemoryError oom) {}
+        }
+        // now the heap should be full so even the smallest allocation should fail
+        try {
+            for (int i = 0; i < 1024; i++) extents.add(new byte[128]);
+            Assert.fail("this allocation should have failed");
+        } catch (OutOfMemoryError e) {}
+        System.gc();
+        return tally;
+    }
+}
diff --git a/yoko-core/src/test/java/org/apache/yoko/CosNamingTest.java b/yoko-core/src/test/java/org/apache/yoko/CosNamingTest.java
index cf9c9a1..ed5525c 100644
--- a/yoko-core/src/test/java/org/apache/yoko/CosNamingTest.java
+++ b/yoko-core/src/test/java/org/apache/yoko/CosNamingTest.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -16,26 +16,33 @@
  *  limitations under the License.
  */
 
-
 /**
  * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
  */
 package org.apache.yoko;
 
-import java.io.File;
+import test.tnaming.ClientForReadOnlyNameService;
+import test.tnaming.ClientForReadWriteNameService;
+import test.tnaming.ServerWithReadWriteIntegralNameService;
+import test.tnaming.ServerWithReadOnlyIntegralNameService;
+import test.tnaming.ServerWithReadWriteStandaloneNameService;
 
 public class CosNamingTest extends AbstractOrbTestBase {
-    private static final String SERVER_CLASS = "test.tnaming.Server";
-    private static final String CLIENT_CLASS = "test.tnaming.Client";
-
-    public void setUp() throws Exception {
-        super.setUp();
-        setWaitForFile(new File("Test.ref"));
+    public void testReadOnlyIntegralNameService() throws Exception {
+        final String refFile = "readonlyintegralnameservice.ref";
+        setWaitForFile(refFile);
+        runServerClientTest(ServerWithReadOnlyIntegralNameService.class, ClientForReadOnlyNameService.class, refFile);
     }
 
-    public void testNameService() throws Exception {
-        runServerClientTest(SERVER_CLASS, CLIENT_CLASS);
+    public void testReadWriteIntegralNameService() throws Exception {
+        final String refFile = "readwriteintegralnameservice.ref";
+        setWaitForFile(refFile);
+        runServerClientTest(ServerWithReadWriteIntegralNameService.class, ClientForReadWriteNameService.class, refFile);
+    }
+
+    public void testReadWriteStandaloneNameService() throws Exception {
+        final String refFile = "readwritestandalonenameservice.ref";
+        setWaitForFile(refFile);
+        runServerClientTest(ServerWithReadWriteStandaloneNameService.class, ClientForReadWriteNameService.class, refFile);
     }
 }
-
-
diff --git a/yoko-core/src/test/java/org/apache/yoko/FVDTest.java b/yoko-core/src/test/java/org/apache/yoko/FVDTest.java
new file mode 100644
index 0000000..988e265
--- /dev/null
+++ b/yoko-core/src/test/java/org/apache/yoko/FVDTest.java
@@ -0,0 +1,36 @@
+/**
+ *
+ * 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.
+ */
+
+/**
+ * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
+ */
+package org.apache.yoko;
+
+import static test.fvd.Marshalling.VERSION1;
+import static test.fvd.Marshalling.VERSION2;
+import test.fvd.MissingFieldsClient;
+import test.fvd.MissingFieldsServer;
+
+public class FVDTest extends AbstractOrbTestBase {
+    public void testMissingFields() throws Exception {
+        if (true) return;
+        final String refFile = "missingfields.ref";
+        setWaitForFile(refFile);
+        runServerClientTest(MissingFieldsServer.class, MissingFieldsClient.class, refFile, VERSION1.name(), VERSION2.name());
+    }
+}
diff --git a/yoko-core/src/test/java/org/apache/yoko/IIOPPluginTest.java b/yoko-core/src/test/java/org/apache/yoko/IIOPPluginTest.java
index 0a6c263..b20c798 100644
--- a/yoko-core/src/test/java/org/apache/yoko/IIOPPluginTest.java
+++ b/yoko-core/src/test/java/org/apache/yoko/IIOPPluginTest.java
@@ -22,7 +22,6 @@
  */
 package org.apache.yoko;
 
-import java.io.File;
 
 public class IIOPPluginTest extends AbstractOrbTestBase {
     private static final String SERVER_CLASS = "test.iiopplugin.Server";
@@ -31,7 +30,7 @@
 
     public void setUp() throws Exception {
         super.setUp();
-        setWaitForFile(new File(OUTPUT_FILE));
+        setWaitForFile(OUTPUT_FILE);
     }
     public void testLocal() throws Exception {
         runServerClientTest(SERVER_CLASS, CLIENT_CLASS);
diff --git a/yoko-core/src/test/java/org/apache/yoko/LocalTest.java b/yoko-core/src/test/java/org/apache/yoko/LocalTest.java
index 3f1fcd1..043e6ec 100755
--- a/yoko-core/src/test/java/org/apache/yoko/LocalTest.java
+++ b/yoko-core/src/test/java/org/apache/yoko/LocalTest.java
@@ -24,7 +24,7 @@
 
     public void setUp() throws Exception {
         super.setUp();
-        setWaitForFile(new java.io.File(OUTPUT_FILE));
+        setWaitForFile(OUTPUT_FILE);
     }
 
     public void testLocal() throws Exception {
diff --git a/yoko-core/src/test/java/org/apache/yoko/MetaTest.java b/yoko-core/src/test/java/org/apache/yoko/MetaTest.java
new file mode 100644
index 0000000..8b1f15c
--- /dev/null
+++ b/yoko-core/src/test/java/org/apache/yoko/MetaTest.java
@@ -0,0 +1,49 @@
+package org.apache.yoko;
+
+import java.io.Serializable;
+
+import javax.rmi.CORBA.Util;
+import javax.rmi.CORBA.ValueHandler;
+
+import junit.framework.TestCase;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.omg.CORBA.ValueDefPackage.FullValueDescription;
+import org.omg.SendingContext.CodeBase;
+
+import test.fvd.Marshalling;
+
+public class MetaTest extends TestCase {
+
+    public static void testMetaForClassWithASelfReference() throws Exception {
+        ValueHandler vh = Util.createValueHandler();
+        CodeBase codebase = (CodeBase)vh.getRunTimeCodeBase();
+        String dataClassRepid = vh.getRMIRepositoryID(Data.class);
+        FullValueDescription fvd = codebase.meta(dataClassRepid);
+        Assert.assertNotNull(fvd);
+    }
+
+    public void testMetaForClassWithTwoSelfReferences() {
+        Marshalling.DEFAULT_VERSION.select();
+        ValueHandler vh = Util.createValueHandler();
+        CodeBase codebase = (CodeBase)vh.getRunTimeCodeBase();
+        String dataClassRepid = vh.getRMIRepositoryID(X.class);
+        System.out.println(dataClassRepid);
+        FullValueDescription fvd = codebase.meta(dataClassRepid);
+        Assert.assertNotNull(fvd);
+    }
+
+    public static class Data implements Serializable {
+        private static final long serialVersionUID = 1L;
+        public Data d;
+    }
+
+    public static class X {
+        X x1;
+        X x2;
+    }
+}
+
+
diff --git a/yoko-core/src/test/java/org/apache/yoko/PoaTest.java b/yoko-core/src/test/java/org/apache/yoko/PoaTest.java
index 04eaa4f..bd50f7b 100755
--- a/yoko-core/src/test/java/org/apache/yoko/PoaTest.java
+++ b/yoko-core/src/test/java/org/apache/yoko/PoaTest.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -17,91 +17,77 @@
  */
 package org.apache.yoko;
 
-import java.io.File;
-import java.io.IOException;
-import java.lang.reflect.InvocationTargetException;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.rmi.RemoteException;
-import java.rmi.registry.Registry;
-
-import org.apache.yoko.processmanager.JavaProcess;
-import org.apache.yoko.processmanager.ProcessManager;
-
-import junit.framework.TestCase;
-
 public class PoaTest extends AbstractOrbTestBase {
 
     public void setUp() throws Exception {
         super.setUp();
-        setWaitForFile(new File("Test.ref"));
+        setWaitForFile("Test.ref");
     }
     public void testActivate() throws Exception {
         client.invokeMain("test.poa.TestActivate");
     }
-        
+
     public void testDeactivate() throws Exception {
         client.invokeMain("test.poa.TestDeactivate");
     }
-        
+
     public void testCollocated() throws Exception {
         client.invokeMain("test.poa.TestCollocated");
     }
-        
+
     public void testCreate() throws Exception {
         client.invokeMain("test.poa.TestCreate");
     }
-        
+
     public void testDestroy() throws Exception {
         client.invokeMain("test.poa.TestDestroy");
     }
-        
+
     public void testFind() throws Exception {
         client.invokeMain("test.poa.TestFind");
     }
-        
+
     public void testMisc() throws Exception {
         client.invokeMain("test.poa.TestMisc");
     }
-        
+
     public void testDefaultServant() throws Exception {
         runServerClientTest("test.poa.TestDefaultServantServer");
     }
-        
+
     public void testServantActivatorServer() throws Exception {
         runServerClientTest("test.poa.TestServantActivatorServer");
     }
-        
+
     public void testServantLocatorServer() throws Exception {
         runServerClientTest("test.poa.TestServantLocatorServer");
     }
-        
+
     public void testLocationForwardServer() throws Exception {
         runServerClientTest("test.poa.TestLocationForwardServerMain", "test.poa.TestLocationForwardClient");
     }
-        
+
     public void testAdapterActivatorServer() throws Exception {
         runServerClientTest("test.poa.TestAdapterActivatorServer");
     }
-        
+
     public void testPoaManagerServer() throws Exception {
         runServerClientTest("test.poa.TestPOAManagerServer", "test.poa.TestPOAManagerClient");
     }
-        
+
     public void testDispatchStrategyServer() throws Exception {
         runServerClientTest("test.poa.TestDispatchStrategyServer", "test.poa.TestDispatchStrategyClient");
     }
-        
+
     public void testMultipleOrbsServer() throws Exception {
         runServerClientTest("test.poa.TestMultipleOrbsServer", "test.poa.TestMultipleOrbsClient");
     }
-        
+
     public void testMultipleOrbsThreadedServer() throws Exception {
         runServerClientTest("test.poa.TestMultipleOrbsThreadedServer", "test.poa.TestMultipleOrbsThreadedClient");
     }
-        
+
     private void runServerClientTest(String serverClass) throws Exception {
         runServerClientTest(serverClass, "test.poa.TestClient");
-    }   
+    }
 }
diff --git a/yoko-core/src/test/java/org/apache/yoko/RMIExceptionHandlingTest.java b/yoko-core/src/test/java/org/apache/yoko/RMIExceptionHandlingTest.java
new file mode 100644
index 0000000..b24f4ff
--- /dev/null
+++ b/yoko-core/src/test/java/org/apache/yoko/RMIExceptionHandlingTest.java
@@ -0,0 +1,118 @@
+package org.apache.yoko;
+
+import java.rmi.RemoteException;
+import java.util.Properties;
+
+import javax.rmi.PortableRemoteObject;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.omg.CORBA.ORB;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAHelper;
+
+import test.rmi.exceptionhandling.MyAppException;
+import test.rmi.exceptionhandling.MyClientRequestInterceptor;
+import test.rmi.exceptionhandling.MyRuntimeException;
+import test.rmi.exceptionhandling.MyServerRequestInterceptor;
+import test.rmi.exceptionhandling.Thrower;
+import test.rmi.exceptionhandling.ThrowerImpl;
+import test.rmi.exceptionhandling._ThrowerImpl_Tie;
+
+@SuppressWarnings("serial")
+public class RMIExceptionHandlingTest {
+    private static ORB serverOrb;
+    private static ORB clientOrb;
+    private static String ior;
+    private static MyAppException mae = null;
+    private static MyRuntimeException mre = null;
+
+    private static ORB initOrb(Properties props, String... args) {
+        return ORB.init(args, props);
+    }
+
+    private static void initExceptions() {
+        if (mae == null) mae = new MyAppException();
+        if (mre == null) mre = new MyRuntimeException();
+    }
+
+    @BeforeClass
+    public static void createServerORB() throws Exception {
+        initExceptions();
+        ThrowerImpl.myAppException = mae;
+        ThrowerImpl.myRuntimeException = mre;
+        serverOrb = initOrb(new Properties() {{
+            put("org.omg.PortableInterceptor.ORBInitializerClass." + MyClientRequestInterceptor.class.getName(),"");
+            put("org.omg.PortableInterceptor.ORBInitializerClass." + MyServerRequestInterceptor.class.getName(),"");
+        }});
+        POA poa = POAHelper.narrow(serverOrb.resolve_initial_references("RootPOA"));
+        poa.the_POAManager().activate();
+
+        _ThrowerImpl_Tie tie = new _ThrowerImpl_Tie();
+        tie.setTarget(new ThrowerImpl(serverOrb));
+
+        poa.activate_object(tie);
+        ior = serverOrb.object_to_string(tie.thisObject());
+        System.out.println(ior);
+    }
+
+    @BeforeClass
+    public static void createClientORB() {
+        clientOrb = initOrb(new Properties() {{
+            put("org.omg.PortableInterceptor.ORBInitializerClass." + MyClientRequestInterceptor.class.getName(),"");
+        }});
+    }
+
+    @AfterClass
+    public static void shutdownServerORB() {
+        serverOrb.shutdown(true);
+        serverOrb.destroy();
+        ior = null;
+    }
+
+    @AfterClass
+    public static void shutdownClientORB() {
+        clientOrb.shutdown(true);
+        clientOrb.destroy();
+    }
+
+    @Test(expected=MyRuntimeException.class)
+    public void testRuntimeException() throws RemoteException {
+        getThrower(clientOrb).throwRuntimeException();
+    }
+
+    @Test(expected=MyAppException.class)
+    public void testAppException() throws RemoteException, MyAppException {
+        getThrower(clientOrb).throwAppException();
+    }
+
+    private Thrower getThrower(ORB orb) {
+        Object o = orb.string_to_object(ior);
+        Thrower thrower = (Thrower) PortableRemoteObject.narrow(o, Thrower.class);
+        return thrower;
+    }
+
+    public static void main(String...args) throws Exception {
+        if (0 == args.length) {
+            System.out.println("Starting server");
+            mae = new MyAppException();
+            mre = new MyRuntimeException();
+            createServerORB();
+            System.out.println(serverOrb.getClass().getName());
+            serverOrb.run();
+        } else {
+            System.out.println("Starting client");
+            ior = args[0];
+            createClientORB();
+            System.out.println(clientOrb.getClass().getName());
+
+            RMIExceptionHandlingTest test = new RMIExceptionHandlingTest();
+            try {
+                test.testRuntimeException();
+                throw new Exception("no exception seen");
+            } catch (MyRuntimeException e) {
+            }
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/org/apache/yoko/RMITest.java b/yoko-core/src/test/java/org/apache/yoko/RMITest.java
index 9481aa6..abd3e34 100755
--- a/yoko-core/src/test/java/org/apache/yoko/RMITest.java
+++ b/yoko-core/src/test/java/org/apache/yoko/RMITest.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -17,20 +17,19 @@
  */
 package org.apache.yoko;
 
-import java.io.File;
-
+import java.nio.file.Files;
+import java.nio.file.Paths;
 
 public class RMITest extends AbstractOrbTestBase {
+    private static final String REF_FILE = "Sample.ref";
+
     public void testRMI() throws Exception {
-	server.launch();
-	File file = new File("Sample.ref");
-	if(file.exists()) {
-	    file.delete();
-	}
-	server.invokeMainAsync("test.rmi.ServerMain");
-	setWaitForFile(file);
-	waitForFile();
-	client.invokeMain("test.rmi.ClientMain");
-	server.exit(0);
+        server.launch();
+        Files.deleteIfExists(Paths.get(REF_FILE));
+        server.invokeMainAsync("test.rmi.ServerMain");
+        setWaitForFile(REF_FILE);
+        waitForFile();
+        client.invokeMain("test.rmi.ClientMain");
+        server.exit(0);
     }
 }
diff --git a/yoko-core/src/test/java/org/apache/yoko/RetryTest.java b/yoko-core/src/test/java/org/apache/yoko/RetryTest.java
index 4ce56c2..236ddc7 100755
--- a/yoko-core/src/test/java/org/apache/yoko/RetryTest.java
+++ b/yoko-core/src/test/java/org/apache/yoko/RetryTest.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -17,14 +17,11 @@
  */
 package org.apache.yoko;
 
-import java.io.File;
-
 public class RetryTest extends AbstractOrbTestBase {
     public static final String SERVER_CLASS = "test.retry.Server";
     public static final String CLIENT_CLASS = "test.retry.Client";
-    public static File waitForFile = new File("Test.ref");
     public void testRetry() throws Exception {
-        setWaitForFile(waitForFile);
+        setWaitForFile("Test.ref");
         runServerClientTest(SERVER_CLASS, CLIENT_CLASS);
     }
 }
diff --git a/yoko-core/src/test/java/org/apache/yoko/TestFrameworkTest.java b/yoko-core/src/test/java/org/apache/yoko/TestFrameworkTest.java
new file mode 100644
index 0000000..7fa7c23
--- /dev/null
+++ b/yoko-core/src/test/java/org/apache/yoko/TestFrameworkTest.java
@@ -0,0 +1,173 @@
+/**
+ *
+ * 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.
+ */
+
+/**
+ * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
+ */
+package org.apache.yoko;
+
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+/**
+ * This test is only to ensure the framework is correctly reporting failures in
+ * server and client processes.
+ * @author nrichard
+ */
+public class TestFrameworkTest extends AbstractOrbTestBase {
+    private static final String TEST_FILE = "FrameworkTest.txt";
+
+    public void setUp() throws Exception {
+        super.setUp();
+        setWaitForFile(TEST_FILE);
+        System.setProperty("server.forked", "true");
+        System.setProperty("client.forked", "true");
+    }
+
+    public void tearDown() throws Exception {
+        super.tearDown();
+        System.getProperties().remove("server.forked");
+        System.getProperties().remove("client.forked");
+    }
+
+    public void testGoodClasses() throws Exception {
+        runServerClientTest(GoodServer.class.getName(), GoodClient.class.getName());
+    }
+
+    public void testBadClasses() throws Exception {
+        try {
+            runServerClientTest(BadServer.class.getName(), BadClient.class.getName());
+            fail("Should have thrown an exception");
+        } catch (Exception e) {
+            assertRootCause(Exception.class, e);
+        }
+    }
+
+    public void testWorseClasses() throws Exception {
+        try {
+            runServerClientTest(WorseServer.class.getName(), WorseClient.class.getName());
+            fail("Should have thrown an error");
+        } catch (Exception e) {
+            assertRootCause(Error.class, e);
+        }
+    }
+
+    public void testBadServer() throws Exception {
+        try {
+            runServerClientTest(BadServer.class.getName(), GoodClient.class.getName());
+            fail("Should have thrown an exception");
+        } catch (Exception e) {
+            assertRootCause(Exception.class, e);
+        }
+    }
+
+    public void testWorseServer() throws Exception {
+        try {
+            runServerClientTest(WorseServer.class.getName(), GoodClient.class.getName());
+            fail("Should have thrown an error");
+        } catch (Exception e) {
+            assertRootCause(Error.class, e);
+        }
+    }
+
+    public void testBadClient() throws Exception {
+        try {
+            runServerClientTest(GoodServer.class.getName(), BadClient.class.getName());
+            fail("Should have thrown an exception");
+        } catch (Exception e) {
+            assertRootCause(Exception.class, e);
+        }
+    }
+
+    public void testWorseClient() throws Exception {
+        try {
+            runServerClientTest(GoodServer.class.getName(), WorseClient.class.getName());
+            fail("Should have thrown an error");
+        } catch (Exception e) {
+            assertRootCause(Error.class, e);
+        }
+    }
+
+    private void assertRootCause(Class<? extends Throwable> expectedExceptionClass, Throwable t) {
+        while (t.getCause() != null)
+            t = t.getCause();
+        assertEquals(expectedExceptionClass, t.getClass());
+    }
+
+    public static final class GoodServer {
+
+        public static void main(String[] args) throws Exception {
+            try (FileWriter fw = new FileWriter(TEST_FILE)) {
+                try (PrintWriter pw = new PrintWriter(fw)) {
+                    pw.println("Hello, World.");
+                }
+            }
+        }
+    }
+
+    public static final class GoodClient {
+        public static void main(String[] args) throws Exception {
+            Files.delete(Paths.get(TEST_FILE));
+        }
+    }
+
+    public static final class BadServer {
+        public static void main(String[] args) throws Exception {
+            GoodServer.main(args);
+            throw new Exception();
+        }
+    }
+
+    public static final class BadClient {
+        public static void main(String[] args) throws Exception {
+            GoodClient.main(args);
+            throw new Exception();
+        }
+    }
+
+    public static final class WorseServer {
+        public static void main(String[] args) throws Exception {
+            GoodServer.main(args);
+            throw new Error();
+        }
+    }
+
+    public static final class WorseClient {
+        public static void main(String[] args) throws Exception {
+            GoodClient.main(args);
+            throw new Error();
+        }
+    }
+
+    public static final class WorstServer {
+        public static void main(String[] args) throws Exception {
+            GoodServer.main(args);
+            System.exit(1);
+        }
+    }
+
+    public static final class WorstClient {
+        public static void main(String[] args) throws Exception {
+            GoodClient.main(args);
+            System.exit(2);
+        }
+    }
+
+}
diff --git a/yoko-core/src/test/java/org/apache/yoko/TestFrameworkUnforkedTest.java b/yoko-core/src/test/java/org/apache/yoko/TestFrameworkUnforkedTest.java
new file mode 100644
index 0000000..e4b10e7
--- /dev/null
+++ b/yoko-core/src/test/java/org/apache/yoko/TestFrameworkUnforkedTest.java
@@ -0,0 +1,11 @@
+package org.apache.yoko;
+
+public class TestFrameworkUnforkedTest extends TestFrameworkTest {
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        System.setProperty("server.forked","false");
+        System.setProperty("client.forked","false");
+    }
+
+}
diff --git a/yoko-core/src/test/java/org/apache/yoko/processmanager/JavaProcess.java b/yoko-core/src/test/java/org/apache/yoko/processmanager/JavaProcess.java
index 844ca9d..53ed42a 100755
--- a/yoko-core/src/test/java/org/apache/yoko/processmanager/JavaProcess.java
+++ b/yoko-core/src/test/java/org/apache/yoko/processmanager/JavaProcess.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -23,7 +23,10 @@
 import java.rmi.RemoteException;
 import java.rmi.registry.Registry;
 import java.util.Properties;
+import java.util.concurrent.Callable;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 import org.apache.yoko.processmanager.internal.ProcessAgent;
 import org.apache.yoko.processmanager.internal.ProcessAgentImpl;
@@ -31,168 +34,132 @@
 
 public class JavaProcess {
 
-	private String name;
-	private Properties systemProperties;
-	private ProcessAgent processAgent;
-	private ProcessManager manager;
+    private final boolean inProcess;
+    private final String name;
+    private final Properties systemProperties;
+    private ProcessAgent processAgent;
+    private ProcessManager manager;
 
-	CountDownLatch processExited = new CountDownLatch(1);
-	CountDownLatch processStarted = new CountDownLatch(1);
+    CountDownLatch processExited = new CountDownLatch(1);
+    CountDownLatch processStarted = new CountDownLatch(1);
 
-	public JavaProcess(String name, ProcessManager manager) {
-		this.name = name;
-		this.manager = manager;
-		systemProperties = new Properties();
-		manager.registerProcess(this);
-	}
+    public JavaProcess(String name, ProcessManager manager) {
+        this.name = name;
+        this.manager = manager;
+        this.inProcess = "false".equals(System.getProperty(name + ".fork"));
+        systemProperties = new Properties();
+        manager.registerProcess(this);
+    }
 
-	/**
-	 * Sets the system properties for this process. Must be called before launch().
-	 * @param properties
-	 */
-	public void setSystemProperties(Properties properties) {
-		this.systemProperties = properties;
-	}
 
-	public void addSystemProperty(String key, String value) {
-		systemProperties.put(key, value);
-	}
+    public void addSystemProperty(String key, String value) {
+        systemProperties.put(key, value);
+    }
 
-	public void addSystemProperty(String key) {
-		systemProperties.put(key, System.getProperty(key));
-	}
+    public void addSystemProperty(String key) {
+        systemProperties.put(key, System.getProperty(key));
+    }
 
-	/**
-	 * Starts the process.
-	 *
-	 */
-	public void launch() {
-		launch(5000);
-	}
+    /**
+     * Starts the process.
+     *
+     */
+    public void launch() {
+        launch(5000);
+    }
 
-	public void launch(int timeoutMillis) {
-        final String[] javaArgs = {name, "localhost",
-                Integer.toString(Registry.REGISTRY_PORT), manager.getName()};
-        if(systemProperties == null) {
-        	systemProperties = new Properties();
+    public void launch(int timeoutMillis) {
+        try {
+            if(inProcess) {
+                ProcessAgentImpl.startLocalProcess(manager, this.name);
+            } else {                
+                Process proc = Util.execJava(ProcessAgentImpl.class.getName(), systemProperties, name, "localhost", ""+Registry.REGISTRY_PORT, manager.getName());
+                Util.redirectStream(proc.getInputStream(), System.out, name+":out");
+                Util.redirectStream(proc.getErrorStream(), System.err, name+":err");
+                waitForProcessStartup(timeoutMillis);
+            }
+        } catch(Exception e) {
+            throw new Error(e);
         }
-        if("false".equals(System.getProperty(name + ".fork"))) {
-        	try {
-        		ProcessAgentImpl.inProcessMain(javaArgs);
-        	}
-        	catch(Exception e) {
-        		throw new Error(e);
-        	}
+    }
+
+    public Object invokeMain(String className, String...args) throws InvocationTargetException {
+        return invokeStatic(className, "main", new Object[] { args });
+    }
+
+    public Future<Void> invokeMainAsync(String className, String...args) {
+        return invokeStaticAsync(className, "main", new Object[] { args });
+    }
+
+    public Future<Void> invokeStaticAsync(final String className, final String method, final Object[] args) {
+        return Executors.newSingleThreadExecutor().submit(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                invokeStatic(className, method, args);
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Invokes a static method within the process. The static method cannot return a Throwable.
+     */
+    public Object invokeStatic(String className, String method, Object[] args) throws InvocationTargetException {
+        Object result = null;
+        try {
+            result = processAgent.invokeStatic(className, method, args);
         }
-        else {
-	        try {
-	        	Process proc = Util.execJava(ProcessAgentImpl.class.getName(), systemProperties, javaArgs);
-	            Util.redirectStream(proc.getInputStream(), System.out, name+":out");
-	            Util.redirectStream(proc.getErrorStream(), System.err, name+":err");
-	            waitForProcessStartup(timeoutMillis);
-	        }
-	        catch(IOException e) {
-	        	throw new Error(e);
-	        }
-        }
-	}
-
-	public Object invokeMain(String className) throws InvocationTargetException {
-		return invokeMain(className, new String[0]);
-	}
-
-	public Object invokeMain(String className, String[] args) throws InvocationTargetException {
-		return invokeStatic(className, "main", new Object[] { args });
-	}
-
-	public Thread invokeMainAsync(String className) {
-		return invokeMainAsync(className, new String[0]);
-	}
-
-	public Thread invokeMainAsync(String className, String[] args) {
-		return invokeStaticAsync(className, "main", new Object[] { args });
-
-	}
-
-	public Thread invokeStaticAsync(final String className, final String method, final Object[] args) {
-		Thread thread = new Thread(new Runnable() {
-			public void run() {
-				try {
-					invokeStatic(className, method, args);
-				}
-				catch(InvocationTargetException e) {
-					e.printStackTrace();
-				}
-			}
-		});
-		thread.start();
-		return thread;
-	}
-
-	/**
-	 * Invokes a static method within the process. The static method cannot return a Throwable.
-	 * @param className
-	 * @param method
-	 * @param args
-	 * @return
-	 * @throws InvocationTargetException
-	 */
-	public Object invokeStatic(String className, String method, Object[] args) throws InvocationTargetException {
-		Object result = null;
-		try {
-		result = processAgent.invokeStatic(className, method, args);
-		}
-		catch(RemoteException e) {
-			if(processExited.getCount() != 0) {
+        catch(RemoteException e) {
+            if(processExited.getCount() != 0) {
                 e.printStackTrace();
-				throw new Error(e);
-			}
-			else {
-				//System.out.println("invokeStatic terminated process");
-			}
-		}
+                throw new Error(e);
+            }
+            else {
+                //System.out.println("invokeStatic terminated process");
+            }
+        }
 
-		if(result instanceof Throwable) {
-			if(result instanceof InvocationTargetException) {
-				throw (InvocationTargetException) result;
-			}
-			else throw new Error((Throwable) result);
-		}
-		return result;
-	}
+        if(result instanceof Throwable) {
+            if(result instanceof InvocationTargetException) {
+                throw (InvocationTargetException) result;
+            }
+            else throw new Error((Throwable) result);
+        }
+        return result;
+    }
 
-	protected void setAgent(ProcessAgent agent) {
-		this.processAgent = agent;
-	}
+    protected void setAgent(ProcessAgent agent) {
+        this.processAgent = agent;
+    }
 
-	public String getName() { return name; }
+    public String getName() { return name; }
 
-	/**
-	 * Terminates the process with the given exit code. Waits for the process to terminate.
-	 * @param exitCode
-	 */
-	public void exit(int exitCode) {
-		try {
-			processAgent.exit(exitCode);
-		}
-		catch(RemoteException e) {
-			//throw new Error(e);
-		}
-		try {
-			processExited.await();
-		} catch (InterruptedException e) {
-			throw new Error(e);
-		}
-	}
+    /**
+     * If this process is forked, this method terminates the process with the given exit code. Waits for the process to terminate.
+     * @param exitCode
+     */
+    public void exit(int exitCode) {
+        if (inProcess) return;
+        try {
+            processAgent.exit(exitCode);
+        } catch(RemoteException e) {
+            //throw new Error(e);
+        }
+        try {
+            processExited.await();
+        } catch (InterruptedException e) {
+            throw new Error(e);
+        }
+    }
 
-	private void waitForProcessStartup(int maxWaitMillis) {
-		try {
-			processStarted.await();
-		} catch (InterruptedException e) {
-			throw new Error(e);
-		}
-		if(processAgent == null) {
-			throw new Error("Failed to start client process");
-		}
-	}
+    private void waitForProcessStartup(int maxWaitMillis) {
+        try {
+            processStarted.await();
+        } catch (InterruptedException e) {
+            throw new Error(e);
+        }
+        if(processAgent == null) {
+            throw new Error("Failed to start "+name+" process");
+        }
+    }
 }
diff --git a/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/ProcessAgentImpl.java b/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/ProcessAgentImpl.java
index 99cb2cc..b9faca1 100755
--- a/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/ProcessAgentImpl.java
+++ b/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/ProcessAgentImpl.java
@@ -30,7 +30,7 @@
 import org.apache.yoko.osgi.ProviderLocator;
 
 public class ProcessAgentImpl extends UnicastRemoteObject implements ProcessAgent {
-
+    private static final long serialVersionUID = 1L;
     private String name;
     private ProcessManagerRemoteIF processManager;
     protected ProcessAgentImpl() throws RemoteException {
@@ -89,17 +89,8 @@
         }
     }
 
-    public static void inProcessMain(String[] args) throws Exception {
-        String agentName = args[0];
-        String registryHost = args[1];
-        int registryPort = Integer.parseInt(args[2]);
-        String processManagerName = args[3];
-
-        Registry reg = LocateRegistry.getRegistry(registryHost, registryPort);
-
-        final ProcessAgentImpl agent = new ProcessAgentImpl();
-        ProcessManagerRemoteIF manager = (ProcessManagerRemoteIF) reg.lookup(processManagerName);
-        agent.init(agentName,manager);
+    public static void startLocalProcess(ProcessManagerRemoteIF manager, String agentName) throws Exception {
+        new ProcessAgentImpl().init(agentName,manager);
     }
 
     private void waitForShutdown() {
diff --git a/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/Util.java b/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/Util.java
index 8723792..2b6cf3e 100755
--- a/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/Util.java
+++ b/yoko-core/src/test/java/org/apache/yoko/processmanager/internal/Util.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -33,87 +33,86 @@
 import java.util.Properties;
 
 public class Util {
-	// Forks a new java process.
-	public static Process execJava(String className, Properties props,
-			String[] javaArgs) throws IOException {
-		// Get path to java binary
-		File javaHome = new File(System.getProperty("java.home"));
-		File javaBin = new File(new File(javaHome, "bin"), "java");
+    // Forks a new java process.
+    public static Process execJava(String className, Properties props, String...javaArgs) throws IOException {
+        // Get path to java binary
+        File javaHome = new File(System.getProperty("java.home"));
+        File javaBin = new File(new File(javaHome, "bin"), "java");
 
-		// Get current class path
-		URLClassLoader cl = (URLClassLoader) Util.class.getClassLoader();
-		URL[] classPathUrls = cl.getURLs();
+        // Get current class path
+        URLClassLoader cl = (URLClassLoader) Util.class.getClassLoader();
+        URL[] classPathUrls = cl.getURLs();
 
-		// Construct list of arguments
-		List binArgs = new ArrayList();
+        // Construct list of arguments
+        List binArgs = new ArrayList();
 
-		// First argument is the java binary to run
-		binArgs.add(javaBin.getPath());
+        // First argument is the java binary to run
+        binArgs.add(javaBin.getPath());
 
-		// Add the classpath to argument list
-		binArgs.add("-classpath");
-		String classPath = ""
-				+ new File(classPathUrls[0].getPath().replaceAll("%20", " "));
-		for (int i = 1; i < classPathUrls.length; i++) {
-			classPath += File.pathSeparator
-					+ new File(classPathUrls[i].getPath()
-							.replaceAll("%20", " "));
-		}
-		classPath += "";
-		binArgs.add(classPath);
+        // Add the classpath to argument list
+        binArgs.add("-classpath");
+        String classPath = ""
+                + new File(classPathUrls[0].getPath().replaceAll("%20", " "));
+        for (int i = 1; i < classPathUrls.length; i++) {
+            classPath += File.pathSeparator
+                    + new File(classPathUrls[i].getPath()
+                            .replaceAll("%20", " "));
+        }
+        classPath += "";
+        binArgs.add(classPath);
 
-		// Add properties to argument list
-		Enumeration en = props.keys();
-		while (en.hasMoreElements()) {
-			String key = (String) en.nextElement();
-			binArgs.add("-D" + key + "=" + props.getProperty(key));
-		}
+        // Add properties to argument list
+        Enumeration en = props.keys();
+        while (en.hasMoreElements()) {
+            String key = (String) en.nextElement();
+            binArgs.add("-D" + key + "=" + props.getProperty(key));
+        }
 
-		// Add class containing main method to arg list
-		binArgs.add(className);
+        // Add class containing main method to arg list
+        binArgs.add(className);
 
-		// Add java arguments
-		for (int i = 0; i < javaArgs.length; i++) {
-			binArgs.add(javaArgs[i]);
-		}
+        // Add java arguments
+        for (int i = 0; i < javaArgs.length; i++) {
+            binArgs.add(javaArgs[i]);
+        }
 
-		// Convert arg list to array
-		String[] argArray = new String[binArgs.size()];
-		for (int i = 0; i < argArray.length; i++) {
-			argArray[i] = (String) binArgs.get(i);
-		}
+        // Convert arg list to array
+        String[] argArray = new String[binArgs.size()];
+        for (int i = 0; i < argArray.length; i++) {
+            argArray[i] = (String) binArgs.get(i);
+        }
 
-		/*for (int i = 0; i < argArray.length; i++) {
+        /*for (int i = 0; i < argArray.length; i++) {
 			System.out.print(argArray[i] + " ");
 		}
 		System.out.println(); */
 
-		// Fork process
-		return Runtime.getRuntime().exec(argArray);
-	}
+        // Fork process
+        return Runtime.getRuntime().exec(argArray);
+    }
 
-	public static void redirectStream(final InputStream in,
-			final OutputStream out, final String streamName) {
-		Thread stdoutTransferThread = new Thread() {
-			public void run() {
-				PrintWriter pw = new PrintWriter(new OutputStreamWriter(out),
-						true);
-				try {
-					BufferedReader reader = new BufferedReader(
-							new InputStreamReader(in));
-					String line;
-					while ((line = reader.readLine()) != null) {
-						pw.print("[");
-						pw.print(streamName);
-						pw.print("] ");
-						pw.println(line);
-					}
-				} catch (Throwable e) {
-					e.printStackTrace();
-					// throw new Error(e);
-				}
-			}
-		};
-		stdoutTransferThread.start();
-	}
+    public static void redirectStream(final InputStream in,
+            final OutputStream out, final String streamName) {
+        Thread stdoutTransferThread = new Thread() {
+            public void run() {
+                PrintWriter pw = new PrintWriter(new OutputStreamWriter(out),
+                        true);
+                try {
+                    BufferedReader reader = new BufferedReader(
+                            new InputStreamReader(in));
+                    String line;
+                    while ((line = reader.readLine()) != null) {
+                        pw.print("[");
+                        pw.print(streamName);
+                        pw.print("] ");
+                        pw.println(line);
+                    }
+                } catch (Throwable e) {
+                    e.printStackTrace();
+                    // throw new Error(e);
+                }
+            }
+        };
+        stdoutTransferThread.start();
+    }
 }
diff --git a/yoko-core/src/test/java/test/common/TestBase.java b/yoko-core/src/test/java/test/common/TestBase.java
index 810fd6f..e57a905 100644
--- a/yoko-core/src/test/java/test/common/TestBase.java
+++ b/yoko-core/src/test/java/test/common/TestBase.java
@@ -17,12 +17,25 @@
 
 package test.common;
 
-public class TestBase {
-    public static void TEST(boolean expr) {
-        if (!expr)
-            throw new TestException();
-    }
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.rmi.Remote;
 
+import javax.rmi.PortableRemoteObject;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.portable.IDLEntity;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+
+public class TestBase {
     public static org.omg.CORBA.TypeCode getOrigType(org.omg.CORBA.TypeCode tc) {
         org.omg.CORBA.TypeCode result = tc;
 
@@ -30,9 +43,71 @@
             while (result.kind() == org.omg.CORBA.TCKind.tk_alias)
                 result = result.content_type();
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            throw new AssertionError(ex);
         }
 
         return result;
     }
+
+    protected static void writeRef(ORB orb, PrintWriter out, org.omg.CORBA.Object obj,
+            NamingContextExt context, NameComponent[] name) throws InvalidName {
+        writeRef(orb, out, obj, context.to_string(name));
+    }
+
+    private static void writeRef(ORB orb, PrintWriter out, org.omg.CORBA.Object obj, String name) {
+        out.println("ref:");
+        out.println(orb.object_to_string(obj));
+        out.println(name);
+    }
+    
+    protected static void writeRef(ORB orb, PrintWriter out, org.omg.CORBA.Object obj) {
+        writeRef(orb, out, obj, "");
+    }
+
+    protected static String[] readRef(BufferedReader reader, String[] refStrings) throws IOException {
+        String line = reader.readLine();
+        if (line == null) {
+            throw new RuntimeException("Unknown Server error");
+        } else if (!!!line.equals("ref:")) {
+            try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
+                pw.println("Server error:");
+                do {
+                    pw.print('\t');
+                    pw.println(line);
+                } while ((line = reader.readLine()) != null);
+                pw.flush();
+                throw new RuntimeException(sw.toString());
+            }
+        }
+        refStrings[0] = reader.readLine();
+        refStrings[1] = reader.readLine();
+        return refStrings;
+    }
+
+    private static org.omg.CORBA.Object readGenericStub(ORB orb, BufferedReader reader) throws IOException {
+        return orb.string_to_object(readRef(reader, new String[2])[0]);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected static<T extends Remote> T readRmiStub(ORB orb, BufferedReader reader, Class<T> type) throws ClassCastException, IOException {
+        return (T)PortableRemoteObject.narrow(readGenericStub(orb, reader), type);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected static<T extends IDLEntity> T readIdlStub(ORB orb, BufferedReader reader, Class<T> type) throws ClassCastException, IOException {
+        return (T)PortableRemoteObject.narrow(readGenericStub(orb, reader), type);
+    }
+
+    protected static BufferedReader openFileReader(final String refFile) throws FileNotFoundException {
+        return new BufferedReader(new FileReader(refFile)) {
+            @Override
+            public void close() throws IOException {
+                try {
+                    super.close();
+                } finally {
+                    Files.delete(Paths.get(refFile));
+                }
+            }
+        };
+    }
 }
diff --git a/yoko-core/src/test/java/test/fvd/Abstract.java b/yoko-core/src/test/java/test/fvd/Abstract.java
new file mode 100644
index 0000000..cc853b0
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/Abstract.java
@@ -0,0 +1,7 @@
+package test.fvd;
+
+import java.io.Serializable;
+
+public interface Abstract extends Serializable {
+
+}
diff --git a/yoko-core/src/test/java/test/fvd/ApeClassLoader.java b/yoko-core/src/test/java/test/fvd/ApeClassLoader.java
new file mode 100644
index 0000000..c3b7777
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/ApeClassLoader.java
@@ -0,0 +1,87 @@
+package test.fvd;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URLClassLoader;
+import java.util.HashSet;
+import java.util.Set;
+
+public final class ApeClassLoader extends URLClassLoader {
+    private final Set<String> skipClassNames = new HashSet<>();
+
+    public ApeClassLoader() {
+        super(((URLClassLoader)ApeClassLoader.class.getClassLoader()).getURLs(), 
+                ApeClassLoader.class.getClassLoader().getParent());
+    }
+
+    public ApeClassLoader doNotLoad(Class<?>... types) {
+        for (Class<?> type : types)
+            skipClassNames.add(type.getName());
+        return this;
+    }
+
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        if (skipClassNames.contains(name))
+            throw new ClassNotFoundException(name);
+        return super.findClass(name);
+    }
+
+    public boolean apeMain(String...args) {
+        if (alreadyAped()) {
+            System.out.println("invoked from an already aped main() in target loader " + this.getClass().getClassLoader());
+            return false;
+        }
+        System.out.println("aping call to main() from class loader " + this.getClass().getClassLoader());
+        invokeApedMain(args);
+        return true;
+    }
+
+    private static boolean alreadyAped() {
+        String expectedLoader = ApeClassLoader.class.getName();
+        String actualLoader = ApeClassLoader.class.getClassLoader().getClass().getName();
+        return expectedLoader.equals(actualLoader);
+    }
+
+    private void invokeApedMain(String...args) {
+        final String className = getCallerClassName();
+        final ClassLoader oldTCCL = Thread.currentThread().getContextClassLoader();
+        Thread.currentThread().setContextClassLoader(this);
+        try {
+            Class<?> targetClass = Class.forName(className, true, this);
+            Method m = targetClass.getMethod("main", String[].class);
+            // m.invoke(null, (Object[])args); // BAD
+            m.invoke(null, (Object)args);     // GOOD
+        } catch (ClassNotFoundException e) {
+            throw new Error("Failed to load mirrored class " + className, e);
+        } catch (NoSuchMethodException | SecurityException e) {
+            throw new Error("Failed to get method main(String[]) for mirrored class " + className, e);
+        } catch (IllegalAccessException | IllegalArgumentException e) {
+            throw new Error("Failed to invoke method main(String[]) for mirrored class" + className, e);
+        } catch (InvocationTargetException e) {
+            rethrow(e.getTargetException());
+            throw new AssertionError("This code should be unreachable");
+        } finally {
+            Thread.currentThread().setContextClassLoader(oldTCCL);
+        }
+    }
+
+    private static void rethrow(Throwable t) throws RuntimeException {
+        ApeClassLoader.<RuntimeException>useTypeErasureMadnessToThrowAnyCheckedException(t);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <T extends Throwable> void useTypeErasureMadnessToThrowAnyCheckedException(Throwable t) throws T {
+        throw (T)t;
+    }
+
+    private static String getCallerClassName() {
+        StackTraceElement[] frames = new Throwable().getStackTrace();
+        int i = 0;
+        // find this class in the stack
+        while (!!!frames[i].getClassName().equals(ApeClassLoader.class.getName())) i++;
+        // find the next class down in the stack
+        while (frames[i].getClassName().equals(ApeClassLoader.class.getName())) i++;
+        return frames[i].getClassName();
+    }
+}
\ No newline at end of file
diff --git a/yoko-core/src/test/java/test/fvd/Bounceable.java b/yoko-core/src/test/java/test/fvd/Bounceable.java
new file mode 100644
index 0000000..4da3033
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/Bounceable.java
@@ -0,0 +1,5 @@
+package test.fvd;
+
+public interface Bounceable extends Abstract, Value {
+    Bounceable validateAndReplace();
+}
diff --git a/yoko-core/src/test/java/test/fvd/BounceableImpl.java b/yoko-core/src/test/java/test/fvd/BounceableImpl.java
new file mode 100644
index 0000000..55a5cd6
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/BounceableImpl.java
@@ -0,0 +1,98 @@
+package test.fvd;
+
+import static test.fvd.Sets.format;
+import static test.fvd.Sets.union;
+
+import java.io.ObjectStreamField;
+import java.lang.reflect.Field;
+import java.util.Objects;
+import java.util.Set;
+
+import org.junit.Assert;
+
+class NonSerializableSuper {
+    final boolean isLocal;
+    NonSerializableSuper() { // invoked by serialization
+        isLocal = false;
+    }
+    NonSerializableSuper(String name) {
+        isLocal = true;
+    }
+}
+
+public class BounceableImpl extends NonSerializableSuper implements Bounceable {
+    private static final long serialVersionUID = 1L;
+
+    // this is the magic that makes this class marshal differently according to FieldMarshal Config
+    private static final ObjectStreamField[] serialPersistentFields = Marshalling.computeSerialPersistentFields(BounceableImpl.class);
+
+    private final Marshalling senderConfig = Marshalling.getCurrent();
+    
+    public BounceableImpl() {
+        super(null); // avoid using the no-args parent constructor
+    }
+
+    private String a = "AAA";
+
+    @Marshalling.SkipInDefaultVersion
+    private transient String b = "BBB";
+
+    @Marshalling.SkipInVersion1
+    private String c = "CCC";
+
+    @Marshalling.SkipInVersion2
+    private String d = "DDD";
+
+    private String e = "EEE";
+
+    public static void main(String[] args) {
+        System.out.println("success!");
+    }
+
+    @Override
+    public Bounceable validateAndReplace() {
+        System.out.println("Received from config " + senderConfig + " into " + Marshalling.getCurrent());
+        Assert.assertEquals(createModelInstance(), this);
+        return new BounceableImpl();
+    }
+
+    private BounceableImpl createModelInstance() throws Error {
+        BounceableImpl expected = new BounceableImpl();
+        if (isLocal) 
+            return expected;
+        try {
+            Set<Field> unread = Marshalling.getCurrent().getSkippedFields(expected);
+            Set<Field> unsent = senderConfig.getSkippedFields(expected);
+            System.out.printf("Creating model instance:%nunsent fields: %s%nunread fields: %s%n", format(unsent), format(unread));
+            for (Field f : union(unread, unsent))
+                f.set(expected, null);
+        } catch (IllegalAccessException e) {
+            throw new Error(e);
+        }
+        return expected;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("[%s|%s|%s|%s|%s]", a, b, c, d, e);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(a, b, c, d, e);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (!(obj instanceof BounceableImpl))
+            return false;
+        BounceableImpl that = (BounceableImpl) obj;
+        return Objects.equals(this.a, that.a) 
+                && Objects.equals(this.b, that.b) 
+                && Objects.equals(this.c, that.c) 
+                && Objects.equals(this.d, that.d)
+                && Objects.equals(this.e, that.e);
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/Bouncer.java b/yoko-core/src/test/java/test/fvd/Bouncer.java
new file mode 100644
index 0000000..d626d92
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/Bouncer.java
@@ -0,0 +1,13 @@
+package test.fvd;
+
+import java.io.Serializable;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Bouncer extends Remote {
+    Abstract bounceAbstract(Abstract obj) throws RemoteException;
+    Object bounceObject(Object obj) throws RemoteException;
+    Serializable bounceSerializable(Serializable obj) throws RemoteException;
+    Value bounceValue(Value obj) throws RemoteException;
+    void shutdown() throws RemoteException;
+}
diff --git a/yoko-core/src/test/java/test/fvd/BouncerImpl.java b/yoko-core/src/test/java/test/fvd/BouncerImpl.java
new file mode 100644
index 0000000..2e7c93e
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/BouncerImpl.java
@@ -0,0 +1,38 @@
+package test.fvd;
+
+import java.io.Serializable;
+
+import org.omg.CORBA.ORB;
+
+public class BouncerImpl implements Bouncer {
+    
+    final ORB orb;
+    
+    public BouncerImpl(ORB orb) {
+        this.orb = orb;
+    }
+
+    @Override
+    public Abstract bounceAbstract(Abstract obj) {
+        return ((Bounceable)obj).validateAndReplace();
+    }
+
+    @Override
+    public Object bounceObject(Object obj) {
+        return ((Bounceable)obj).validateAndReplace();
+    }
+
+    @Override
+    public Serializable bounceSerializable(Serializable obj) {
+        return ((Bounceable)obj).validateAndReplace();
+    }
+
+    @Override
+    public Value bounceValue(Value obj){
+        return ((Bounceable)obj).validateAndReplace();
+    }
+
+    public void shutdown() {
+        orb.shutdown(false);
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/Marshalling.java b/yoko-core/src/test/java/test/fvd/Marshalling.java
new file mode 100644
index 0000000..f2591cd
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/Marshalling.java
@@ -0,0 +1,238 @@
+package test.fvd;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static test.fvd.Sets.difference;
+import static test.fvd.Sets.format;
+import static test.fvd.Sets.intersection;
+
+import java.io.ObjectStreamField;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.junit.Assert;
+
+public enum Marshalling {
+    DEFAULT_VERSION(SkipInDefaultVersion.class), 
+    VERSION1(SkipInVersion1.class), 
+    VERSION2(SkipInVersion2.class);
+
+    private static final AtomicReference<Marshalling> IN_USE = new AtomicReference<>();
+    private static final Set<Class<? extends Annotation>> VALID_ANNOTATIONS;
+
+    static {
+        HashSet<Class<? extends Annotation>> set = new HashSet<>();
+        for (Marshalling mc : Marshalling.values())
+            set.add(mc.skipAnnotationType);
+        VALID_ANNOTATIONS = Collections.unmodifiableSet(set);
+    }
+
+    private final Class<? extends Annotation> skipAnnotationType;
+
+    private Marshalling(Class<? extends Annotation> annotationType) {
+        this.skipAnnotationType = annotationType;
+    }
+
+    public Marshalling select() {
+        if (IN_USE.compareAndSet(null, this)) return this;
+        Assert.fail("Attempt to select MarshallingConfiguration " + this + " when " + IN_USE.get() + " was already selected");
+        throw new Error("Unreachable code");
+    }
+
+    static Marshalling getCurrent() {
+        Marshalling current = IN_USE.get();
+        Assert.assertNotNull("A " + Marshalling.class.getSimpleName() + " setting should have been selected.", current);
+        return current;
+    }
+
+    public static ObjectStreamField[] computeSerialPersistentFields(Class<?> type) {
+        validate(type);
+
+        // check what type of marshalling is configured
+        Marshalling currentConfig = getCurrent();
+        System.out.println(currentConfig + " marshalling selected");
+        if (currentConfig == DEFAULT_VERSION) {
+            System.out.println("Using null for serialPersistentFields for type: " + type);
+            // we can coerce default serialization semantics by making the serialPersistentFields null
+            return null;
+        }
+
+        System.out.println("Constructing serialPersistentFields for type: " + type);
+
+        // build an ordered set of object stream fields
+        SortedSet<ObjectStreamField> result = new TreeSet<>(SerializationOrdering.INSTANCE);
+        for(Field f : type.getDeclaredFields()) {
+            if (Modifier.isStatic(f.getModifiers()) ||
+                    getAllAnnoTypes(f).contains(currentConfig.skipAnnotationType)) {
+                System.out.println("Excluding field from serialPersistentFields: " + f);
+            } else {
+                System.out.println("Adding field to serialPersistentFields: "+ f);
+                result.add(new ObjectStreamField(f.getName(), f.getType()));
+            }
+        }
+        return result.toArray(new ObjectStreamField[result.size()]);
+    }
+
+    private static Set<Class<? extends Annotation>> getAllAnnoTypes(Field f) {
+        HashSet<Class<? extends Annotation>> result = new HashSet<>();
+        for (Annotation a : f.getAnnotations()) result.add(a.annotationType());
+        System.out.println("anno types for field " + f + " = " + result);
+        return result;
+    }
+
+    private static Set<Class<? extends Annotation>> getSkipAnnoTypes(Field f) {
+        Set<Class<? extends Annotation>> result = getAllAnnoTypes(f);
+        result.retainAll(VALID_ANNOTATIONS);
+        return result;
+    }
+
+    private static void validate(Class<?> type) {
+        Map<?, Set<Field>> fieldsByAnnoType = createAnnoTypeMap();
+
+        checkForSerialPersistentFieldsField(type);
+
+        Set<Field> nonStaticFields = getValidatedFields(type);
+
+        for (Field f : nonStaticFields) {
+            // find the relevant annotations for this field
+            Set<?> annoTypes = getSkipAnnoTypes(f);
+            for (Object annoType : annoTypes)
+                fieldsByAnnoType.get(annoType).add(f);
+            boolean isTransient = Modifier.isTransient(f.getModifiers());
+            System.out.printf("Examining field %s: isTransient=%b anno types=%s%n", f, isTransient, annoTypes);
+            // validate all and only default persisted fields have @Default
+            Assert.assertEquals("@Marshalling.SkipInDefault should be used iff the field is transient", isTransient, annoTypes.contains(SkipInDefaultVersion.class));
+            // validate all and only non-static fields should have at least one of the VALID_ANNOTATIONS
+            Assert.assertNotEquals("No field should have all the Skip annotations", VALID_ANNOTATIONS, annoTypes);
+        }
+        checkForCommonFields(nonStaticFields, fieldsByAnnoType);
+        checkForSkippedFields(fieldsByAnnoType);
+    }
+
+    private static Set<Field> getValidatedFields(Class<?> type) {
+        Set<Field> result = new HashSet<>();
+        for (Field f : type.getDeclaredFields()) {
+            if (Modifier.isStatic(f.getModifiers())) {
+                Assert.assertTrue("Static fields should not have any Skip... annotations", getSkipAnnoTypes(f).isEmpty());
+                continue;
+            }
+            result.add(f);
+        }
+        // check there are some persistent fields
+        for (Field f : result) {
+            if (!!!Modifier.isTransient(f.getModifiers())) 
+                return result; // found at least one persistent field!
+        }
+        Assert.fail("The class " + type + " should declare some non-transient, non-static fields");
+        throw new Error("Unreachable code!");
+    }
+
+    private static void checkForSerialPersistentFieldsField(Class<?> type) {
+        // first and foremost - the class must declare serialPersistentFields 
+        try {
+            Field spff = type.getDeclaredField("serialPersistentFields");
+            // field must be private (probably)
+            Assert.assertTrue(spff + " should be private", Modifier.isPrivate(spff.getModifiers()));
+            // field must be static
+            Assert.assertTrue(spff + " should be static", Modifier.isStatic(spff.getModifiers()));
+            // field must be final
+            Assert.assertTrue(spff + " should be final", Modifier.isFinal(spff.getModifiers()));
+            // field must be of type ObjectStreamField[]
+            Assert.assertEquals(spff + " should be of type ObjectStreamField[]", ObjectStreamField[].class, spff.getType());
+        } catch (NoSuchFieldException | SecurityException e) {
+            e.printStackTrace();
+            Assert.fail("Class " + type + " must declare serialPersistentFields");
+        }
+    }
+
+    private static void checkForCommonFields(Set<Field> allFields, Map<?, Set<Field>> fieldsByAnnoType) {
+        // compare each combination of two configs
+        Queue<Marshalling> configs = new LinkedList<>(Arrays.asList(Marshalling.values()));
+        do {
+            Marshalling leftConfig = configs.remove();
+            Set<Field> leftFields = difference(allFields, fieldsByAnnoType.get(leftConfig.skipAnnotationType));
+            for (Marshalling rightConfig: configs) {
+                Set<Field> rightFields = difference(allFields, fieldsByAnnoType.get(rightConfig.skipAnnotationType));
+                Set<Field> commonFields = intersection(leftFields, rightFields);
+                System.out.printf("When communicating between %s and %s, the common fields are %s%n", leftConfig, rightConfig, format(commonFields));
+                Assert.assertNotEquals("There should be some common fields between versions " + leftConfig + " and " + rightConfig , Collections.emptySet(), commonFields);
+            }
+        } while(!!!configs.isEmpty());
+    }
+
+    private static void checkForSkippedFields(Map<?, Set<Field>> fieldsByAnnoType) {
+        // compare each permutation of two configs
+        for (Marshalling sender : Marshalling.values()) {
+            Set<Field> unsentFields = fieldsByAnnoType.get(sender.skipAnnotationType);
+            for (Marshalling receiver : Marshalling.values()) {
+                if (sender == receiver)
+                    continue;
+                Set<Field> skippedFields = difference(fieldsByAnnoType.get(receiver.skipAnnotationType), unsentFields);
+                System.out.printf("When %s transmits to %s, the skipped fields are %s%n", sender, receiver, format(skippedFields));
+                Assert.assertNotEquals("There should be some skipped fields when " + sender + " sends to " + receiver, 
+                        Collections.emptySet(), skippedFields);
+            }
+        }
+    }
+
+    private static Map<Class<? extends Annotation>, Set<Field>> createAnnoTypeMap() {
+        Map<Class<? extends Annotation>, Set<Field>> fieldsByAnnotationType = new HashMap<>();
+        // fill the map with empty sets for each annotation we are considering
+        for (Class<? extends Annotation> annotationType : VALID_ANNOTATIONS)
+            fieldsByAnnotationType.put(annotationType, new HashSet<Field>());
+        return fieldsByAnnotationType;
+    }
+
+    public Set<Field> getSkippedFields(Object expected) {
+        Set<Field> result = new HashSet<>();
+        for (Field f: getValidatedFields(expected.getClass()))
+            if (getAllAnnoTypes(f).contains(skipAnnotationType))
+                result.add(f);
+        return result;
+    }
+
+    @Retention(RUNTIME)
+    @Target(FIELD)
+    @Documented
+    public @interface SkipInDefaultVersion {}
+    @Retention(RUNTIME)
+    @Target(FIELD)
+    @Documented
+    public @interface SkipInVersion1 {}
+    @Retention(RUNTIME)
+    @Target(FIELD)
+    @Documented
+    public @interface SkipInVersion2 {}
+
+    /**
+     * The serialization spec dictates that primitive fields are serialized before Objects, 
+     * and each group is sorted by the natural ordering of their names @see {@link String#compareTo(String)}
+     */
+    private static enum SerializationOrdering implements Comparator<ObjectStreamField> {
+        INSTANCE;
+        @Override
+        public int compare(ObjectStreamField f1, ObjectStreamField f2) {
+            boolean f1IsPrim = f1.getType().isPrimitive();
+            boolean f2IsPrim = f2.getType().isPrimitive();
+            if (f1IsPrim == f2IsPrim) 
+                return f1.getName().compareTo(f2.getName());
+            return f1IsPrim ? -1 : 1;
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/MissingFields.java b/yoko-core/src/test/java/test/fvd/MissingFields.java
new file mode 100644
index 0000000..f25d123
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/MissingFields.java
@@ -0,0 +1,25 @@
+package test.fvd;
+
+import static test.fvd.Marshalling.VERSION1;
+import static test.fvd.Marshalling.VERSION2;
+
+import java.io.File;
+
+import org.apache.yoko.AbstractOrbTestBase;
+
+public class MissingFields {
+    public static void main(String[] args) throws Exception {
+        final String fileName = "bouncer.ref";
+        final String[] serverArgs = { fileName, VERSION1.name(), VERSION2.name() };
+        final String[] clientArgs = serverArgs;
+        new Thread() {
+            @Override
+            public void run() {
+                MissingFieldsServer.main(serverArgs);
+            }
+        }.start();
+        AbstractOrbTestBase.waitFor(new File(fileName), 20000);
+        Thread.sleep(2000);
+        MissingFieldsClient.main(clientArgs);
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/MissingFieldsClient.java b/yoko-core/src/test/java/test/fvd/MissingFieldsClient.java
new file mode 100644
index 0000000..62ab7f1
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/MissingFieldsClient.java
@@ -0,0 +1,38 @@
+package test.fvd;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import org.omg.CORBA.ORB;
+
+import test.common.TestBase;
+
+public class MissingFieldsClient extends TestBase {
+
+    private static final ApeClassLoader apeLoader = new ApeClassLoader().doNotLoad();
+
+    public static void main(String...args) throws Exception {
+        if (apeLoader.apeMain(args))
+            return;
+        ////////////////////// CODE BELOW HERE EXECUTES IN APE LOADER ONLY //////////////////////
+        final String refFile = args[0];
+        Marshalling.valueOf(args[1]).select(); // client version
+        Marshalling.valueOf(args[2]);          // server version
+
+        ORB orb = ORB.init(args, null);
+
+        try (BufferedReader file = openFileReader(refFile)) {
+            Bouncer bouncer = readRmiStub(orb, file, Bouncer.class);
+            try {
+                Bounceable bounceable = new BounceableImpl().validateAndReplace();
+                Bounceable returned = (Bounceable) bouncer.bounceObject(bounceable);
+                returned.validateAndReplace();
+            } finally {
+                bouncer.shutdown();
+            }
+        } finally {
+            orb.shutdown(true);
+            orb.destroy();
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/MissingFieldsServer.java b/yoko-core/src/test/java/test/fvd/MissingFieldsServer.java
new file mode 100644
index 0000000..a2f90b1
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/MissingFieldsServer.java
@@ -0,0 +1,50 @@
+package test.fvd;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Paths;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAHelper;
+import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
+import org.omg.PortableServer.POAPackage.ServantAlreadyActive;
+import org.omg.PortableServer.POAPackage.WrongPolicy;
+
+import test.common.TestBase;
+
+public class MissingFieldsServer extends TestBase {
+    static final String CLASS_NAME = new Object(){}.getClass().getEnclosingClass().getName();
+
+    private static final ApeClassLoader apeLoader = new ApeClassLoader().doNotLoad();
+
+    public static void main(String...args) {
+        if (apeLoader.apeMain(args)) return;
+        ////////////////////// CODE BELOW HERE EXECUTES IN APE LOADER ONLY //////////////////////
+        final String refFile = args[0];
+        Marshalling.valueOf(args[1]);          // client version
+        Marshalling.valueOf(args[2]).select(); // server version
+
+        ORB orb = ORB.init(args, null);
+        System.out.println(CLASS_NAME + " opening file for writing: " + Paths.get(refFile).toAbsolutePath());
+        try (PrintWriter out = new PrintWriter(new FileWriter(refFile))) {
+            POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+            rootPOA.the_POAManager().activate();
+            ////// create a Bouncer object and write out the IOR //////
+            BouncerImpl bouncer = new BouncerImpl(orb);
+            _BouncerImpl_Tie tie = new _BouncerImpl_Tie();
+            tie.setTarget(bouncer);
+            rootPOA.activate_object(tie);
+            writeRef(orb, out, tie.thisObject());
+            out.flush();
+        } catch (IOException | InvalidName | AdapterInactive | ServantAlreadyActive | WrongPolicy e) {
+            e.printStackTrace();
+        }
+        System.out.println("Running the orb");
+        orb.run();
+        System.out.println("Destroying the orb");
+        orb.destroy();
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/Sets.java b/yoko-core/src/test/java/test/fvd/Sets.java
new file mode 100644
index 0000000..4671a20
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/Sets.java
@@ -0,0 +1,33 @@
+package test.fvd;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+public enum Sets {
+    ;
+    static <T> Set<T> union(Set<T> left, Set<T> right) {
+        HashSet<T> result = new HashSet<>(left);
+        result.addAll(right);
+        return result;
+    }
+
+    static <T> Set<T> intersection(Set<T> left, Set<T> right) {
+        HashSet<T> result = new HashSet<>(left);
+        result.retainAll(right);
+        return result;
+    }
+
+    static <T> Set<T> difference(Set<T> minuend, Set<T> subtrahend) {
+        HashSet<T> result = new HashSet<>(minuend);
+        result.removeAll(subtrahend);
+        return result;
+    }
+
+    static String format(Set<Field> fields) {
+        String result = "{";
+        for (Field field : fields)
+            result += (result.length() == 1 ? "" : ",") + field.getName();
+        return result + "}";
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/Value.java b/yoko-core/src/test/java/test/fvd/Value.java
new file mode 100644
index 0000000..99eeec5
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/Value.java
@@ -0,0 +1,7 @@
+package test.fvd;
+
+import java.io.Serializable;
+
+public interface Value extends Serializable {
+    String toString();
+}
diff --git a/yoko-core/src/test/java/test/fvd/_BouncerImpl_Tie.java b/yoko-core/src/test/java/test/fvd/_BouncerImpl_Tie.java
new file mode 100644
index 0000000..7cffbc1
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/_BouncerImpl_Tie.java
@@ -0,0 +1,145 @@
+// POA Tie class generated by rmic, do not edit.
+// Contents subject to change without notice.
+
+package test.fvd;
+
+import java.io.Serializable;
+import java.lang.ClassCastException;
+import java.lang.Object;
+import java.lang.String;
+import java.lang.Throwable;
+import java.rmi.Remote;
+import javax.rmi.CORBA.Tie;
+import javax.rmi.CORBA.Util;
+import org.omg.CORBA.BAD_OPERATION;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.ResponseHandler;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAPackage.ObjectNotActive;
+import org.omg.PortableServer.POAPackage.ServantNotActive;
+import org.omg.PortableServer.POAPackage.WrongPolicy;
+
+public class _BouncerImpl_Tie extends org.omg.PortableServer.Servant implements Tie {
+    
+    private BouncerImpl target = null;
+    
+    private static final String[] _type_ids = {
+        "RMI:test.fvd.Bouncer:0000000000000000"
+    };
+    
+    public void setTarget(Remote target) {
+        this.target = (BouncerImpl) target;
+    }
+    
+    public Remote getTarget() {
+        return target;
+    }
+    
+    public org.omg.CORBA.Object thisObject() {
+        return _this_object();
+    }
+    
+    public void deactivate() {
+        try {
+            _poa().deactivate_object(_poa().servant_to_id(this));
+        }
+        catch(WrongPolicy e) { }
+        catch(ObjectNotActive e) { }
+        catch(ServantNotActive e) { }
+    }
+    
+    public ORB orb() {
+        return _orb();
+    }
+    
+    public void orb(ORB orb) {
+        try {
+            ((org.omg.CORBA_2_3.ORB)orb).set_delegate(this);
+        }
+        catch(ClassCastException e) {
+            throw new BAD_PARAM("POA Servant needs an org.omg.CORBA_2_3.ORB");
+        }
+    }
+    
+    public String[] _all_interfaces(POA poa, byte[] objectId) { 
+        return (String [] )  _type_ids.clone();
+    }
+    
+    public OutputStream _invoke(String method, InputStream _in, ResponseHandler reply) throws SystemException {
+        try {
+            org.omg.CORBA_2_3.portable.InputStream in = 
+                (org.omg.CORBA_2_3.portable.InputStream) _in;
+            switch (method.length()) {
+                case 8: 
+                    if (method.equals("shutdown")) {
+                        return shutdown(in, reply);
+                    }
+                case 11: 
+                    if (method.equals("bounceValue")) {
+                        return bounceValue(in, reply);
+                    }
+                case 12: 
+                    if (method.equals("bounceObject")) {
+                        return bounceObject(in, reply);
+                    }
+                case 14: 
+                    if (method.equals("bounceAbstract")) {
+                        return bounceAbstract(in, reply);
+                    }
+                case 18: 
+                    if (method.equals("bounceSerializable")) {
+                        return bounceSerializable(in, reply);
+                    }
+            }
+            throw new BAD_OPERATION();
+        } catch (SystemException ex) {
+            throw ex;
+        } catch (Throwable ex) {
+            throw new UnknownException(ex);
+        }
+    }
+    
+    private OutputStream bounceAbstract(org.omg.CORBA_2_3.portable.InputStream in , ResponseHandler reply) throws Throwable {
+        Abstract arg0 = (Abstract) in.read_abstract_interface(Abstract.class);
+        Abstract result = target.bounceAbstract(arg0);
+        OutputStream out = reply.createReply();
+        Util.writeAbstractObject(out,result);
+        return out;
+    }
+    
+    private OutputStream bounceObject(org.omg.CORBA_2_3.portable.InputStream in , ResponseHandler reply) throws Throwable {
+        Object arg0 = Util.readAny(in);
+        Object result = target.bounceObject(arg0);
+        OutputStream out = reply.createReply();
+        Util.writeAny(out,result);
+        return out;
+    }
+    
+    private OutputStream bounceSerializable(org.omg.CORBA_2_3.portable.InputStream in , ResponseHandler reply) throws Throwable {
+        Serializable arg0 = (Serializable) Util.readAny(in);
+        Serializable result = target.bounceSerializable(arg0);
+        OutputStream out = reply.createReply();
+        Util.writeAny(out,result);
+        return out;
+    }
+    
+    private OutputStream bounceValue(org.omg.CORBA_2_3.portable.InputStream in , ResponseHandler reply) throws Throwable {
+        Value arg0 = (Value) in.read_value(Value.class);
+        Value result = target.bounceValue(arg0);
+        org.omg.CORBA_2_3.portable.OutputStream out = 
+            (org.omg.CORBA_2_3.portable.OutputStream) reply.createReply();
+        out.write_value((Serializable)result,Value.class);
+        return out;
+    }
+    
+    private OutputStream shutdown(org.omg.CORBA_2_3.portable.InputStream in , ResponseHandler reply) throws Throwable {
+        target.shutdown();
+        OutputStream out = reply.createReply();
+        return out;
+    }
+}
diff --git a/yoko-core/src/test/java/test/fvd/_Bouncer_Stub.java b/yoko-core/src/test/java/test/fvd/_Bouncer_Stub.java
new file mode 100644
index 0000000..866d9f3
--- /dev/null
+++ b/yoko-core/src/test/java/test/fvd/_Bouncer_Stub.java
@@ -0,0 +1,235 @@
+// Stub class generated by rmic, do not edit.
+// Contents subject to change without notice.
+
+package test.fvd;
+
+import java.io.Serializable;
+import java.lang.Object;
+import java.lang.String;
+import java.lang.Throwable;
+import java.rmi.RemoteException;
+import java.rmi.UnexpectedException;
+import javax.rmi.CORBA.Stub;
+import javax.rmi.CORBA.Util;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.ApplicationException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.RemarshalException;
+import org.omg.CORBA.portable.ServantObject;
+
+public class _Bouncer_Stub extends Stub implements Bouncer {
+
+    private static final String[] _type_ids = {
+        "RMI:test.fvd.Bouncer:0000000000000000"
+    };
+
+    public String[] _ids() {
+        return (String [] )  _type_ids.clone();
+    }
+
+    public Abstract bounceAbstract(Abstract arg0) throws RemoteException {
+        while(true) {
+            if (!Util.isLocal(this)) {
+                org.omg.CORBA_2_3.portable.InputStream in = null;
+                try {
+                    try {
+                        OutputStream out = _request("bounceAbstract", true);
+                        Util.writeAbstractObject(out,arg0);
+                        in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out);
+                        return (Abstract) in.read_abstract_interface(Abstract.class);
+                    } catch (ApplicationException ex) {
+                        in = (org.omg.CORBA_2_3.portable.InputStream) ex.getInputStream();
+                        String id = in.read_string();
+                        throw new UnexpectedException(id);
+                    } catch (RemarshalException ex) {
+                        continue;
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                } finally {
+                    _releaseReply(in);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("bounceAbstract",test.fvd.Bouncer.class);
+                if (so == null) {
+                    continue;
+                }
+                try {
+                    Abstract arg0Copy = (Abstract) Util.copyObject(arg0,_orb());
+                    Abstract result = ((test.fvd.Bouncer)so.servant).bounceAbstract(arg0Copy);
+                    return (Abstract)Util.copyObject(result,_orb());
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
+
+    public Object bounceObject(Object arg0) throws RemoteException {
+        while(true) {
+            if (!Util.isLocal(this)) {
+                InputStream in = null;
+                try {
+                    try {
+                        OutputStream out = _request("bounceObject", true);
+                        Util.writeAny(out,arg0);
+                        in = _invoke(out);
+                        return Util.readAny(in);
+                    } catch (ApplicationException ex) {
+                        in = ex.getInputStream();
+                        String id = in.read_string();
+                        throw new UnexpectedException(id);
+                    } catch (RemarshalException ex) {
+                        continue;
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                } finally {
+                    _releaseReply(in);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("bounceObject",test.fvd.Bouncer.class);
+                if (so == null) {
+                    continue;
+                }
+                try {
+                    Object arg0Copy = (Object) Util.copyObject(arg0,_orb());
+                    Object result = ((test.fvd.Bouncer)so.servant).bounceObject(arg0Copy);
+                    return (Object)Util.copyObject(result,_orb());
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
+
+    public Serializable bounceSerializable(Serializable arg0) throws RemoteException {
+        while(true) {
+            if (!Util.isLocal(this)) {
+                InputStream in = null;
+                try {
+                    try {
+                        OutputStream out = _request("bounceSerializable", true);
+                        Util.writeAny(out,arg0);
+                        in = _invoke(out);
+                        return (Serializable) Util.readAny(in);
+                    } catch (ApplicationException ex) {
+                        in = ex.getInputStream();
+                        String id = in.read_string();
+                        throw new UnexpectedException(id);
+                    } catch (RemarshalException ex) {
+                        continue;
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                } finally {
+                    _releaseReply(in);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("bounceSerializable",test.fvd.Bouncer.class);
+                if (so == null) {
+                    continue;
+                }
+                try {
+                    Serializable arg0Copy = (Serializable) Util.copyObject(arg0,_orb());
+                    Serializable result = ((test.fvd.Bouncer)so.servant).bounceSerializable(arg0Copy);
+                    return (Serializable)Util.copyObject(result,_orb());
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
+
+    public Value bounceValue(Value arg0) throws RemoteException {
+        while(true) {
+            if (!Util.isLocal(this)) {
+                org.omg.CORBA_2_3.portable.InputStream in = null;
+                try {
+                    try {
+                        org.omg.CORBA_2_3.portable.OutputStream out =
+                            (org.omg.CORBA_2_3.portable.OutputStream)
+                            _request("bounceValue", true);
+                        out.write_value((Serializable)arg0,Value.class);
+                        in = (org.omg.CORBA_2_3.portable.InputStream)_invoke(out);
+                        return (Value) in.read_value(Value.class);
+                    } catch (ApplicationException ex) {
+                        in = (org.omg.CORBA_2_3.portable.InputStream) ex.getInputStream();
+                        String id = in.read_string();
+                        throw new UnexpectedException(id);
+                    } catch (RemarshalException ex) {
+                        continue;
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                } finally {
+                    _releaseReply(in);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("bounceValue",test.fvd.Bouncer.class);
+                if (so == null) {
+                    continue;
+                }
+                try {
+                    Value arg0Copy = (Value) Util.copyObject(arg0,_orb());
+                    Value result = ((test.fvd.Bouncer)so.servant).bounceValue(arg0Copy);
+                    return (Value)Util.copyObject(result,_orb());
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
+
+    public void shutdown() throws RemoteException {
+        while(true) {
+            if (!Util.isLocal(this)) {
+                InputStream in = null;
+                try {
+                    try {
+                        OutputStream out = _request("shutdown", true);
+                        _invoke(out);
+                        return;
+                    } catch (ApplicationException ex) {
+                        in = ex.getInputStream();
+                        String id = in.read_string();
+                        throw new UnexpectedException(id);
+                    } catch (RemarshalException ex) {
+                        continue;
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                } finally {
+                    _releaseReply(in);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("shutdown",test.fvd.Bouncer.class);
+                if (so == null) {
+                    continue;
+                }
+                try {
+                    ((test.fvd.Bouncer)so.servant).shutdown();
+                    return;
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/iiopplugin/Client.java b/yoko-core/src/test/java/test/iiopplugin/Client.java
index a0360ff..a2fb830 100644
--- a/yoko-core/src/test/java/test/iiopplugin/Client.java
+++ b/yoko-core/src/test/java/test/iiopplugin/Client.java
@@ -23,7 +23,10 @@
 
 package test.iiopplugin;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 
@@ -40,13 +43,13 @@
         }
 
         Test test = TestHelper.narrow(obj);
-        TEST(test != null);
+        assertTrue(test != null);
 
         Test localTest = new LocalTest_impl();
 
         org.omg.IOP.CodecFactory factory = org.omg.IOP.CodecFactoryHelper
                 .narrow(orb.resolve_initial_references("CodecFactory"));
-        TEST(factory != null);
+        assertTrue(factory != null);
 
         org.omg.IOP.Encoding how = new org.omg.IOP.Encoding();
         how.major_version = 0;
@@ -54,7 +57,7 @@
         how.format = org.omg.IOP.ENCODING_CDR_ENCAPS.value;
 
         org.omg.IOP.Codec codec = factory.create_codec(how);
-        TEST(codec != null);
+        assertTrue(codec != null);
 
         System.out.print("Testing Codec... ");
         System.out.flush();
@@ -63,7 +66,7 @@
             TestHelper.insert(a, test);
             byte[] data = codec.encode_value(a);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
 
@@ -77,7 +80,7 @@
         try {
             test.intest(test);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
 
@@ -85,7 +88,7 @@
         System.out.flush();
         try {
             test.intest(localTest);
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.MARSHAL ex) {
             // Expected
         }
@@ -98,7 +101,7 @@
             TestHelper.insert(a, test);
             test.inany(a);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
 //        if (!ServerPlugin.testPassed()) {
@@ -106,7 +109,7 @@
 //        }
 
         if (!ClientPlugin.testPassed()) {
-            TEST(false);
+            assertTrue(false);
         }
 
         System.out.println("Done!");
diff --git a/yoko-core/src/test/java/test/iiopplugin/ClientPlugin.java b/yoko-core/src/test/java/test/iiopplugin/ClientPlugin.java
index 95a29a7..6745f05 100644
--- a/yoko-core/src/test/java/test/iiopplugin/ClientPlugin.java
+++ b/yoko-core/src/test/java/test/iiopplugin/ClientPlugin.java
@@ -30,7 +30,6 @@
 import java.net.Socket;
 
 import org.apache.yoko.orb.OCI.IIOP.ConnectionHelper;
-import org.omg.CORBA.DynAnyPackage.Invalid;
 import org.omg.CORBA.ORB;
 import org.omg.CORBA.Policy;
 import org.omg.IOP.IOR;
diff --git a/yoko-core/src/test/java/test/iiopplugin/ServerPlugin.java b/yoko-core/src/test/java/test/iiopplugin/ServerPlugin.java
index 28c7355..2f8a923 100644
--- a/yoko-core/src/test/java/test/iiopplugin/ServerPlugin.java
+++ b/yoko-core/src/test/java/test/iiopplugin/ServerPlugin.java
@@ -30,7 +30,6 @@
 import java.net.Socket;
 
 import org.apache.yoko.orb.OCI.IIOP.ConnectionHelper;
-import org.omg.CORBA.DynAnyPackage.Invalid;
 import org.omg.CORBA.Policy;
 import org.omg.CORBA.ORB;
 import org.omg.IOP.IOR;
diff --git a/yoko-core/src/test/java/test/iiopplugin/ServiceContextInterceptor.java b/yoko-core/src/test/java/test/iiopplugin/ServiceContextInterceptor.java
index faeb14a..64c2841 100644
--- a/yoko-core/src/test/java/test/iiopplugin/ServiceContextInterceptor.java
+++ b/yoko-core/src/test/java/test/iiopplugin/ServiceContextInterceptor.java
@@ -46,9 +46,9 @@
         ServerRequestInfoExt riExt = (ServerRequestInfoExt) ri;
         TransportInfo_impl connection = (TransportInfo_impl)riExt.getTransportInfo();
         if (connection != null) {
-            Socket socket = connection.socket();
-            if (socket != null) {
-                System.out.println("Retrieved socket successfully");
+            String remoteHost = connection.remote_addr();
+            if (remoteHost != null && remoteHost.length() > 0) {
+                System.out.println("Retrieved remote host successfully");
                 return;
             }
         }
diff --git a/yoko-core/src/test/java/test/ins/Server.java b/yoko-core/src/test/java/test/ins/Server.java
index d7c2840..fa81ee2 100644
--- a/yoko-core/src/test/java/test/ins/Server.java
+++ b/yoko-core/src/test/java/test/ins/Server.java
@@ -114,10 +114,8 @@
         // Create POA
         //
         Policy[] policies = new Policy[2];
-        policies[0] = poa
-                .create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);
-        policies[1] = poa
-                .create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
+        policies[0] = poa.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);
+        policies[1] = poa.create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
         POA testPOA = poa.create_POA("testPOA", manager, policies);
 
         //
diff --git a/yoko-core/src/test/java/test/local/Client.java b/yoko-core/src/test/java/test/local/Client.java
index ab26cc0..6ce6551 100644
--- a/yoko-core/src/test/java/test/local/Client.java
+++ b/yoko-core/src/test/java/test/local/Client.java
@@ -17,7 +17,10 @@
 
 package test.local;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 
@@ -34,13 +37,13 @@
         }
 
         Test test = TestHelper.narrow(obj);
-        TEST(test != null);
+        assertTrue(test != null);
 
         Test localTest = new LocalTest_impl();
 
         org.omg.IOP.CodecFactory factory = org.omg.IOP.CodecFactoryHelper
                 .narrow(orb.resolve_initial_references("CodecFactory"));
-        TEST(factory != null);
+        assertTrue(factory != null);
 
         org.omg.IOP.Encoding how = new org.omg.IOP.Encoding();
         how.major_version = 0;
@@ -48,7 +51,7 @@
         how.format = org.omg.IOP.ENCODING_CDR_ENCAPS.value;
 
         org.omg.IOP.Codec codec = factory.create_codec(how);
-        TEST(codec != null);
+        assertTrue(codec != null);
 
         System.out.print("Testing Codec... ");
         System.out.flush();
@@ -57,13 +60,13 @@
             TestHelper.insert(a, test);
             byte[] data = codec.encode_value(a);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         try {
             org.omg.CORBA.Any a = orb.create_any();
             TestHelper.insert(a, localTest);
             byte[] data = codec.encode_value(a);
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.MARSHAL ex) {
             // Expected
         }
@@ -79,7 +82,7 @@
         try {
             test.intest(test);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
 
@@ -87,7 +90,7 @@
         System.out.flush();
         try {
             test.intest(localTest);
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.MARSHAL ex) {
             // Expected
         }
@@ -100,7 +103,7 @@
             TestHelper.insert(a, test);
             test.inany(a);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
 
@@ -110,9 +113,9 @@
             org.omg.CORBA.Any a = orb.create_any();
             TestHelper.insert(a, localTest);
             Test t = TestHelper.extract(a);
-            TEST(t == localTest);
+            assertTrue(t == localTest);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
 
@@ -122,7 +125,7 @@
             org.omg.CORBA.Any a = orb.create_any();
             TestHelper.insert(a, localTest);
             test.inany(a);
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.MARSHAL ex) {
             // Expected
         }
@@ -132,7 +135,7 @@
         System.out.flush();
         try {
             Test t = test.returntest();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.MARSHAL ex) {
             // Expected
         }
@@ -143,7 +146,7 @@
         try {
             org.omg.CORBA.AnyHolder a = new org.omg.CORBA.AnyHolder();
             test.outany(a);
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.MARSHAL ex) {
             // Expected
         }
diff --git a/yoko-core/src/test/java/test/obv/Client.java b/yoko-core/src/test/java/test/obv/Client.java
index a24917e..d4bfd42 100644
--- a/yoko-core/src/test/java/test/obv/Client.java
+++ b/yoko-core/src/test/java/test/obv/Client.java
@@ -17,9 +17,13 @@
 
 package test.obv;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
+
 import test.obv.TestOBVColoPackage.*;
 
 public class Client extends test.common.TestBase {
@@ -38,70 +42,70 @@
         TestNodeHolder nodeH = new TestNodeHolder();
 
         vb = to.get_null_valuebase();
-        TEST(vb == null);
+        assertTrue(vb == null);
         to.set_null_valuebase(null);
 
         valueSub = to.get_null_valuesub();
-        TEST(valueSub == null);
+        assertTrue(valueSub == null);
         to.set_null_valuesub(null);
 
         a1 = to.get_abs_value1();
-        TEST(a1 != null);
+        assertTrue(a1 != null);
         a1.ping1();
         to.set_abs_value1(a1);
 
         a2 = to.get_abs_value2();
-        TEST(a2 != null);
+        assertTrue(a2 != null);
         a2.ping2();
         to.set_abs_value2(a2);
 
         value = to.get_value();
-        TEST(value != null);
+        assertTrue(value != null);
         value.ping1();
-        TEST(value.count == 500);
+        assertTrue(value.count == 500);
         to.set_value(value);
 
         valueSub = to.get_valuesub();
-        TEST(valueSub != null);
+        assertTrue(valueSub != null);
         valueSub.ping1();
         valueSub.ping2();
-        TEST(valueSub.count == 501);
-        TEST(valueSub.name.equals("ValueSub"));
+        assertTrue(valueSub.count == 501);
+        assertTrue(valueSub.name.equals("ValueSub"));
         to.set_valuesub(valueSub);
 
         value = to.get_valuesub_as_value();
-        TEST(value != null);
+        assertTrue(value != null);
         value.ping1();
-        TEST(value.count == 501);
+        assertTrue(value.count == 501);
         pValueSub = (TestValueSub) value;
         pValueSub.ping2();
-        TEST(pValueSub.name.equals("ValueSub"));
+        assertTrue(pValueSub.name.equals("ValueSub"));
         to.set_valuesub_as_value(value);
 
         to.get_two_values(v1H, v2H);
-        TEST(v1H.value != null);
-        TEST(v2H.value != null);
-        TEST(v1H.value == v2H.value);
+        assertTrue(v1H.value != null);
+        assertTrue(v2H.value != null);
+        assertTrue(v1H.value == v2H.value);
         v1H.value.ping1();
-        TEST(v1H.value.count == 500);
+        assertTrue(v1H.value.count == 500);
         to.set_two_values(v1H.value, v2H.value);
 
         to.get_two_valuesubs_as_values(v1H, v2H);
-        TEST(v1H.value != null);
-        TEST(v2H.value != null);
+        assertTrue(v1H.value != null);
+        assertTrue(v2H.value != null);
         v1H.value.ping1();
         v2H.value.ping1();
-        TEST(v1H.value.count == v2H.value.count);
+        assertTrue(v1H.value.count == v2H.value.count);
         s1 = (TestValueSub) v1H.value;
         s2 = (TestValueSub) v2H.value;
         s1.ping2();
         s2.ping2();
-        TEST(s1.name.equals(s2.name));
+        assertTrue(s1.name.equals(s2.name));
         to.set_two_valuesubs_as_values(v1H.value, v2H.value);
 
         IntHolder count = new IntHolder();
         to.get_node(nodeH, count);
-        TEST(count.value == nodeH.value.compute_count());
+        assertTrue(count.value == nodeH.value.compute_count());
         to.set_node(nodeH.value);
     }
 
@@ -111,22 +115,22 @@
         TestAbsValue1 a1;
 
         cust = to.get_custom();
-        TEST(cust != null);
+        assertTrue(cust != null);
         cust.ping1();
-        TEST(cust.shortVal == -99);
-        TEST(cust.longVal == -123456);
-        TEST(cust.stringVal.equals("CustomVal"));
-        TEST(cust.doubleVal == 100.997);
+        assertTrue(cust.shortVal == -99);
+        assertTrue(cust.longVal == -123456);
+        assertTrue(cust.stringVal.equals("CustomVal"));
+        assertTrue(cust.doubleVal == 100.997);
         to.set_custom(cust);
 
         a1 = to.get_abs_custom();
-        TEST(a1 != null);
+        assertTrue(a1 != null);
         a1.ping1();
         pCust = (TestCustom) a1;
-        TEST(pCust.shortVal == -99);
-        TEST(pCust.longVal == -123456);
-        TEST(pCust.stringVal.equals("CustomVal"));
-        TEST(pCust.doubleVal == 100.997);
+        assertTrue(pCust.shortVal == -99);
+        assertTrue(pCust.longVal == -123456);
+        assertTrue(pCust.stringVal.equals("CustomVal"));
+        assertTrue(pCust.doubleVal == 100.997);
         to.set_abs_custom(a1);
     }
 
@@ -135,15 +139,15 @@
 
         String sb;
         sb = to.get_string_box("hi there");
-        TEST(sb != null);
-        TEST(sb.equals("hi there"));
+        assertTrue(sb != null);
+        assertTrue(sb.equals("hi there"));
         sb = "bye now";
         to.set_string_box(sb, "bye now");
 
         TestULongBox ub;
         ub = to.get_ulong_box(999);
-        TEST(ub != null);
-        TEST(ub.value == 999);
+        assertTrue(ub != null);
+        assertTrue(ub.value == 999);
         ub = new TestULongBox(77777);
         to.set_ulong_box(ub, 77777);
 
@@ -153,10 +157,10 @@
         fs.y = 222;
         fs.radius = 3.33;
         fsb = to.get_fix_struct_box(fs);
-        TEST(fsb != null);
-        TEST(fsb.x == fs.x);
-        TEST(fsb.y == fs.y);
-        TEST(fsb.radius == fs.radius);
+        assertTrue(fsb != null);
+        assertTrue(fsb.x == fs.x);
+        assertTrue(fsb.y == fs.y);
+        assertTrue(fsb.radius == fs.radius);
         fsb = new TestFixStruct(fs.x, fs.y, fs.radius);
         to.set_fix_struct_box(fsb, fs);
 
@@ -165,9 +169,9 @@
         vs.name = "Joe Bob Briggs";
         vs.email = "jbb@cheese.com";
         vsb = to.get_var_struct_box(vs);
-        TEST(vsb != null);
-        TEST(vsb.name.equals(vs.name));
-        TEST(vsb.email.equals(vs.email));
+        assertTrue(vsb != null);
+        assertTrue(vsb.name.equals(vs.name));
+        assertTrue(vsb.email.equals(vs.email));
         vsb = new TestVarStruct(vs.name, vs.email);
         to.set_var_struct_box(vsb, vs);
 
@@ -175,8 +179,8 @@
         TestFixUnion fu = new TestFixUnion();
         fu.o((byte) 55);
         fub = to.get_fix_union_box(fu);
-        TEST(fub != null);
-        TEST(fub.o() == (byte) 55);
+        assertTrue(fub != null);
+        assertTrue(fub.o() == (byte) 55);
         fu.d(99.88);
         fub = new TestFixUnion();
         fub.d(fu.d());
@@ -186,8 +190,8 @@
         TestVarUnion vu = new TestVarUnion();
         vu.s("howdy");
         vub = to.get_var_union_box(vu);
-        TEST(vub != null);
-        TEST(vub.s().equals("howdy"));
+        assertTrue(vub != null);
+        assertTrue(vub.s().equals("howdy"));
         vu.fs(fs);
         vub = new TestVarUnion();
         vub.fs(vu.fs());
@@ -195,10 +199,10 @@
 
         short[] asb;
         asb = to.get_anon_seq_box(10);
-        TEST(asb != null);
-        TEST(asb.length == 10);
+        assertTrue(asb != null);
+        assertTrue(asb.length == 10);
         for (i = 0; i < asb.length; i++)
-            TEST(asb[i] == (short) i);
+			assertTrue(asb[i] == (short) i);
         to.set_anon_seq_box(asb, 10);
 
         String[] ssb;
@@ -207,10 +211,10 @@
             ss[i] = "s" + i;
         }
         ssb = to.get_string_seq_box(ss);
-        TEST(ssb != null);
-        TEST(ssb.length == ss.length);
+        assertTrue(ssb != null);
+        assertTrue(ssb.length == ss.length);
         for (i = 0; i < ssb.length; i++)
-            TEST(ssb[i].equals(ss[i]));
+			assertTrue(ssb[i].equals(ss[i]));
         to.set_string_seq_box(ssb, ss);
 
         TestStringBoxStruct stringbox_struct = new TestStringBoxStruct();
@@ -226,15 +230,15 @@
         TestStringBoxStruct ex_stringbox_struct = null;
         ex_stringbox_struct = TestStringBoxStructHelper.extract(test_any);
 
-        TEST(ex_stringbox_struct.a.equals(stringbox_struct.a));
-        TEST(ex_stringbox_struct.b.equals(stringbox_struct.b));
+        assertTrue(ex_stringbox_struct.a.equals(stringbox_struct.a));
+        assertTrue(ex_stringbox_struct.b.equals(stringbox_struct.b));
 
         //
         // Double check against constant values in case something happened
         // to the original instance.
         //
-        TEST(ex_stringbox_struct.a.equals("foo"));
-        TEST(ex_stringbox_struct.b.equals("bar"));
+        assertTrue(ex_stringbox_struct.a.equals("foo"));
+        assertTrue(ex_stringbox_struct.b.equals("bar"));
 
         //
         // Identical values. This tests a bug in ValueReader that
@@ -248,15 +252,15 @@
 
         ex_stringbox_struct = TestStringBoxStructHelper.extract(test_any);
 
-        TEST(ex_stringbox_struct.a.equals(stringbox_struct.a));
-        TEST(ex_stringbox_struct.b.equals(stringbox_struct.b));
+        assertTrue(ex_stringbox_struct.a.equals(stringbox_struct.a));
+        assertTrue(ex_stringbox_struct.b.equals(stringbox_struct.b));
 
         //
         // Double check against constant values in case something happened
         // to the original instance.
         //
-        TEST(ex_stringbox_struct.a.equals("foo"));
-        TEST(ex_stringbox_struct.b.equals("foo"));
+        assertTrue(ex_stringbox_struct.a.equals("foo"));
+        assertTrue(ex_stringbox_struct.b.equals("foo"));
     }
 
     static void testCollocated(ORB orb, TestOBV to)
@@ -278,7 +282,7 @@
         TestOBVColo colo = coloImpl._this(orb);
 
         v1 = to.get_value();
-        TEST(v1 != null);
+        assertTrue(v1 != null);
 
         //
         // Test: valuetype arguments
@@ -289,24 +293,24 @@
 
         colo.test_value_attribute(null);
         vr = colo.test_value_attribute();
-        TEST(vr == null);
+        assertTrue(vr == null);
 
         vr = colo.test_value_op(null, v2, v3);
-        TEST(vr == null);
-        TEST(v2.value == null);
-        TEST(v3.value == null);
+        assertTrue(vr == null);
+        assertTrue(v2.value == null);
+        assertTrue(v3.value == null);
 
         colo.test_value_attribute(v1);
-        TEST(v1.count == 111);
+        assertTrue(v1.count == 111);
 
         v1.count = 222;
         colo.set_expected_count(222);
 
         v2.value = v1;
         vr = colo.test_value_op(v1, v2, v3);
-        TEST(vr == v2.value);
-        TEST(v3.value == v2.value);
-        TEST(v1.count == 222);
+        assertTrue(vr == v2.value);
+        assertTrue(v3.value == v2.value);
+        assertTrue(v1.count == 222);
 
         //
         // Test: struct arguments containing valuetypes
@@ -321,16 +325,16 @@
         colo.set_expected_count(111);
 
         colo.test_value_struct_attribute(s1);
-        TEST(s1.val.count == 111);
+        assertTrue(s1.val.count == 111);
         sr = colo.test_value_struct_attribute();
-        TEST(sr.val == null);
+        assertTrue(sr.val == null);
 
         s1.val = null;
         s2.value = new SV(s1.str, s1.val);
         sr = colo.test_value_struct_op(s1, s2, s3);
-        TEST(sr.val == null);
-        TEST(s2.value.val == null);
-        TEST(s3.value.val == null);
+        assertTrue(sr.val == null);
+        assertTrue(s2.value.val == null);
+        assertTrue(s3.value.val == null);
 
         s1.val = v1;
         s1.val.count = 222;
@@ -338,9 +342,9 @@
 
         s2.value = new SV(s1.str, s1.val);
         sr = colo.test_value_struct_op(s1, s2, s3);
-        TEST(sr.val == s2.value.val);
-        TEST(s3.value.val == s2.value.val);
-        TEST(s1.val.count == 222);
+        assertTrue(sr.val == s2.value.val);
+        assertTrue(s3.value.val == s2.value.val);
+        assertTrue(s1.val.count == 222);
 
         //
         // Test: union arguments containing valuetypes
@@ -354,17 +358,17 @@
         colo.set_expected_count(111);
 
         colo.test_value_union_attribute(u1);
-        TEST(u1.val().count == 111);
+        assertTrue(u1.val().count == 111);
         ur = colo.test_value_union_attribute();
-        TEST(ur.val() == null);
+        assertTrue(ur.val() == null);
 
         u1.val(null);
         u2.value = new UV();
         u2.value.val(null);
         ur = colo.test_value_union_op(u1, u2, u3);
-        TEST(ur.val() == null);
-        TEST(u2.value.val() == null);
-        TEST(u3.value.val() == null);
+        assertTrue(ur.val() == null);
+        assertTrue(u2.value.val() == null);
+        assertTrue(u3.value.val() == null);
 
         u1.val(v1);
         u1.val().count = 222;
@@ -373,9 +377,9 @@
         u2.value = new UV();
         u2.value.val(u1.val());
         ur = colo.test_value_union_op(u1, u2, u3);
-        TEST(ur.val() == u2.value.val());
-        TEST(u3.value.val() == u2.value.val());
-        TEST(u1.val().count == 222);
+        assertTrue(ur.val() == u2.value.val());
+        assertTrue(u3.value.val() == u2.value.val());
+        assertTrue(u1.val().count == 222);
 
         //
         // Test: sequence arguments containing valuetypes
@@ -392,10 +396,10 @@
         colo.set_expected_count(111);
 
         colo.test_value_seq_attribute(seq1);
-        TEST(v1.count == 111);
+        assertTrue(v1.count == 111);
         seqr = colo.test_value_seq_attribute();
         for (int i = 0; i < seqr.length; i++)
-            TEST(seqr[i] == null);
+			assertTrue(seqr[i] == null);
 
         seq1[0] = null;
         seq1[1] = null;
@@ -403,11 +407,11 @@
         seq2.value = new TestValue[3];
         seqr = colo.test_value_seq_op(seq1, seq2, seq3);
         for (int i = 0; i < seqr.length; i++)
-            TEST(seqr[i] == null);
+			assertTrue(seqr[i] == null);
         for (int i = 0; i < seq2.value.length; i++)
-            TEST(seq2.value[i] == null);
+			assertTrue(seq2.value[i] == null);
         for (int i = 0; i < seq3.value.length; i++)
-            TEST(seq3.value[i] == null);
+			assertTrue(seq3.value[i] == null);
 
         v1.count = 222;
         seq1[0] = v1;
@@ -418,14 +422,14 @@
         seq2.value = new TestValue[3];
         System.arraycopy(seq1, 0, seq2.value, 0, seq1.length);
         seqr = colo.test_value_seq_op(seq1, seq2, seq3);
-        TEST(v1.count == 222);
-        TEST(seqr.length == seq1.length);
-        TEST(seq2.value.length == seq1.length);
-        TEST(seq3.value.length == seq1.length);
+        assertTrue(v1.count == 222);
+        assertTrue(seqr.length == seq1.length);
+        assertTrue(seq2.value.length == seq1.length);
+        assertTrue(seq3.value.length == seq1.length);
         for (int i = 0; i < seq2.value.length; i++) {
-            TEST(seq2.value[i] == seq2.value[0]);
-            TEST(seqr[i] == seq2.value[0]);
-            TEST(seq3.value[i] == seq2.value[0]);
+            assertTrue(seq2.value[i] == seq2.value[0]);
+            assertTrue(seqr[i] == seq2.value[0]);
+            assertTrue(seq3.value[i] == seq2.value[0]);
         }
 
         //
@@ -435,7 +439,7 @@
         TestAbstract abstractInterface = to.get_ai_interface();
         TestAbstract abstractValue = to.get_ai_value();
         TestValueAI vai = (TestValueAI) abstractValue;
-        TEST(vai != null);
+        assertTrue(vai != null);
 
         colo.test_abstract_attribute(null);
         colo.test_abstract_op(null);
@@ -446,12 +450,12 @@
         vai.count = 333;
         colo.set_expected_count(333);
         colo.test_abstract_attribute(abstractValue);
-        TEST(vai.count == 333);
+        assertTrue(vai.count == 333);
 
         vai.count = 444;
         colo.set_expected_count(444);
         colo.test_abstract_op(abstractValue);
-        TEST(vai.count == 444);
+        assertTrue(vai.count == 444);
     }
 
     static void testAbstract(ORB orb, TestOBV to) {
@@ -463,7 +467,7 @@
         Any any;
 
         ai = to.get_ai_interface();
-        TEST(ai != null);
+        assertTrue(ai != null);
         obj = (org.omg.CORBA.Object) ai;
         ai.abstract_op();
         sub = TestAbstractSubHelper.narrow(ai);
@@ -472,7 +476,7 @@
 
         any = to.get_ai_interface_any();
         obj = any.extract_Object();
-        TEST(obj != null);
+        assertTrue(obj != null);
         sub = TestAbstractSubHelper.narrow(obj);
         sub.abstract_op();
         sub.sub_op();
@@ -482,7 +486,7 @@
         vb = (java.io.Serializable) ai;
         ai.abstract_op();
         v = (TestValueAI) ai;
-        TEST(v.count == 12345);
+        assertTrue(v.count == 12345);
         to.set_ai_value(ai);
     }
 
@@ -500,13 +504,13 @@
         TestTrunc1Factory_impl.install(orb);
         truncBase = to.get_trunc1();
         trunc1 = (TestTrunc1) truncBase;
-        TEST(trunc1.cost > 1.99 && trunc1.cost < 2.0);
-        TEST(trunc1.boolVal == true);
+        assertTrue(trunc1.cost > 1.99 && trunc1.cost < 2.0);
+        assertTrue(trunc1.boolVal == true);
         a = trunc1.v;
-        TEST(a != null);
+        assertTrue(a != null);
         v = (TestValue) a;
-        TEST(v.count == 999);
-        TEST(trunc1.shortVal == 12667);
+        assertTrue(v.count == 999);
+        assertTrue(trunc1.shortVal == 12667);
 
         //
         // With factory removed, we should not be able to downcast to
@@ -516,11 +520,11 @@
         truncBase = to.get_trunc1();
         try {
             trunc1 = (TestTrunc1) truncBase;
-            TEST(false);
+            assertTrue(false);
         } catch (ClassCastException ex) {
             // expected
         }
-        TEST(truncBase.cost > 1.99 && truncBase.cost < 2.0);
+        assertTrue(truncBase.cost > 1.99 && truncBase.cost < 2.0);
 
         //
         // With factories installed, we should be able to downcast to
@@ -530,21 +534,21 @@
         TestTrunc2Factory_impl.install(orb);
         truncBase = to.get_trunc2();
         trunc2 = (TestTrunc2) truncBase;
-        TEST(trunc2.cost > 5.99 && trunc2.cost < 6.0);
+        assertTrue(trunc2.cost > 5.99 && trunc2.cost < 6.0);
         trunc1 = (TestTrunc1) trunc2.t;
-        TEST(trunc1.cost > 1.99 && trunc1.cost < 2.0);
-        TEST(trunc1.boolVal == true);
+        assertTrue(trunc1.cost > 1.99 && trunc1.cost < 2.0);
+        assertTrue(trunc1.boolVal == true);
         a = trunc1.v;
-        TEST(a != null);
+        assertTrue(a != null);
         v = (TestValue) a;
-        TEST(v.count == 999);
-        TEST(trunc1.shortVal == 12667);
+        assertTrue(v.count == 999);
+        assertTrue(trunc1.shortVal == 12667);
         a = trunc2.a;
-        TEST(a != null);
+        assertTrue(a != null);
         v = (TestValue) a;
-        TEST(v.count == 9999);
-        TEST(trunc2.v == trunc1.v); // indirection
-        TEST(trunc2.b == trunc1); // indirection
+        assertTrue(v.count == 9999);
+        assertTrue(trunc2.v == trunc1.v); // indirection
+        assertTrue(trunc2.b == trunc1); // indirection
 
         //
         // Without a factory for TestTrunc1, some nested values of TestTrunc2
@@ -553,22 +557,22 @@
         orb_2_3.unregister_value_factory(TestTrunc1Helper.id());
         truncBase = to.get_trunc2();
         trunc2 = (TestTrunc2) truncBase;
-        TEST(trunc2.cost > 5.99 && trunc2.cost < 6.0);
-        TEST(trunc2.t != null);
+        assertTrue(trunc2.cost > 5.99 && trunc2.cost < 6.0);
+        assertTrue(trunc2.t != null);
         try {
             trunc1 = (TestTrunc1) trunc2.t;
-            TEST(false);
+            assertTrue(false);
         } catch (ClassCastException ex) {
             // expected
         }
-        TEST(trunc2.t.cost > 1.99 && trunc2.t.cost < 2.0);
+        assertTrue(trunc2.t.cost > 1.99 && trunc2.t.cost < 2.0);
         a = trunc2.a;
-        TEST(a != null);
+        assertTrue(a != null);
         v = (TestValue) a;
-        TEST(v.count == 9999);
-        TEST(trunc2.v != null); // indirection
-        TEST(trunc2.v.count == 999); // indirection
-        TEST(trunc2.b == trunc2.t); // indirection
+        assertTrue(v.count == 9999);
+        assertTrue(trunc2.v != null); // indirection
+        assertTrue(trunc2.v.count == 999); // indirection
+        assertTrue(trunc2.b == trunc2.t); // indirection
 
         //
         // With factory removed, we should not be able to downcast to
@@ -579,11 +583,11 @@
         truncBase = to.get_trunc2();
         try {
             trunc2 = (TestTrunc2) truncBase;
-            TEST(false);
+            assertTrue(false);
         } catch (ClassCastException ex) {
             // expected
         }
-        TEST(truncBase.cost > 5.99 && truncBase.cost < 6.0);
+        assertTrue(truncBase.cost > 5.99 && truncBase.cost < 6.0);
 
         //
         // Leave factories in original state
@@ -626,7 +630,7 @@
         //
         try {
             v2 = TestValueHelper.extract(av);
-            TEST(false);
+            assertTrue(false);
         } catch (MARSHAL ex) {
             // expected
         }
@@ -637,8 +641,8 @@
         TestValueFactory_impl.install(orb);
         to.remarshal_any(av); // uses factory instead of TypeCode
         v2 = TestValueHelper.extract(av);
-        TEST(v2 != null);
-        TEST(v2.count == 500);
+        assertTrue(v2 != null);
+        assertTrue(v2.count == 500);
 
         //
         // Test simple valuetype inheritance
@@ -659,9 +663,9 @@
         TestValueSubFactory_impl.install(orb);
         to.remarshal_any(av); // uses factory instead of TypeCode
         sub = TestValueSubHelper.extract(av);
-        TEST(sub != null);
-        TEST(sub.count == 501);
-        TEST(sub.name.equals("ValueSub"));
+        assertTrue(sub != null);
+        assertTrue(sub.count == 501);
+        assertTrue(sub.name.equals("ValueSub"));
 
         //
         // Obtain an any whose TypeCode is TestValue, but whose value is
@@ -671,17 +675,17 @@
         orb_2_3.unregister_value_factory(TestValueSubHelper.id());
         try {
             av = to.get_valuesub_as_value_any();
-            TEST(false);
+            assertTrue(false);
         } catch (MARSHAL ex) {
             // expected
         }
         TestValueSubFactory_impl.install(orb);
         av = to.get_valuesub_as_value_any();
         v2 = TestValueHelper.extract(av);
-        TEST(v2 != null);
+        assertTrue(v2 != null);
         sub = (TestValueSub) v2;
-        TEST(sub.count == 501);
-        TEST(sub.name.equals("ValueSub"));
+        assertTrue(sub.count == 501);
+        assertTrue(sub.name.equals("ValueSub"));
 
         //
         // Test custom valuetype
@@ -694,7 +698,7 @@
         orb_2_3.unregister_value_factory(TestCustomHelper.id());
         try {
             av = to.get_custom_any();
-            TEST(false);
+            assertTrue(false);
         } catch (MARSHAL ex) {
             // expected
         }
@@ -702,11 +706,11 @@
         av = to.get_custom_any();
         to.remarshal_any(av);
         cust = TestCustomHelper.extract(av);
-        TEST(cust != null);
-        TEST(cust.shortVal == (short) -99);
-        TEST(cust.longVal == -123456);
-        TEST(cust.stringVal.equals("CustomVal"));
-        TEST(cust.doubleVal == 100.997);
+        assertTrue(cust != null);
+        assertTrue(cust.shortVal == (short) -99);
+        assertTrue(cust.longVal == -123456);
+        assertTrue(cust.stringVal.equals("CustomVal"));
+        assertTrue(cust.doubleVal == 100.997);
 
         //
         // Simple tests for truncatable valuetypes
@@ -725,7 +729,7 @@
         av = to.get_trunc2_any();
         try {
             t2 = TestTrunc2Helper.extract(av);
-            TEST(false);
+            assertTrue(false);
         } catch (BAD_OPERATION ex) {
             // expected
         }
@@ -754,12 +758,12 @@
         TestTruncBaseFactory_impl.install(orb);
         TestTrunc1Factory_impl.install(orb);
         base = TestTruncBaseHelper.extract(av);
-        TEST(base != null);
-        TEST(base.cost > 1.99 && base.cost < 2.0);
+        assertTrue(base != null);
+        assertTrue(base.cost > 1.99 && base.cost < 2.0);
         try {
             // this should fail due to truncation
             t1 = (TestTrunc1) base;
-            TEST(false);
+            assertTrue(false);
         } catch (ClassCastException ex) {
             // expected
         }
@@ -770,11 +774,11 @@
         av = to.get_trunc1_as_base_any();
         to.remarshal_any(av);
         base = TestTruncBaseHelper.extract(av);
-        TEST(base != null);
+        assertTrue(base != null);
         t1 = (TestTrunc1) base;
-        TEST(t1.cost > 1.99 && t1.cost < 2.0);
-        TEST(t1.boolVal == true);
-        TEST(t1.shortVal == (short) 12667);
+        assertTrue(t1.cost > 1.99 && t1.cost < 2.0);
+        assertTrue(t1.boolVal == true);
+        assertTrue(t1.shortVal == (short) 12667);
 
         //
         // Request a TestTrunc2 value with the TestTruncBase TypeCode.
@@ -790,12 +794,12 @@
         TestTrunc1Factory_impl.install(orb);
         TestTrunc2Factory_impl.install(orb);
         base = TestTruncBaseHelper.extract(av);
-        TEST(base != null);
-        TEST(base.cost > 5.99 && base.cost < 6.0);
+        assertTrue(base != null);
+        assertTrue(base.cost > 5.99 && base.cost < 6.0);
         try {
             // this should fail due to truncation
             t2 = (TestTrunc2) base;
-            TEST(false);
+            assertTrue(false);
         } catch (ClassCastException ex) {
             // expected
         }
@@ -806,9 +810,9 @@
         av = to.get_trunc2_as_base_any();
         to.remarshal_any(av);
         base = TestTruncBaseHelper.extract(av);
-        TEST(base != null);
+        assertTrue(base != null);
         t2 = (TestTrunc2) base;
-        TEST(t2.cost > 5.99 && t2.cost < 6.0);
+        assertTrue(t2.cost > 5.99 && t2.cost < 6.0);
 
         //
         // Request a TestTrunc2 value with the TestTruncBase TypeCode.
@@ -820,11 +824,11 @@
         av = to.get_trunc2_as_base_any();
         to.remarshal_any(av);
         base = TestTruncBaseHelper.extract(av);
-        TEST(base != null);
-        TEST(base.cost > 5.99 && base.cost < 6.0);
+        assertTrue(base != null);
+        assertTrue(base.cost > 5.99 && base.cost < 6.0);
         try {
             t2 = (TestTrunc2) base;
-            TEST(false);
+            assertTrue(false);
         } catch (ClassCastException ex) {
             // expected
         }
@@ -838,11 +842,11 @@
         //
         av = to.get_trunc2_any();
         base = TestTruncBaseHelper.extract(av);
-        TEST(base != null);
-        TEST(base.cost > 5.99 && base.cost < 6.0);
+        assertTrue(base != null);
+        assertTrue(base.cost > 5.99 && base.cost < 6.0);
         try {
             t2 = (TestTrunc2) base;
-            TEST(false);
+            assertTrue(false);
         } catch (ClassCastException ex) {
             // expected
         }
@@ -857,7 +861,7 @@
         //
         av = to.get_ai_value_any();
         tab = TestAbstractHelper.extract(av);
-        TEST(tab != null);
+        assertTrue(tab != null);
         tab.abstract_op();
         ai = (TestValueAI) tab;
         ai.value_op();
@@ -871,19 +875,19 @@
         to.get_two_value_anys(a1, a2);
         v1 = TestValueHelper.extract(a1.value);
         v2 = TestValueHelper.extract(a2.value);
-        TEST(v1 != null);
-        TEST(v2 != null);
-        TEST(v1 == v2);
+        assertTrue(v1 != null);
+        assertTrue(v2 != null);
+        assertTrue(v1 == v2);
         to.set_two_value_anys(a1.value, a2.value);
     }
 
     static void testSupported(ORB orb, TestOBV to) {
         TestValueInterface val = to.get_value_as_value();
         val.value_op();
-        TEST(val.get_count() == val.count);
+        assertTrue(val.get_count() == val.count);
 
         TestInterface i = to.get_value_as_interface();
-        TEST(val.count == i.get_count());
+        assertTrue(val.count == i.get_count());
     }
 
     public static int run(ORB orb, String[] args)
@@ -900,7 +904,7 @@
         }
 
         TestOBV to = TestOBVHelper.narrow(obj);
-        TEST(to != null);
+        assertTrue(to != null);
 
         //
         // Install value factories
diff --git a/yoko-core/src/test/java/test/obv/TestCustom_impl.java b/yoko-core/src/test/java/test/obv/TestCustom_impl.java
index 323d5b3..6919ffb 100644
--- a/yoko-core/src/test/java/test/obv/TestCustom_impl.java
+++ b/yoko-core/src/test/java/test/obv/TestCustom_impl.java
@@ -17,6 +17,8 @@
 
 package test.obv;
 
+import static org.junit.Assert.assertTrue;
+
 public class TestCustom_impl extends TestCustom {
     public void marshal(org.omg.CORBA.DataOutputStream os) {
         //
@@ -32,7 +34,7 @@
 
     public void unmarshal(org.omg.CORBA.DataInputStream is) {
         String str = is.read_string();
-        test.common.TestBase.TEST(str.equals("Extra String"));
+        assertTrue(str.equals("Extra String"));
 
         stringVal = is.read_string();
         doubleVal = is.read_double();
diff --git a/yoko-core/src/test/java/test/obv/TestOBV_impl.java b/yoko-core/src/test/java/test/obv/TestOBV_impl.java
index b16ddc2..6a9ab94 100644
--- a/yoko-core/src/test/java/test/obv/TestOBV_impl.java
+++ b/yoko-core/src/test/java/test/obv/TestOBV_impl.java
@@ -17,6 +17,8 @@
 
 package test.obv;
 
+import static org.junit.Assert.assertTrue;
+
 public class TestOBV_impl extends TestOBVPOA {
     private org.omg.CORBA.ORB orb_;
 
@@ -37,7 +39,7 @@
     private TestInterfacePOATie valueInterfaceTie_; // Java only
 
     private void TEST(boolean b) {
-        test.common.TestBase.TEST(b);
+        assertTrue(b);
     }
 
     public TestOBV_impl(org.omg.CORBA.ORB orb,
diff --git a/yoko-core/src/test/java/test/pi/Client.java b/yoko-core/src/test/java/test/pi/Client.java
index 72b2b2a..74b0371 100644
--- a/yoko-core/src/test/java/test/pi/Client.java
+++ b/yoko-core/src/test/java/test/pi/Client.java
@@ -1,10 +1,10 @@
 /*
  *  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
+ *  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
  *
@@ -17,15 +17,50 @@
 
 package test.pi;
 
+import static org.junit.Assert.assertTrue;
+import static org.omg.CORBA.SetOverrideType.ADD_OVERRIDE;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.util.Properties;
-import org.omg.CORBA.*;
-import org.omg.PortableInterceptor.*;
-import test.pi.TestInterfacePackage.*;
-import java.io.*;
+
+import org.apache.yoko.orb.OB.Assert;
+import org.omg.CORBA.Any;
+import org.omg.CORBA.BAD_INV_ORDER;
+import org.omg.CORBA.NO_IMPLEMENT;
+import org.omg.CORBA.NO_PERMISSION;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Policy;
+import org.omg.CORBA.Request;
+import org.omg.CORBA.StringHolder;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.TCKind;
+import org.omg.CORBA.WrongTransaction;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.IOP.Codec;
+import org.omg.IOP.CodecFactory;
+import org.omg.IOP.CodecFactoryHelper;
+import org.omg.IOP.ENCODING_CDR_ENCAPS;
+import org.omg.IOP.Encoding;
+import org.omg.IOP.CodecFactoryPackage.UnknownEncoding;
+import org.omg.IOP.CodecPackage.FormatMismatch;
+import org.omg.IOP.CodecPackage.InvalidTypeForEncoding;
+import org.omg.IOP.CodecPackage.TypeMismatch;
+import org.omg.PortableInterceptor.ClientRequestInterceptor;
+import org.omg.PortableInterceptor.Current;
+import org.omg.PortableInterceptor.CurrentHelper;
+import org.omg.PortableInterceptor.InvalidSlot;
+
+import test.pi.TestInterfacePackage.s;
+import test.pi.TestInterfacePackage.sHelper;
+import test.pi.TestInterfacePackage.sHolder;
+import test.pi.TestInterfacePackage.user;
+import test.pi.TestInterfacePackage.userHelper;
 
 public final class Client extends test.common.TestBase {
-    private static void TestTranslation(ORB orb, ClientProxyManager manager,
-            TestInterface ti) {
+    private static void TestTranslation(ORB orb, ClientProxyManager manager, TestInterface ti) {
         //
         // Set up the correct interceptor
         //
@@ -40,7 +75,7 @@
         i0.throwOnRequest(new NO_PERMISSION());
         try {
             ti.noargs();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_PERMISSION ex) {
             // Expected
         }
@@ -49,7 +84,7 @@
         i0.throwOnReply(new NO_PERMISSION());
         try {
             ti.noargs();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_PERMISSION ex) {
             // Expected
         }
@@ -60,7 +95,7 @@
         i0.expectException(new NO_PERMISSION());
         try {
             ti.noargs();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_PERMISSION ex) {
             // Expected
         }
@@ -74,7 +109,7 @@
 
         try {
             ti.noargs();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_PERMISSION ex) {
             // Expected
         }
@@ -84,7 +119,7 @@
 
         try {
             ti.noargs();
-            TEST(false);
+            assertTrue(false);
         } catch (NO_PERMISSION ex) {
             // Expected
         }
@@ -92,16 +127,14 @@
         manager.clearInterceptors();
     }
 
-    private static void TestCalls(ORB orb, ClientProxyManager manager,
-            TestInterface ti) {
-        org.omg.PortableInterceptor.Current pic = null;
+    private static void TestCalls(ORB orb, ClientProxyManager manager, TestInterface ti) {
+        Current pic = null;
         try {
-            org.omg.CORBA.Object obj = orb
-                    .resolve_initial_references("PICurrent");
-            pic = org.omg.PortableInterceptor.CurrentHelper.narrow(obj);
-        } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
+            org.omg.CORBA.Object obj = orb.resolve_initial_references("PICurrent");
+            pic = CurrentHelper.narrow(obj);
+        } catch (InvalidName ex) {
         }
-        TEST(pic != null);
+        assertTrue(pic != null);
 
         Any slotData = orb.create_any();
         slotData.insert_long(10);
@@ -109,7 +142,7 @@
         try {
             pic.set_slot(0, slotData);
         } catch (InvalidSlot ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
@@ -121,62 +154,62 @@
         int num = 0;
 
         ti.noargs();
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         ti.noargs_oneway();
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         try {
             ti.userexception();
-            TEST(false);
+            assertTrue(false);
         } catch (user ex) {
         }
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         try {
             ti.systemexception();
-            TEST(false);
+            assertTrue(false);
         } catch (SystemException ex) {
         }
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         ti.test_service_context();
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         try {
             ti.location_forward();
         } catch (NO_IMPLEMENT ex) {
         }
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         //
         // Test simple attribute
         //
         ti.string_attrib("TEST");
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
         String satt = ti.string_attrib();
-        TEST(satt.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(satt.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         //
         // Test in, inout and out simple parameters
         //
         ti.one_string_in("TEST");
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         StringHolder spinout = new StringHolder("TESTINOUT");
         ti.one_string_inout(spinout);
-        TEST(spinout.value.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(spinout.value.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         StringHolder spout = new StringHolder();
         ti.one_string_out(spout);
-        TEST(spout.value.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(spout.value.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         String sprc = ti.one_string_return();
-        TEST(sprc.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(sprc.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         //
         // Test struct attribute
@@ -184,30 +217,30 @@
         s ss = new s();
         ss.sval = "TEST";
         ti.struct_attrib(ss);
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
         s ssatt = ti.struct_attrib();
-        TEST(ssatt.sval.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(ssatt.sval.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         //
         // Test in, inout and out struct parameters
         //
         ti.one_struct_in(ss);
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         sHolder sinout = new sHolder(new s("TESTINOUT"));
         ti.one_struct_inout(sinout);
-        TEST(sinout.value.sval.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(sinout.value.sval.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         sHolder sout = new sHolder();
         ti.one_struct_out(sout);
-        TEST(sout.value.sval.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(sout.value.sval.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         s ssrc = ti.one_struct_return();
-        TEST(ssrc.sval.equals("TEST"));
-        TEST(++num == impl._OB_numReq());
+        assertTrue(ssrc.sval.equals("TEST"));
+        assertTrue(++num == impl._OB_numReq());
 
         manager.clearInterceptors();
 
@@ -218,22 +251,20 @@
         try {
             slotData2 = pic.get_slot(0);
         } catch (InvalidSlot ex) {
-            TEST(false);
+            assertTrue(false);
         }
         int v = slotData2.extract_long();
-        TEST(v == 10);
+        assertTrue(v == 10);
     }
 
-    private static void TestDIICalls(ORB orb, ClientProxyManager manager,
-            TestInterface ti) {
-        org.omg.PortableInterceptor.Current pic = null;
+    private static void TestDIICalls(ORB orb, ClientProxyManager manager, TestInterface ti) {
+        Current pic = null;
         try {
-            org.omg.CORBA.Object obj = orb
-                    .resolve_initial_references("PICurrent");
-            pic = org.omg.PortableInterceptor.CurrentHelper.narrow(obj);
-        } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
+            org.omg.CORBA.Object obj = orb.resolve_initial_references("PICurrent");
+            pic = CurrentHelper.narrow(obj);
+        } catch (InvalidName ex) {
         }
-        TEST(pic != null);
+        assertTrue(pic != null);
 
         Any slotData = orb.create_any();
         slotData.insert_long(10);
@@ -241,7 +272,7 @@
         try {
             pic.set_slot(0, slotData);
         } catch (InvalidSlot ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
@@ -255,16 +286,16 @@
         Request req;
         req = ti._request("noargs");
         req.invoke();
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         req = ti._request("noargs_oneway");
         req.send_oneway();
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         req = ti._request("userexception");
         req.exceptions().add(userHelper.type());
         req.invoke();
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         req = ti._request("systemexception");
         try {
@@ -272,7 +303,7 @@
         } catch (NO_IMPLEMENT ex) {
             // expected - raised by remote servant
         }
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         req = ti._request("location_forward");
         try {
@@ -280,7 +311,7 @@
         } catch (NO_IMPLEMENT ex) {
             // expected - raised by local interceptor
         }
-        TEST(++num == impl._OB_numReq());
+        assertTrue(++num == impl._OB_numReq());
 
         //
         // Test in, inout and out simple parameters
@@ -290,7 +321,7 @@
             req.set_return_type(orb.get_primitive_tc(TCKind.tk_void));
             req.add_in_arg().insert_string("TEST");
             req.invoke();
-            TEST(++num == impl._OB_numReq());
+            assertTrue(++num == impl._OB_numReq());
 
             req = ti._request("one_string_inout");
             req.set_return_type(orb.get_primitive_tc(TCKind.tk_void));
@@ -299,8 +330,8 @@
             inOutAny.insert_string(sp);
             req.invoke();
             String sprc = inOutAny.extract_string();
-            TEST(sprc.equals("TEST"));
-            TEST(++num == impl._OB_numReq());
+            assertTrue(sprc.equals("TEST"));
+            assertTrue(++num == impl._OB_numReq());
 
             req = ti._request("one_string_out");
             req.set_return_type(orb.get_primitive_tc(TCKind.tk_void));
@@ -308,15 +339,15 @@
             outAny.insert_string("");
             req.invoke();
             sprc = outAny.extract_string();
-            TEST(sprc.equals("TEST"));
-            TEST(++num == impl._OB_numReq());
+            assertTrue(sprc.equals("TEST"));
+            assertTrue(++num == impl._OB_numReq());
 
             req = ti._request("one_string_return");
             req.set_return_type(orb.get_primitive_tc(TCKind.tk_string));
             req.invoke();
             sprc = req.return_value().extract_string();
-            TEST(sprc.equals("TEST"));
-            TEST(++num == impl._OB_numReq());
+            assertTrue(sprc.equals("TEST"));
+            assertTrue(++num == impl._OB_numReq());
         }
 
         //
@@ -329,7 +360,7 @@
             req.set_return_type(orb.get_primitive_tc(TCKind.tk_void));
             sHelper.insert(req.add_in_arg(), ss);
             req.invoke();
-            TEST(++num == impl._OB_numReq());
+            assertTrue(++num == impl._OB_numReq());
 
             ss.sval = "TESTINOUT";
             req = ti._request("one_struct_inout");
@@ -338,8 +369,8 @@
             sHelper.insert(inOutAny, ss);
             req.invoke();
             s ssrc = sHelper.extract(inOutAny);
-            TEST(ssrc.sval.equals("TEST"));
-            TEST(++num == impl._OB_numReq());
+            assertTrue(ssrc.sval.equals("TEST"));
+            assertTrue(++num == impl._OB_numReq());
 
             req = ti._request("one_struct_out");
             req.set_return_type(orb.get_primitive_tc(TCKind.tk_void));
@@ -347,15 +378,15 @@
             outAny.type(sHelper.type());
             req.invoke();
             ssrc = sHelper.extract(outAny);
-            TEST(ssrc.sval.equals("TEST"));
-            TEST(++num == impl._OB_numReq());
+            assertTrue(ssrc.sval.equals("TEST"));
+            assertTrue(++num == impl._OB_numReq());
 
             req = ti._request("one_struct_return");
             req.set_return_type(sHelper.type());
             req.invoke();
             ssrc = sHelper.extract(req.return_value());
-            TEST(ssrc.sval.equals("TEST"));
-            TEST(++num == impl._OB_numReq());
+            assertTrue(ssrc.sval.equals("TEST"));
+            assertTrue(++num == impl._OB_numReq());
         }
 
         //
@@ -365,10 +396,10 @@
         try {
             slotData2 = pic.get_slot(0);
         } catch (InvalidSlot ex) {
-            TEST(false);
+            assertTrue(false);
         }
         int v = slotData2.extract_long();
-        TEST(v == 10);
+        assertTrue(v == 10);
 
         //
         // Test: ASYNC calls
@@ -378,42 +409,42 @@
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             req = ti._request("noargs");
             req.send_deferred();
-            TEST(++num == impl._OB_numReq());
+            assertTrue(++num == impl._OB_numReq());
 
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             v = slotData2.extract_long();
-            TEST(v == 10);
+            assertTrue(v == 10);
 
             slotData.insert_long(11);
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 req.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
             v = slotData2.extract_long();
-            TEST(v == 11);
+            assertTrue(v == 11);
         }
 
         {
@@ -421,43 +452,43 @@
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             req = ti._request("userexception");
             req.exceptions().add(userHelper.type());
             req.send_deferred();
-            TEST(++num == impl._OB_numReq());
+            assertTrue(++num == impl._OB_numReq());
 
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             v = slotData2.extract_long();
-            TEST(v == 10);
+            assertTrue(v == 10);
 
             slotData.insert_long(11);
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 req.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
             v = slotData2.extract_long();
-            TEST(v == 11);
+            assertTrue(v == 11);
         }
 
         {
@@ -465,33 +496,33 @@
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             req = ti._request("systemexception");
             req.send_deferred();
-            TEST(++num == impl._OB_numReq());
+            assertTrue(++num == impl._OB_numReq());
 
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             v = slotData2.extract_long();
-            TEST(v == 10);
+            assertTrue(v == 10);
 
             slotData.insert_long(11);
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 req.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (NO_IMPLEMENT ex) {
                 // expected - raised by remote servant
             }
@@ -499,10 +530,10 @@
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
             v = slotData2.extract_long();
-            TEST(v == 11);
+            assertTrue(v == 11);
         }
 
         {
@@ -510,33 +541,33 @@
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             req = ti._request("location_forward");
             req.send_deferred();
-            TEST(++num == impl._OB_numReq());
+            assertTrue(++num == impl._OB_numReq());
 
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             v = slotData2.extract_long();
-            TEST(v == 10);
+            assertTrue(v == 10);
 
             slotData.insert_long(11);
             try {
                 pic.set_slot(0, slotData);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 req.get_response();
             } catch (WrongTransaction ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (NO_IMPLEMENT ex) {
                 // expected - raised by local interceptor
             }
@@ -544,10 +575,10 @@
             try {
                 slotData2 = pic.get_slot(0);
             } catch (InvalidSlot ex) {
-                TEST(false);
+                assertTrue(false);
             }
             v = slotData2.extract_long();
-            TEST(v == 11);
+            assertTrue(v == 11);
         }
 
         manager.clearInterceptors();
@@ -557,16 +588,15 @@
         //
         // Test: Resolve CodecFactory
         //
-        org.omg.IOP.CodecFactory factory = null;
+        CodecFactory factory = null;
         try {
-            factory = org.omg.IOP.CodecFactoryHelper.narrow(orb
-                    .resolve_initial_references("CodecFactory"));
-        } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
-            TEST(false);
+            factory = CodecFactoryHelper.narrow(orb.resolve_initial_references("CodecFactory"));
+        } catch (InvalidName ex) {
+            assertTrue(false);
         }
-        TEST(factory != null);
+        assertTrue(factory != null);
 
-        org.omg.IOP.Encoding how = new org.omg.IOP.Encoding();
+        Encoding how = new Encoding();
         how.major_version = 0;
         how.minor_version = 0;
 
@@ -575,23 +605,23 @@
         //
         try {
             how.format = 1; // Some unknown value
-            org.omg.IOP.Codec codec = factory.create_codec(how);
-            TEST(false);
-        } catch (org.omg.IOP.CodecFactoryPackage.UnknownEncoding ex) {
+            factory.create_codec(how);
+            assertTrue(false);
+        } catch (UnknownEncoding ex) {
             // Expected
         }
 
         //
         // Test: CDR Codec
         //
-        how.format = org.omg.IOP.ENCODING_CDR_ENCAPS.value;
-        org.omg.IOP.Codec cdrCodec = null;
+        how.format = ENCODING_CDR_ENCAPS.value;
+        Codec cdrCodec = null;
         try {
             cdrCodec = factory.create_codec(how);
-        } catch (org.omg.IOP.CodecFactoryPackage.UnknownEncoding ex) {
-            TEST(false);
+        } catch (UnknownEncoding ex) {
+            assertTrue(false);
         }
-        org.apache.yoko.orb.OB.Assert._OB_assert(cdrCodec != null);
+        Assert._OB_assert(cdrCodec != null);
 
         //
         // Test: Encode/decode
@@ -604,77 +634,62 @@
         byte[] encoding = null;
         try {
             encoding = cdrCodec.encode(any);
-        } catch (org.omg.IOP.CodecPackage.InvalidTypeForEncoding ex) {
-            TEST(false);
+        } catch (InvalidTypeForEncoding ex) {
+            assertTrue(false);
         }
         Any result = null;
         try {
             result = cdrCodec.decode(encoding);
-        } catch (org.omg.IOP.CodecPackage.FormatMismatch ex) {
-            TEST(false);
+        } catch (FormatMismatch ex) {
+            assertTrue(false);
         }
 
         foo newf = fooHelper.extract(result);
-        TEST(newf.l == 10);
+        assertTrue(newf.l == 10);
 
         //
         // Test: Encode/decode
         //
         try {
             encoding = cdrCodec.encode_value(any);
-        } catch (org.omg.IOP.CodecPackage.InvalidTypeForEncoding ex) {
-            TEST(false);
+        } catch (InvalidTypeForEncoding ex) {
+            assertTrue(false);
         }
         try {
             result = cdrCodec.decode_value(encoding, fooHelper.type());
-        } catch (org.omg.IOP.CodecPackage.FormatMismatch ex) {
-            TEST(false);
-        } catch (org.omg.IOP.CodecPackage.TypeMismatch ex) {
-            TEST(false);
+        } catch (FormatMismatch ex) {
+            assertTrue(false);
+        } catch (TypeMismatch ex) {
+            assertTrue(false);
         }
 
         newf = fooHelper.extract(result);
-        TEST(newf.l == 10);
+        assertTrue(newf.l == 10);
     }
 
-    static void ClientRegisterInterceptors(java.util.Properties props,
-            boolean local) {
-        props.put("org.omg.PortableInterceptor.ORBInitializerClass."
-                + "test.pi.ClientORBInitializer_impl", "");
+    static void ClientRegisterInterceptors(Properties props, boolean local) {
+        props.put("org.omg.PortableInterceptor.ORBInitializerClass." + ClientORBInitializer_impl.class.getName(), "");
         ClientORBInitializer_impl._OB_setLocal(local);
     }
 
-    static int ClientRun(ORB orb, boolean nonBlocking, String[] args)
-            throws org.omg.CORBA.UserException {
+    static void ClientRun(ORB orb, boolean nonBlocking, String[] args) throws Exception {
         String impl;
         String dsiImpl;
 
         //
         // Get TestInterface
         //
-        try {
-            String refFile = "TestInterface.ref";
-            FileInputStream file = new FileInputStream(refFile);
-            BufferedReader in = new BufferedReader(new InputStreamReader(file));
-            impl = in.readLine();
-            dsiImpl = in.readLine();
-            file.close();
-        } catch (IOException ex) {
-            System.err.println("Can't read from `" + ex.getMessage() + "'");
-            return 1;
+        try (BufferedReader in = new BufferedReader(new FileReader("TestInterface.ref"))) {
+            impl = readRef(in);
+            dsiImpl = readRef(in);
         }
 
-        System.out.print("Testing initial reference registration... ");
-        System.out.flush();
-        // TODO
-        System.out.println("Done!");
-
         System.out.print("Testing string_to_object()... ");
         System.out.flush();
         org.omg.CORBA.Object obj = orb.string_to_object(impl);
         org.omg.CORBA.Object dsiObj = orb.string_to_object(dsiImpl);
-        TEST(obj != null);
-        TEST(dsiObj != null);
+        assertTrue(obj != null);
+        assertTrue(dsiObj != null);
         System.out.println("Done!");
 
         //
@@ -687,89 +702,96 @@
 
         System.out.print("Testing _narrow()... ");
         System.out.flush();
-        obj = obj._set_policy_override(pl,
-                org.omg.CORBA.SetOverrideType.ADD_OVERRIDE);
+        obj = obj._set_policy_override(pl, ADD_OVERRIDE);
         TestInterface ti = TestInterfaceHelper.narrow(obj);
-        dsiObj = dsiObj._set_policy_override(pl,
-                org.omg.CORBA.SetOverrideType.ADD_OVERRIDE);
-        TestInterface tiDSI = TestInterfaceHelper.narrow(dsiObj);
-        TEST(ti != null);
-        TEST(tiDSI != null);
-        System.out.println("Done!");
+        assertTrue(ti != null);
+        try {
+            if ("".isEmpty()) return;
+            dsiObj = dsiObj._set_policy_override(pl, ADD_OVERRIDE);
+            TestInterface tiDSI = TestInterfaceHelper.narrow(dsiObj);
+            assertTrue(tiDSI != null);
+            System.out.println("Done!");
 
-        //
-        // Test: Codec
-        //
-        System.out.print("Testing Codec... ");
-        System.out.flush();
-        TestCodec(orb);
-        System.out.println("Done!");
+            //
+            // Test: Codec
+            //
+            System.out.print("Testing Codec... ");
+            System.out.flush();
+            TestCodec(orb);
+            System.out.println("Done!");
 
-        //
-        // Test: Exception translation
-        //
-        System.out.print("Testing client side exception translation... ");
-        System.out.flush();
-        TestTranslation(orb, ClientORBInitializer_impl.clientProxyManager, ti);
-        System.out.println("Done!");
+            //
+            // Test: Exception translation
+            //
+            System.out.print("Testing client side exception translation... ");
+            System.out.flush();
+            TestTranslation(orb, ClientORBInitializer_impl.clientProxyManager, ti);
+            System.out.println("Done!");
 
-        //
-        // Run tests
-        //
-        System.out.print("Testing standard method calls with static stubs... ");
-        System.out.flush();
-        TestCalls(orb, ClientORBInitializer_impl.clientProxyManager, ti);
-        System.out.println("Done!");
+            //
+            // Run tests
+            //
+            System.out.print("Testing standard method calls with static stubs... ");
+            System.out.flush();
+            TestCalls(orb, ClientORBInitializer_impl.clientProxyManager, ti);
+            System.out.println("Done!");
 
-        System.out.print("Ditto, but with the DSI implementation... ");
-        System.out.flush();
-        TestCalls(orb, ClientORBInitializer_impl.clientProxyManager, tiDSI);
-        System.out.println("Done!");
+            System.out.print("Ditto, but with the DSI implementation... ");
+            System.out.flush();
+            TestCalls(orb, ClientORBInitializer_impl.clientProxyManager, tiDSI);
+            System.out.println("Done!");
 
-        System.out.print("Testing standard method calls with the DII... ");
-        System.out.flush();
-        TestDIICalls(orb, ClientORBInitializer_impl.clientProxyManager, ti);
-        System.out.println("Done!");
+            System.out.print("Testing standard method calls with the DII... ");
+            System.out.flush();
+            TestDIICalls(orb, ClientORBInitializer_impl.clientProxyManager, ti);
+            System.out.println("Done!");
 
-        System.out.print("Ditto, but with the DSI implementation... ");
-        System.out.flush();
-        TestDIICalls(orb, ClientORBInitializer_impl.clientProxyManager, tiDSI);
-        System.out.println("Done!");
-
-        ti.deactivate();
-
-        return 0;
+            System.out.print("Ditto, but with the DSI implementation... ");
+            System.out.flush();
+            TestDIICalls(orb, ClientORBInitializer_impl.clientProxyManager, tiDSI);
+            System.out.println("Done!");
+        } finally {
+            System.out.println("About to call deactivate");
+            ti.deactivate();
+            System.out.println("Deactivate returned normally");
+        }
     }
 
-    public static void main(String[] args) {
+    private static String readRef(BufferedReader in) throws Exception {
+        String line = in.readLine();
+        if (line == null) {
+            throw new RuntimeException("Unknown Server error");
+        } else if (!!!line.equals("ref:")) {
+            try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
+                pw.println("Server error:");
+                do {
+                    pw.print('\t');
+                    pw.println(line);
+                } while ((line = in.readLine()) != null);
+                pw.flush();
+                throw new RuntimeException(sw.toString());
+            }
+        }
+        return in.readLine();
+    }
+
+    public static void main(String[] args) throws Exception {
         java.util.Properties props = new Properties();
         props.putAll(System.getProperties());
         props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
-        props.put("org.omg.CORBA.ORBSingletonClass",
-                "org.apache.yoko.orb.CORBA.ORBSingleton");
+        props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
 
-        int status = 0;
         ORB orb = null;
 
         try {
             ClientRegisterInterceptors(props, false);
 
             orb = ORB.init(args, props);
-            status = ClientRun(orb, false, args);
-        } catch (Exception ex) {
-            ex.printStackTrace();
-            status = 1;
-        }
-
-        if (orb != null) {
-            try {
+            ClientRun(orb, false, args);
+        } finally {
+            if (orb != null) {
                 orb.destroy();
-            } catch (Exception ex) {
-                ex.printStackTrace();
-                status = 1;
             }
         }
-
-        System.exit(status);
     }
 }
diff --git a/yoko-core/src/test/java/test/pi/ClientORBInitializer_impl.java b/yoko-core/src/test/java/test/pi/ClientORBInitializer_impl.java
index f63fc65..3c3a09b 100644
--- a/yoko-core/src/test/java/test/pi/ClientORBInitializer_impl.java
+++ b/yoko-core/src/test/java/test/pi/ClientORBInitializer_impl.java
@@ -48,7 +48,7 @@
         //
         if (!local_) {
             int id = info.allocate_slot_id();
-            TEST(id == 0);
+            TEST(id >= 0);
         }
 
         //
diff --git a/yoko-core/src/test/java/test/pi/Collocated.java b/yoko-core/src/test/java/test/pi/Collocated.java
index f6039ec..91e01bc 100644
--- a/yoko-core/src/test/java/test/pi/Collocated.java
+++ b/yoko-core/src/test/java/test/pi/Collocated.java
@@ -1,10 +1,10 @@
 /*
  *  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
+ *  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
  *
@@ -18,19 +18,18 @@
 package test.pi;
 
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableInterceptor.*;
 
 final public class Collocated {
-    public static void main(String[] args) {
+    public static void main(String[] args) throws Exception {
         java.util.Properties props = new Properties();
         props.putAll(System.getProperties());
         props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
-        props.put("org.omg.CORBA.ORBSingletonClass",
-                "org.apache.yoko.orb.CORBA.ORBSingleton");
+        props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
 
-        int status = 0;
         ORB orb = null;
 
         try {
@@ -39,33 +38,21 @@
 
             props.put("yoko.orb.id", "myORB");
             orb = ORB.init(args, props);
-            status = Server.ServerRun(orb, true, args);
+            Server.ServerRun(orb, true, args);
+            Client.ClientRun(orb, true, args);
 
-            if (status == 0) {
-                status = Client.ClientRun(orb, true, args);
+            //
+            // The ORB must be totally shutdown before the servants
+            // are deleted.
+            //
+            orb.shutdown(true);
 
-                //
-                // The ORB must be totally shutdown before the servants
-                // are deleted.
-                //
-                orb.shutdown(true);
-
-                Server.ServerCleanup();
-            }
-        } catch (Exception ex) {
-            ex.printStackTrace();
-            status = 1;
-        }
-
-        if (orb != null) {
-            try {
+            Server.ServerCleanup();
+        } finally {
+            if (orb != null) {
                 orb.destroy();
-            } catch (Exception ex) {
-                ex.printStackTrace();
-                status = 1;
             }
         }
 
-        System.exit(status);
     }
 }
diff --git a/yoko-core/src/test/java/test/pi/Server.java b/yoko-core/src/test/java/test/pi/Server.java
index b0dc37a..bc353b7 100644
--- a/yoko-core/src/test/java/test/pi/Server.java
+++ b/yoko-core/src/test/java/test/pi/Server.java
@@ -1,10 +1,10 @@
 /*
  *  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
+ *  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
  *
@@ -17,141 +17,147 @@
 
 package test.pi;
 
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
 import java.util.Properties;
-import org.omg.CORBA.*;
-import org.omg.PortableServer.*;
-import org.omg.PortableServer.POAPackage.*;
-import org.omg.PortableServer.POAManagerPackage.*;
-import org.omg.PortableInterceptor.*;
-import java.io.*;
+
+import org.omg.CORBA.Any;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Policy;
+import org.omg.PortableInterceptor.ServerRequestInterceptor;
+import org.omg.PortableServer.ID_ASSIGNMENT_POLICY_ID;
+import org.omg.PortableServer.IMPLICIT_ACTIVATION_POLICY_ID;
+import org.omg.PortableServer.IdAssignmentPolicyValue;
+import org.omg.PortableServer.IdAssignmentPolicyValueHelper;
+import org.omg.PortableServer.ImplicitActivationPolicyValue;
+import org.omg.PortableServer.ImplicitActivationPolicyValueHelper;
+import org.omg.PortableServer.LIFESPAN_POLICY_ID;
+import org.omg.PortableServer.LifespanPolicyValue;
+import org.omg.PortableServer.LifespanPolicyValueHelper;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAHelper;
+import org.omg.PortableServer.POAManager;
+import org.omg.PortableServer.REQUEST_PROCESSING_POLICY_ID;
+import org.omg.PortableServer.RequestProcessingPolicyValue;
+import org.omg.PortableServer.RequestProcessingPolicyValueHelper;
+import org.omg.PortableServer.SERVANT_RETENTION_POLICY_ID;
+import org.omg.PortableServer.ServantLocator;
+import org.omg.PortableServer.ServantRetentionPolicyValue;
+import org.omg.PortableServer.ServantRetentionPolicyValueHelper;
 
 public final class Server extends test.common.TestBase {
-    private static TestInterface_impl impl;
-
-    private static TestInterfaceDSI_impl dsiImpl;
-
     private static String refFile = "TestInterface.ref";
 
     private static TestLocator_impl locatorImpl;
 
     static void ServerRegisterInterceptors(java.util.Properties props) {
-        props.put("org.omg.PortableInterceptor.ORBInitializerClass."
-                + "test.pi.ServerORBInitializer_impl", "");
+        props.put("org.omg.PortableInterceptor.ORBInitializerClass." + "test.pi.ServerORBInitializer_impl", "");
     }
 
-    static int ServerRun(ORB orb, boolean nonBlocking, String[] args)
-            throws org.omg.CORBA.UserException {
-    	try {
-    		Class.forName("test.pi.ServerORBInitializer_impl");
-    	}
-    	catch(ClassNotFoundException e) {
-    		e.printStackTrace();
-    	}
-        //
-        // Resolve Root POA
-        //
-        POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+    static void ServerRun(ORB orb, boolean nonBlocking, String[] args) throws Exception {
+        try (PrintWriter out = new PrintWriter(new FileWriter(refFile))) {
+            try {
+                Object c = Class.forName("test.pi.ServerORBInitializer_impl");
+                System.out.println("Got class " + c);
+                //
+                // Resolve Root POA
+                //
+                POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+                System.out.println("Got root POA");
+                //
+                // Activate the POA manager
+                //
+                POAManager manager = poa.the_POAManager();
+                manager.activate();
+                System.out.println("Activated root poa manager");
+                //
+                // This will use ORB::create_policy to create all the POA policies
+                // and our custom policy
+                //
+                Any any = orb.create_any();
 
-        //
-        // Activate the POA manager
-        //
-        POAManager manager = poa.the_POAManager();
-        manager.activate();
+                //
+                // Create policies for the POA
+                //
+                Policy[] policies = new Policy[6];
 
-        //
-        // This will use ORB::create_policy to create all the POA policies
-        // and our custom policy
-        //
-        Any any = orb.create_any();
+                LifespanPolicyValueHelper.insert(any, LifespanPolicyValue.PERSISTENT);
+                policies[0] = orb.create_policy(LIFESPAN_POLICY_ID.value, any);
+                IdAssignmentPolicyValueHelper.insert(any, IdAssignmentPolicyValue.USER_ID);
+                policies[1] = orb.create_policy(ID_ASSIGNMENT_POLICY_ID.value, any);
+                RequestProcessingPolicyValueHelper.insert(any, RequestProcessingPolicyValue.USE_SERVANT_MANAGER);
+                policies[2] = orb.create_policy(REQUEST_PROCESSING_POLICY_ID.value, any);
+                ServantRetentionPolicyValueHelper.insert(any, ServantRetentionPolicyValue.NON_RETAIN);
+                policies[3] = orb.create_policy(SERVANT_RETENTION_POLICY_ID.value, any);
+                ImplicitActivationPolicyValueHelper.insert(any, ImplicitActivationPolicyValue.NO_IMPLICIT_ACTIVATION);
+                policies[4] = orb.create_policy(IMPLICIT_ACTIVATION_POLICY_ID.value, any);
+                any.insert_long(10);
+                policies[5] = orb.create_policy(MY_SERVER_POLICY_ID.value, any);
 
-        //
-        // Create policies for the POA
-        //
-        Policy[] policies = new Policy[6];
+                POA persistentPOA = poa.create_POA("persistent", manager, policies);
 
-        LifespanPolicyValueHelper.insert(any, LifespanPolicyValue.PERSISTENT);
-        policies[0] = orb.create_policy(LIFESPAN_POLICY_ID.value, any);
-        IdAssignmentPolicyValueHelper.insert(any,
-                IdAssignmentPolicyValue.USER_ID);
-        policies[1] = orb.create_policy(ID_ASSIGNMENT_POLICY_ID.value, any);
-        RequestProcessingPolicyValueHelper.insert(any,
-                RequestProcessingPolicyValue.USE_SERVANT_MANAGER);
-        policies[2] = orb
-                .create_policy(REQUEST_PROCESSING_POLICY_ID.value, any);
-        ServantRetentionPolicyValueHelper.insert(any,
-                ServantRetentionPolicyValue.NON_RETAIN);
-        policies[3] = orb.create_policy(SERVANT_RETENTION_POLICY_ID.value, any);
-        ImplicitActivationPolicyValueHelper.insert(any,
-                ImplicitActivationPolicyValue.NO_IMPLICIT_ACTIVATION);
-        policies[4] = orb.create_policy(IMPLICIT_ACTIVATION_POLICY_ID.value,
-                any);
-        any.insert_long(10);
-        policies[5] = orb.create_policy(MY_SERVER_POLICY_ID.value, any);
+                //
+                // Create implementation objects
+                //
+                TestInterface_impl impl = new TestInterface_impl(orb, persistentPOA);
+                byte[] oid = ("test").getBytes();
+                org.omg.CORBA.Object objImpl = persistentPOA.create_reference_with_id(oid, "IDL:TestInterface:1.0");
+                TestInterfaceDSI_impl dsiImpl = new TestInterfaceDSI_impl(orb, persistentPOA);
+                oid = ("testDSI").getBytes();
+                org.omg.CORBA.Object objDSIImpl = persistentPOA.create_reference_with_id(oid, "IDL:TestInterface:1.0");
 
-        POA persistentPOA = poa.create_POA("persistent", manager, policies);
+                locatorImpl = new TestLocator_impl(orb, impl, dsiImpl);
+                ServantLocator locator = locatorImpl._this(orb);
+                persistentPOA.set_servant_manager(locator);
 
-        //
-        // Create implementation objects
-        //
-        TestInterface_impl impl = new TestInterface_impl(orb, persistentPOA);
-        byte[] oid = ("test").getBytes();
-        org.omg.CORBA.Object objImpl = persistentPOA.create_reference_with_id(
-                oid, "IDL:TestInterface:1.0");
-        TestInterfaceDSI_impl dsiImpl = new TestInterfaceDSI_impl(orb,
-                persistentPOA);
-        oid = ("testDSI").getBytes();
-        org.omg.CORBA.Object objDSIImpl = persistentPOA
-                .create_reference_with_id(oid, "IDL:TestInterface:1.0");
+                org.omg.IOP.CodecFactory factory = org.omg.IOP.CodecFactoryHelper.narrow(orb.resolve_initial_references("CodecFactory"));
+                assertTrue(factory != null);
 
-        locatorImpl = new TestLocator_impl(orb, impl, dsiImpl);
-        ServantLocator locator = locatorImpl._this(orb);
-        persistentPOA.set_servant_manager(locator);
+                ServerRequestInterceptor interceptor = new ServerTestInterceptor_impl(orb, factory);
+                ServerORBInitializer_impl.serverProxyManager.setInterceptor(0, interceptor);
 
-        //
-        // Save references. This must be done after POA manager
-        // activation, otherwise there is a potential for a race
-        // condition between the client sending request and the server
-        // not being ready yet.
-        //
-        try {
-            FileOutputStream file = new FileOutputStream(refFile);
-            PrintWriter out = new PrintWriter(file);
+                System.out.println("About to write refs");
+                
+                //
+                // Save references. This must be done after POA manager
+                // activation, otherwise there is a potential for a race
+                // condition between the client sending request and the server
+                // not being ready yet.
+                //
+                writeRef(orb, out, objImpl);
+                writeRef(orb, out, objDSIImpl);
+                out.flush();
+                System.out.println("Wrote refs");
 
-            String strimpl = orb.object_to_string(objImpl);
-            out.println(strimpl);
+                
+                if (!nonBlocking) {
+                    //
+                    // Give up control to the ORB
+                    //
+                    System.out.println("About to call orb.run()");
+                    orb.run();
+                    System.out.println("orb.run() returned");
+                    //
+                    // Clean up
+                    //
+                    ServerCleanup();
+                }
 
-            strimpl = orb.object_to_string(objDSIImpl);
-            out.println(strimpl);
-
-            out.flush();
-            file.close();
-        } catch (IOException ex) {
-            System.err.println("Can't write to `" + ex.getMessage() + "'");
-            return 1;
+                return;
+            } catch (Throwable e) {
+                e.printStackTrace(out);
+                e.printStackTrace(System.out);
+                throw e;
+            }
         }
+    }
 
-        org.omg.IOP.CodecFactory factory = org.omg.IOP.CodecFactoryHelper
-                .narrow(orb.resolve_initial_references("CodecFactory"));
-        TEST(factory != null);
-
-        ServerRequestInterceptor interceptor = new ServerTestInterceptor_impl(
-                orb, factory);
-        ServerORBInitializer_impl.serverProxyManager.setInterceptor(0,
-                interceptor);
-
-        if (!nonBlocking) {
-            //
-            // Give up control to the ORB
-            //
-            orb.run();
-
-            //
-            // Clean up
-            //
-            ServerCleanup();
-        }
-
-        return 0;
+    protected static void writeRef(ORB orb, PrintWriter out, org.omg.CORBA.Object objImpl) {
+        out.println("ref:");
+        out.println(orb.object_to_string(objImpl));
     }
 
     static void ServerCleanup() {
@@ -159,14 +165,12 @@
         file.delete();
     }
 
-    public static void main(String[] args) {
+    public static void main(String[] args) throws Exception {
         java.util.Properties props = new Properties();
         props.putAll(System.getProperties());
         props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
-        props.put("org.omg.CORBA.ORBSingletonClass",
-                "org.apache.yoko.orb.CORBA.ORBSingleton");
+        props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
 
-        int status = 0;
         ORB orb = null;
 
         try {
@@ -174,21 +178,11 @@
 
             props.put("yoko.orb.id", "myORB");
             orb = ORB.init(args, props);
-            status = ServerRun(orb, false, args);
-        } catch (Exception ex) {
-            ex.printStackTrace();
-            status = 1;
-        }
-
-        if (orb != null) {
-            try {
+            ServerRun(orb, false, args);
+        } finally {
+            if (orb != null) {
                 orb.destroy();
-            } catch (Exception ex) {
-                ex.printStackTrace();
-                status = 1;
             }
         }
-
-        System.exit(status);
     }
 }
diff --git a/yoko-core/src/test/java/test/pi/ServerORBInitializer_impl.java b/yoko-core/src/test/java/test/pi/ServerORBInitializer_impl.java
index c35d089..8a4d4cf 100644
--- a/yoko-core/src/test/java/test/pi/ServerORBInitializer_impl.java
+++ b/yoko-core/src/test/java/test/pi/ServerORBInitializer_impl.java
@@ -17,8 +17,10 @@
 
 package test.pi;
 
-import org.omg.CORBA.*;
-import org.omg.PortableInterceptor.*;
+import org.omg.PortableInterceptor.IORInterceptor;
+import org.omg.PortableInterceptor.ORBInitInfo;
+import org.omg.PortableInterceptor.ORBInitializer;
+import org.omg.PortableInterceptor.PolicyFactory;
 
 final public class ServerORBInitializer_impl extends org.omg.CORBA.LocalObject
         implements ORBInitializer {
@@ -40,7 +42,7 @@
         // Test: PICurrent::allocate_slot_id
         //
         int id = info.allocate_slot_id();
-        TEST(id == 0);
+        TEST(id >= 0);
 
         //
         // Test: register an IORInterceptor
diff --git a/yoko-core/src/test/java/test/pi/TestInterface_impl.java b/yoko-core/src/test/java/test/pi/TestInterface_impl.java
index 7d0ec7c..a940520 100644
--- a/yoko-core/src/test/java/test/pi/TestInterface_impl.java
+++ b/yoko-core/src/test/java/test/pi/TestInterface_impl.java
@@ -150,7 +150,9 @@
     }
 
     public void deactivate() {
+        System.out.println("TestInterface_Impl.deactivate() - calling orb.shutdown(false)");
         orb_.shutdown(false);
+        System.out.println("TestInterface_Impl.deactivate() - returned from orb.shutdown(false)");
     }
 
     public POA _default_POA() {
diff --git a/yoko-core/src/test/java/test/poa/PMSTestThread.java b/yoko-core/src/test/java/test/poa/PMSTestThread.java
index 1002cf6..a882e7e 100644
--- a/yoko-core/src/test/java/test/poa/PMSTestThread.java
+++ b/yoko-core/src/test/java/test/poa/PMSTestThread.java
@@ -17,47 +17,48 @@
 
 package test.poa;
 
-import org.omg.CORBA.*;
-import org.omg.PortableServer.*;
-import org.omg.PortableServer.POAPackage.*;
-import java.io.*;
+import java.util.concurrent.CountDownLatch;
 
 final class PMSTestThread extends Thread {
-    private Test test_;
+    private final Test test_;
 
-    private int state_;
+    private final CountDownLatch startLatch = new CountDownLatch(1);
+    public volatile Result result = null;
 
-    final static int NONE = 0;
-
-    final static int CALL_STARTED = 1;
-
-    final static int CALL_FAILURE = 2;
-
-    final static int CALL_SUCCESS = 3;
-
-    private synchronized void setState(int val) {
-        state_ = val;
-    }
+    public enum Result { SUCCESS, FAILURE, ERROR };
 
     public void run() {
-        setState(CALL_STARTED);
+        startLatch.countDown();
         try {
             test_.aMethod();
+            result = Result.SUCCESS;
         } catch (org.omg.CORBA.TRANSIENT ex) {
-            setState(CALL_FAILURE);
+            result = Result.FAILURE;
             return;
         } catch (org.omg.CORBA.SystemException ex) {
+            result = Result.ERROR;
             System.err.println("Unexpected: " + ex);
         }
-        setState(CALL_SUCCESS);
     }
 
-    synchronized int callState() {
-        return state_;
+    public void waitForStart() {
+        do {
+            try {
+                startLatch.await();
+                return;
+            } catch (InterruptedException ie) {}
+        } while (true);
+    }
+
+    public void waitForEnd() {
+        while (isAlive()) {
+            try {
+                join();
+            } catch (InterruptedException ie) {}
+        }
     }
 
     PMSTestThread(Test test) {
         test_ = test;
-        state_ = NONE;
     }
 }
diff --git a/yoko-core/src/test/java/test/poa/TestActivate.java b/yoko-core/src/test/java/test/poa/TestActivate.java
index fafdd44..683c6e7 100644
--- a/yoko-core/src/test/java/test/poa/TestActivate.java
+++ b/yoko-core/src/test/java/test/poa/TestActivate.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -52,10 +55,10 @@
 
         public void etherealize(byte[] oid, POA poa, Servant servant,
                 boolean cleanup, boolean remaining) {
-            TEST(TestUtil.Compare(oid_, oid));
-            TEST(poa_._is_equivalent(poa));
-            TEST(servant_ == servant);
-            TEST(remaining_ == remaining);
+            assertTrue(TestUtil.Compare(oid_, oid));
+            assertTrue(poa_._is_equivalent(poa));
+            assertTrue(servant_ == servant);
+            assertTrue(remaining_ == remaining);
             valid_ = true;
         }
     }
@@ -156,7 +159,7 @@
         //
         try {
             ether.set_servant_manager(null);
-            TEST(false); // set_servant_manager should not have succeeded
+            assertTrue(false); // set_servant_manager should not have succeeded
         } catch (OBJ_ADAPTER ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -184,7 +187,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(!TestUtil.Compare(id1, id2));
+        assertTrue(!TestUtil.Compare(id1, id2));
         try {
             tmpserv = system.id_to_servant(id1);
         } catch (ObjectNotActive ex) {
@@ -193,7 +196,7 @@
             throw new RuntimeException();
         }
 
-        TEST(tmpserv == servant1);
+        assertTrue(tmpserv == servant1);
         try {
             tmpserv = system.id_to_servant(id2);
         } catch (ObjectNotActive ex) {
@@ -201,14 +204,14 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(tmpserv == servant2);
+        assertTrue(tmpserv == servant2);
 
         //
         // Test: ServantAlreadyActive exception
         //
         try {
             system.activate_object(servant1);
-            TEST(false); // activate_object should not have succeeded
+            assertTrue(false); // activate_object should not have succeeded
         } catch (ServantAlreadyActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -217,7 +220,7 @@
 
         try {
             system.activate_object(servant2);
-            TEST(false); // activate_object should not have succeeded
+            assertTrue(false); // activate_object should not have succeeded
         } catch (ServantAlreadyActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -241,7 +244,7 @@
         //
         try {
             system.deactivate_object(id1);
-            TEST(false); // deactivate_object should not have succeeded
+            assertTrue(false); // deactivate_object should not have succeeded
         } catch (ObjectNotActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -250,7 +253,7 @@
 
         try {
             system.deactivate_object(id2);
-            TEST(false); // deactivate_object should not have succeeded
+            assertTrue(false); // deactivate_object should not have succeeded
         } catch (ObjectNotActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -262,7 +265,7 @@
         //
         try {
             nonretain.activate_object(servant1);
-            TEST(false); // activate_object should not have succeeded
+            assertTrue(false); // activate_object should not have succeeded
         } catch (WrongPolicy ex) {
             // expected
         } catch (ServantAlreadyActive ex) {
@@ -272,7 +275,7 @@
         try {
             byte[] id = ("XXX").getBytes();
             nonretain.activate_object_with_id(id, servant1);
-            TEST(false); // activate_object_with_id should not have succeeded
+            assertTrue(false); // activate_object_with_id should not have succeeded
         } catch (WrongPolicy ex) {
             // expected
         } catch (ServantAlreadyActive ex) {
@@ -284,7 +287,7 @@
         try {
             byte[] id = ("XXX").getBytes();
             nonretain.deactivate_object(id);
-            TEST(false); // deactivate_object should not have succeeded
+            assertTrue(false); // deactivate_object should not have succeeded
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         } catch (WrongPolicy ex) {
@@ -303,7 +306,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(!TestUtil.Compare(id1, id2));
+        assertTrue(!TestUtil.Compare(id1, id2));
         try {
             tmpserv = multiple.id_to_servant(id1);
         } catch (ObjectNotActive ex) {
@@ -311,7 +314,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(tmpserv == servant1);
+        assertTrue(tmpserv == servant1);
         try {
             tmpserv = multiple.id_to_servant(id2);
         } catch (ObjectNotActive ex) {
@@ -319,7 +322,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(tmpserv == servant1);
+        assertTrue(tmpserv == servant1);
 
         //
         // Test: confirm servant1 is no longer active
@@ -370,7 +373,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(activatorImpl.isValid());
+        assertTrue(activatorImpl.isValid());
         activatorImpl.expect(id2, ether, servant1, false);
         try {
             ether.deactivate_object(id2);
@@ -379,7 +382,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(activatorImpl.isValid());
+        assertTrue(activatorImpl.isValid());
         activatorImpl.expect(id3, ether, servant2, false);
         try {
             ether.deactivate_object(id3);
@@ -388,7 +391,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(activatorImpl.isValid());
+        assertTrue(activatorImpl.isValid());
 
         system.destroy(true, true);
         nonretain.destroy(true, true);
diff --git a/yoko-core/src/test/java/test/poa/TestAdapterActivatorServer.java b/yoko-core/src/test/java/test/poa/TestAdapterActivatorServer.java
index e91b2a6..82dcf9b 100644
--- a/yoko-core/src/test/java/test/poa/TestAdapterActivatorServer.java
+++ b/yoko-core/src/test/java/test/poa/TestAdapterActivatorServer.java
@@ -17,11 +17,15 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
 import org.omg.PortableServer.POAManagerPackage.*;
+
 import java.io.*;
 
 public final class TestAdapterActivatorServer extends test.common.TestBase {
@@ -39,9 +43,9 @@
         try {
             return parent.create_POA(name, mgr, policies);
         } catch (AdapterAlreadyExists ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (InvalidPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         return null;
@@ -70,7 +74,7 @@
         }
 
         public boolean unknown_adapter(POA parent, String name) {
-            TEST(name.equals(expectedName_));
+            assertTrue(name.equals(expectedName_));
             invoked_ = true;
             if (create_) {
                 Policy[] policies = new Policy[0];
@@ -78,9 +82,9 @@
                 try {
                     POA poa = parent.create_POA(name, mgr, policies);
                 } catch (AdapterAlreadyExists ex) {
-                    TEST(false);
+                    assertTrue(false);
                 } catch (InvalidPolicy ex) {
-                    TEST(false);
+                    assertTrue(false);
                 }
                 return true;
             } else
@@ -96,7 +100,7 @@
         String str;
 
         POAManager rootMgr = root.the_POAManager();
-        TEST(rootMgr != null);
+        assertTrue(rootMgr != null);
 
         //
         // If this function terminates due to an exception this
@@ -115,15 +119,15 @@
         try {
             poa = root.find_POA("poa1", true);
         } catch (AdapterNonExistent ex) {
-            TEST(false);
+            assertTrue(false);
         }
-        TEST(poa != null);
-        TEST(activatorImpl.invoked());
+        assertTrue(poa != null);
+        assertTrue(activatorImpl.invoked());
         str = poa.the_name();
-        TEST(str.equals("poa1"));
+        assertTrue(str.equals("poa1"));
         parent = poa.the_parent();
-        TEST(parent != null);
-        TEST(parent._is_equivalent(root));
+        assertTrue(parent != null);
+        assertTrue(parent._is_equivalent(root));
 
         //
         // Test: Activator and unsuccessful creation
@@ -134,7 +138,7 @@
         } catch (AdapterNonExistent ex) {
             // expected
         }
-        TEST(activatorImpl.invoked());
+        assertTrue(activatorImpl.invoked());
 
         //
         // Test: Make sure activator isn't called when POA already exists
@@ -143,9 +147,9 @@
         try {
             poa = root.find_POA("poa1", true);
         } catch (AdapterNonExistent ex) {
-            TEST(false);
+            assertTrue(false);
         }
-        TEST(!activatorImpl.invoked());
+        assertTrue(!activatorImpl.invoked());
 
         //
         // Test: Disable adapter activator and make sure it isn't invoked
@@ -157,7 +161,7 @@
         } catch (AdapterNonExistent ex) {
             // expected
         }
-        TEST(!activatorImpl.invoked());
+        assertTrue(!activatorImpl.invoked());
 
         poa.destroy(true, true);
 
@@ -165,11 +169,11 @@
             byte[] id = root.servant_to_id(activatorImpl);
             root.deactivate_object(id);
         } catch (ServantNotActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (ObjectNotActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (WrongPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -201,11 +205,11 @@
                     poa.activate_object_with_id(oid, servant);
                     return servant;
                 } catch (ObjectAlreadyActive ex) {
-                    TEST(false);
+                    assertTrue(false);
                 } catch (ServantAlreadyActive ex) {
-                    TEST(false);
+                    assertTrue(false);
                 } catch (WrongPolicy ex) {
-                    TEST(false);
+                    assertTrue(false);
                 }
             }
 
@@ -256,7 +260,7 @@
                     try {
                         poa.set_servant_manager(activator);
                     } catch (WrongPolicy ex) {
-                        TEST(false);
+                        assertTrue(false);
                     }
                 }
                 return true;
@@ -280,7 +284,7 @@
             POA root = TestUtil.GetRootPOA(orb);
 
             POAManager manager = root.the_POAManager();
-            TEST(manager != null);
+            assertTrue(manager != null);
 
             //
             // Run implementation
@@ -288,7 +292,7 @@
             try {
                 manager.activate();
             } catch (org.omg.PortableServer.POAManagerPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             TestAdapterActivator(orb, root);
diff --git a/yoko-core/src/test/java/test/poa/TestClient.java b/yoko-core/src/test/java/test/poa/TestClient.java
index 3f68b35..d9a1ee6 100644
--- a/yoko-core/src/test/java/test/poa/TestClient.java
+++ b/yoko-core/src/test/java/test/poa/TestClient.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 
 public class TestClient extends test.common.TestBase {
@@ -47,13 +50,13 @@
             }
 
             TestServer server = TestServerHelper.narrow(obj);
-            TEST(server != null);
+            assertTrue(server != null);
 
             TestInfo[] info = server.get_info();
             for (int i = 0; i < info.length; i++) {
                 try {
                     info[i].obj.aMethod();
-                    TEST(info[i].except_id.length() == 0);
+                    assertTrue(info[i].except_id.length() == 0);
                 } catch (SystemException ex) {
                     String id = org.apache.yoko.orb.OB.Util.getExceptionId(ex);
                     if (!id.equals(info[i].except_id)) {
@@ -62,7 +65,7 @@
                                 + "unexpected exception");
                         System.err.println("Expected " + info[i].except_id
                                 + " but caught " + id);
-                        TEST(false);
+                        assertTrue(false);
                     }
                 }
             }
diff --git a/yoko-core/src/test/java/test/poa/TestCollocated.java b/yoko-core/src/test/java/test/poa/TestCollocated.java
index 99b0b30..8f8f327 100644
--- a/yoko-core/src/test/java/test/poa/TestCollocated.java
+++ b/yoko-core/src/test/java/test/poa/TestCollocated.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -112,7 +115,7 @@
         test.aMethod();
         request = obj._request("aMethod");
         request.invoke();
-        TEST(request.env().exception() == null);
+        assertTrue(request.env().exception() == null);
 
         id = ("testDSI").getBytes();
         obj = poa.create_reference_with_id(id, "IDL:Test:1.0");
@@ -120,7 +123,7 @@
         test.aMethod();
         request = obj._request("aMethod");
         request.invoke();
-        TEST(request.env().exception() == null);
+        assertTrue(request.env().exception() == null);
     }
 
     static void TestDefaultServant(ORB orb, POA root, POAManager manager) {
diff --git a/yoko-core/src/test/java/test/poa/TestCreate.java b/yoko-core/src/test/java/test/poa/TestCreate.java
index e0824d6..662ba2f 100644
--- a/yoko-core/src/test/java/test/poa/TestCreate.java
+++ b/yoko-core/src/test/java/test/poa/TestCreate.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -32,12 +35,12 @@
         String str;
 
         POAManager rootMgr = root.the_POAManager();
-        TEST(rootMgr != null);
+        assertTrue(rootMgr != null);
 
         //
         // Test: POAManager should be in HOLDING state
         //
-        TEST(rootMgr.get_state() == State.HOLDING);
+        assertTrue(rootMgr.get_state() == State.HOLDING);
 
         //
         // Create child POA
@@ -54,31 +57,31 @@
         // Test: POAManager should NOT be the same as the root's manager
         //
         mgr = poa.the_POAManager();
-        TEST(!mgr._is_equivalent(rootMgr));
+        assertTrue(!mgr._is_equivalent(rootMgr));
 
         //
         // Test: POAManager should be in HOLDING state
         //
-        TEST(mgr.get_state() == State.HOLDING);
+        assertTrue(mgr.get_state() == State.HOLDING);
 
         //
         // Test: Confirm name
         //
         str = poa.the_name();
-        TEST(str.equals("poa1"));
+        assertTrue(str.equals("poa1"));
 
         //
         // Test: Confirm parent
         //
         parent = poa.the_parent();
-        TEST(parent._is_equivalent(root));
+        assertTrue(parent._is_equivalent(root));
 
         //
         // Test: AdapterAlreadyExists exception
         //
         try {
             poa2 = root.create_POA("poa1", null, policies);
-            TEST(false); // create_POA should not have succeeded
+            assertTrue(false); // create_POA should not have succeeded
         } catch (AdapterAlreadyExists ex) {
             // expected
         } catch (InvalidPolicy ex) {
@@ -94,7 +97,7 @@
 
         try {
             poa2 = root.create_POA("invalid", null, invalidpolicies);
-            TEST(false); // create_POA should not have succeeded
+            assertTrue(false); // create_POA should not have succeeded
         } catch (InvalidPolicy ex) {
             // expected
         } catch (AdapterAlreadyExists ex) {
@@ -116,7 +119,7 @@
         // Test: POAManager should be the same as the root's manager
         //
         mgr = poa2.the_POAManager();
-        TEST(mgr._is_equivalent(rootMgr));
+        assertTrue(mgr._is_equivalent(rootMgr));
 
         //
         // Create child of child POA
@@ -133,7 +136,7 @@
         // Test: Confirm parent
         //
         parent = poa3.the_parent();
-        TEST(parent._is_equivalent(poa2));
+        assertTrue(parent._is_equivalent(poa2));
 
         poa.destroy(true, true);
         poa2.destroy(true, true);
diff --git a/yoko-core/src/test/java/test/poa/TestDeactivate.java b/yoko-core/src/test/java/test/poa/TestDeactivate.java
index f04af78..8c56938 100644
--- a/yoko-core/src/test/java/test/poa/TestDeactivate.java
+++ b/yoko-core/src/test/java/test/poa/TestDeactivate.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -95,9 +98,9 @@
         try {
             oid = root.servant_to_id(impl);
         } catch (ServantNotActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (WrongPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         Thread thr = new LongCaller(t);
@@ -111,9 +114,9 @@
         try {
             root.deactivate_object(oid);
         } catch (ObjectNotActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (WrongPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
@@ -123,18 +126,18 @@
         try {
             root.activate_object_with_id(oid, impl);
         } catch (ObjectAlreadyActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (ServantAlreadyActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (WrongPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
         // The destroy call shouldn't return until the aMethod call is
         // complete
         //
-        TEST(impl.callComplete());
+        assertTrue(impl.callComplete());
 
         //
         // Wait for the thread to terminate
@@ -149,9 +152,9 @@
         try {
             root.deactivate_object(oid);
         } catch (ObjectNotActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (WrongPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -166,22 +169,22 @@
         try {
             oid = root.servant_to_id(impl);
         } catch (ServantNotActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (WrongPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             root.deactivate_object(oid);
         } catch (ObjectNotActive ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (WrongPolicy ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             t.aMethod();
-            TEST(false); // expected OBJECT_NOT_EXIST
+            assertTrue(false); // expected OBJECT_NOT_EXIST
         } catch (OBJECT_NOT_EXIST ex) {
             // Expected
         }
@@ -209,12 +212,12 @@
             // Activate the RootPOA manager
             //
             POAManager rootMgr = root.the_POAManager();
-            TEST(rootMgr != null);
+            assertTrue(rootMgr != null);
 
             try {
                 rootMgr.activate();
             } catch (org.omg.PortableServer.POAManagerPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             System.out.print("Testing deactivate... ");
diff --git a/yoko-core/src/test/java/test/poa/TestDestroy.java b/yoko-core/src/test/java/test/poa/TestDestroy.java
index 73cd061..88b054b 100644
--- a/yoko-core/src/test/java/test/poa/TestDestroy.java
+++ b/yoko-core/src/test/java/test/poa/TestDestroy.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -87,7 +90,7 @@
     //
     static void TestDestroyThreaded(ORB orb, POA root) {
         POAManager rootMgr = root.the_POAManager();
-        TEST(rootMgr != null);
+        assertTrue(rootMgr != null);
 
         Policy[] policies = new Policy[1];
         policies[0] = root
@@ -123,7 +126,7 @@
         // The destroy call shouldn't return until the aMethod call is
         // complete
         //
-        TEST(impl.callComplete());
+        assertTrue(impl.callComplete());
 
         while (thr.isAlive()) {
             try {
@@ -141,7 +144,7 @@
         String str;
 
         POAManager rootMgr = root.the_POAManager();
-        TEST(rootMgr != null);
+        assertTrue(rootMgr != null);
 
         //
         // Create child POA
@@ -164,7 +167,7 @@
         //
         try {
             root.find_POA("poa1", false);
-            TEST(false); // find_POA should not have succeeded
+            assertTrue(false); // find_POA should not have succeeded
         } catch (AdapterNonExistent ex) {
             // expected
         }
@@ -201,7 +204,7 @@
         //
         try {
             root.find_POA("poa1", false);
-            TEST(false); // find_POA should not have succeeded
+            assertTrue(false); // find_POA should not have succeeded
         } catch (AdapterNonExistent ex) {
             // expected
         }
@@ -230,7 +233,7 @@
             POA root = TestUtil.GetRootPOA(orb);
 
             POAManager rootMgr = root.the_POAManager();
-            TEST(rootMgr != null);
+            assertTrue(rootMgr != null);
 
             try {
                 rootMgr.activate();
diff --git a/yoko-core/src/test/java/test/poa/TestDispatchStrategyClient.java b/yoko-core/src/test/java/test/poa/TestDispatchStrategyClient.java
index c2c292b..ee03d63 100644
--- a/yoko-core/src/test/java/test/poa/TestDispatchStrategyClient.java
+++ b/yoko-core/src/test/java/test/poa/TestDispatchStrategyClient.java
@@ -17,6 +17,8 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.*;
 
 final public class TestDispatchStrategyClient extends test.common.TestBase {
@@ -57,7 +59,7 @@
 
             int idx;
             for (idx = 0; idx < info.length; idx++) {
-                TEST(info[idx].obj != null);
+                assertTrue(info[idx].obj != null);
 
                 for (int idx2 = 0; idx2 < 4; idx2++) {
                     req = info[idx].obj._request("aMethod");
diff --git a/yoko-core/src/test/java/test/poa/TestDispatchStrategyServer.java b/yoko-core/src/test/java/test/poa/TestDispatchStrategyServer.java
index 258e9e3..ea03185 100644
--- a/yoko-core/src/test/java/test/poa/TestDispatchStrategyServer.java
+++ b/yoko-core/src/test/java/test/poa/TestDispatchStrategyServer.java
@@ -17,135 +17,78 @@
 
 package test.poa;
 
-import java.io.*;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.HashSet;
 import java.util.Properties;
+import java.util.Set;
 
 public final class TestDispatchStrategyServer extends test.common.TestBase {
     //
     // Implementation to test same thread dispatch strategy
     //
-    final static class TestSameThread_impl extends TestPOA {
-        private Thread thread_;
+    abstract static class AbstractTest extends TestPOA {
+        private volatile boolean failed = false;
 
-        private boolean failed_;
-
-        private boolean first_;
-
-        TestSameThread_impl() {
-            failed_ = false;
-            first_ = true;
+        public final boolean failed() {
+            return failed;
         }
 
-        public void aMethod() {
-            //
-            // Test to ensure that all requests handled by the same thread
-            //
-            if (first_) {
-                thread_ = Thread.currentThread();
-                first_ = false;
-            } else if (!Thread.currentThread().equals(thread_)) {
-                failed_ = true;
+        protected void fail() {
+            failed = true;
+        }
+    }
+
+    abstract static class AbstractTestPool extends AbstractTest {
+        private final Set<Thread> threadSet = new HashSet<>();
+        private final int maxSize;
+
+        AbstractTestPool(int maxSize) {
+            this.maxSize = maxSize;
+        }
+
+        public final synchronized void aMethod() {
+            final Thread thisThread = Thread.currentThread();
+            if (threadSet.contains(thisThread)) return;
+            if (threadSet.size() < maxSize) {
+                threadSet.add(thisThread);
+                return;
             }
-
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException ex) {
-            }
+            fail();
         }
+    }
 
-        public boolean failed() {
-            return failed_;
-        }
+    final static class TestSameThread_impl extends AbstractTestPool {
+        TestSameThread_impl() { super(1); }
     }
 
     //
     // Implementation to test thread per request dispatch strategy
     //
-    final static class TestThreadPerReq_impl extends TestPOA {
-        private Thread threads_[];
+    final static class TestThreadPerReq_impl extends AbstractTest {
+        private final Set<Thread> threadSet = new HashSet<>();
 
-        private int thread_count_;
-
-        private boolean failed_;
-
-        TestThreadPerReq_impl() {
-            failed_ = false;
-            thread_count_ = 0;
-            threads_ = new Thread[5];
-        }
-
-        public void aMethod() {
-            int idx;
-            synchronized (this) {
-                //
-                // Test to ensure that each request is being handled
-                // by a different thread.
-                //
-                for (idx = 0; idx < thread_count_; idx++) {
-                    if (Thread.currentThread().equals(threads_[idx]))
-                        failed_ = true;
-                }
-
-                if (idx == thread_count_) {
-                    threads_[thread_count_++] = Thread.currentThread();
-                }
+        public synchronized void aMethod() {
+            final Thread thisThread = Thread.currentThread();
+            //
+            // Test to ensure that each request is being handled
+            // by a different thread.
+            //
+            if (threadSet.contains(thisThread)) {
+                fail();
+                return;
             }
-
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException ex) {
-            }
-        }
-
-        public boolean failed() {
-            return failed_;
+            threadSet.add(thisThread);
         }
     }
 
     //
     // Implementation to test thread pool dispatch strategy
     //
-    final static class TestThreadPool_impl extends TestPOA {
-        private Thread threads_[];
-
-        private int thread_count_;
-
-        private boolean failed_;
-
-        TestThreadPool_impl() {
-            failed_ = false;
-            thread_count_ = 0;
-            threads_ = new Thread[2];
-        }
-
-        public void aMethod() {
-            synchronized (this) {
-                //
-                // Test to ensure that all requests are handled only by
-                // the two threads in the thread pool.
-                //
-                if (thread_count_ == 0) {
-                    threads_[0] = Thread.currentThread();
-                    ++thread_count_;
-                } else if (!Thread.currentThread().equals(threads_[0])) {
-                    if (thread_count_ == 1) {
-                        threads_[1] = Thread.currentThread();
-                        ++thread_count_;
-                    } else if (!Thread.currentThread().equals(threads_[1])) {
-                        failed_ = true;
-                    }
-                }
-            }
-
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException ex) {
-            }
-        }
-
-        public boolean failed() {
-            return failed_;
-        }
+    final static class TestThreadPool_impl extends AbstractTestPool {
+        TestThreadPool_impl() { super(2); }
     }
 
     //
diff --git a/yoko-core/src/test/java/test/poa/TestFind.java b/yoko-core/src/test/java/test/poa/TestFind.java
index aea3dce..2d449eb 100644
--- a/yoko-core/src/test/java/test/poa/TestFind.java
+++ b/yoko-core/src/test/java/test/poa/TestFind.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -31,7 +34,7 @@
         String str;
 
         POAManager rootMgr = root.the_POAManager();
-        TEST(rootMgr != null);
+        assertTrue(rootMgr != null);
 
         //
         // Create child POA
@@ -52,15 +55,15 @@
         } catch (AdapterNonExistent ex) {
             throw new RuntimeException();
         }
-        TEST(poa2 != null);
-        TEST(poa2._is_equivalent(poa));
+        assertTrue(poa2 != null);
+        assertTrue(poa2._is_equivalent(poa));
 
         //
         // Test: AdapterNonExistent exception
         //
         try {
             poa2 = root.find_POA("poaX", false);
-            TEST(false); // find_POA should not have succeeded
+            assertTrue(false); // find_POA should not have succeeded
         } catch (AdapterNonExistent ex) {
             // expected
         }
@@ -85,8 +88,8 @@
             throw new RuntimeException();
         }
 
-        TEST(poa3 != null);
-        TEST(poa3._is_equivalent(poa2));
+        assertTrue(poa3 != null);
+        assertTrue(poa3._is_equivalent(poa2));
     }
 
     public static void main(String[] args) {
diff --git a/yoko-core/src/test/java/test/poa/TestLocationForwardClient.java b/yoko-core/src/test/java/test/poa/TestLocationForwardClient.java
index 51d4d1d..650f17e 100644
--- a/yoko-core/src/test/java/test/poa/TestLocationForwardClient.java
+++ b/yoko-core/src/test/java/test/poa/TestLocationForwardClient.java
@@ -17,10 +17,14 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
+
 import java.util.*;
 
 final public class TestLocationForwardClient extends test.common.TestBase {
@@ -90,7 +94,7 @@
             }
             TestLocationForwardServer server = TestLocationForwardServerHelper
                     .narrow(obj);
-            TEST(server != null);
+            assertTrue(server != null);
             org.omg.CORBA.Object servant = server.get_servant();
 
             activatorImpl.setForwardRequest(servant);
diff --git a/yoko-core/src/test/java/test/poa/TestMisc.java b/yoko-core/src/test/java/test/poa/TestMisc.java
index 459cd9c..6466927 100644
--- a/yoko-core/src/test/java/test/poa/TestMisc.java
+++ b/yoko-core/src/test/java/test/poa/TestMisc.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -58,7 +61,7 @@
         //
         try {
             obj = user.create_reference("IDL:Test:1.0");
-            TEST(false); // create_reference should not have succeeded
+            assertTrue(false); // create_reference should not have succeeded
         } catch (WrongPolicy ex) {
             // expected
         }
@@ -72,7 +75,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             id1 = system.reference_to_id(obj);
         } catch (WrongPolicy ex) {
@@ -85,7 +88,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             id2 = system.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -93,7 +96,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(!TestUtil.Compare(id1, id2));
+        assertTrue(!TestUtil.Compare(id1, id2));
 
         //
         // Test: create_reference_with_id using a system-generated ID
@@ -101,7 +104,7 @@
         try {
             obj = system.create_reference_with_id(id1, "IDL:Test:1.0");
         } catch (BAD_PARAM ex) {
-            TEST(false); // create_reference_with_id should have succeeded
+            assertTrue(false); // create_reference_with_id should have succeeded
         }
 
         id1 = ("id1").getBytes();
@@ -111,7 +114,7 @@
         //
         try {
             obj = system.create_reference_with_id(id1, "IDL:Test:1.0");
-            TEST(false); // create_reference_with_id should have not
+            assertTrue(false); // create_reference_with_id should have not
                             // succeeded
         } catch (BAD_PARAM ex) {
             // Expected
@@ -121,7 +124,7 @@
         // Test: create_reference_with_id
         //
         obj = user.create_reference_with_id(id1, "IDL:Test:1.0");
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid = user.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -129,10 +132,10 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(id1, tmpid));
+        assertTrue(TestUtil.Compare(id1, tmpid));
         id2 = ("id2").getBytes();
         obj = user.create_reference_with_id(id2, "IDL:Test:1.0");
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid = user.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -140,7 +143,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(id2, tmpid));
+        assertTrue(TestUtil.Compare(id2, tmpid));
 
         user.destroy(true, true);
         system.destroy(true, true);
@@ -220,7 +223,7 @@
         //
         try {
             unique.servant_to_id(servant1);
-            TEST(false); // servant_to_id should not have succeeded
+            assertTrue(false); // servant_to_id should not have succeeded
         } catch (ServantNotActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -248,7 +251,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(id1, tmpid));
+        assertTrue(TestUtil.Compare(id1, tmpid));
 
         //
         // Test: servant_to_id (IMPLICIT_ACTIVATION) - servant1 should
@@ -273,7 +276,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(id1, tmpid));
+        assertTrue(TestUtil.Compare(id1, tmpid));
 
         //
         // Test: Implicitly activating servant2 should produce a new ID
@@ -285,7 +288,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(!TestUtil.Compare(id1, id2));
+        assertTrue(!TestUtil.Compare(id1, id2));
 
         //
         // Test: servant_to_id (IMPLICIT_ACTIVATION, MULTIPLE_ID) - servant1
@@ -309,7 +312,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(!TestUtil.Compare(id1, tmpid));
+        assertTrue(!TestUtil.Compare(id1, tmpid));
 
         unique.destroy(true, true);
         implicit.destroy(true, true);
@@ -384,7 +387,7 @@
         try {
             tmpid = ("bad_id").getBytes();
             retain.id_to_servant(tmpid);
-            TEST(false); // id_to_servant should not have succeeded
+            assertTrue(false); // id_to_servant should not have succeeded
         } catch (ObjectNotActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -414,7 +417,7 @@
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(servant1 == tmpservant);
+        assertTrue(servant1 == tmpservant);
         try {
             tmpservant = retain.id_to_servant(id2);
         } catch (WrongPolicy ex) {
@@ -422,7 +425,7 @@
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(servant2 == tmpservant);
+        assertTrue(servant2 == tmpservant);
 
         //
         // Test: id_to_servant (USE_DEFAULT_SERVANT)
@@ -444,7 +447,7 @@
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(servant1 == tmpservant);
+        assertTrue(servant1 == tmpservant);
         try {
             tmpservant = defaultPOA.id_to_servant(id2);
         } catch (WrongPolicy ex) {
@@ -452,7 +455,7 @@
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(servant2 == tmpservant);
+        assertTrue(servant2 == tmpservant);
 
         //
         // Test: id_to_servant (USE_DEFAULT_SERVANT) - should return
@@ -466,7 +469,7 @@
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(tmpservant == def);
+        assertTrue(tmpservant == def);
         tmpservant = null;
 
         retain.destroy(true, true);
@@ -547,7 +550,7 @@
         //
         try {
             unique.servant_to_reference(servant1);
-            TEST(false); // servant_to_reference should not have succeeded
+            assertTrue(false); // servant_to_reference should not have succeeded
         } catch (ServantNotActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -575,7 +578,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid1 = unique.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -583,7 +586,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(id1, tmpid1));
+        assertTrue(TestUtil.Compare(id1, tmpid1));
 
         //
         // Test: servant_to_reference (IMPLICIT_ACTIVATION) - servant1 should
@@ -596,7 +599,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid1 = implicit.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -616,7 +619,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid2 = implicit.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -624,7 +627,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(tmpid1, tmpid2));
+        assertTrue(TestUtil.Compare(tmpid1, tmpid2));
 
         //
         // Test: Implicitly activating servant2 should produce a new ID
@@ -636,7 +639,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid2 = implicit.reference_to_id(obj);
         } catch (WrongPolicy ex) {
@@ -644,7 +647,7 @@
         } catch (WrongAdapter ex) {
             throw new RuntimeException();
         }
-        TEST(!TestUtil.Compare(tmpid1, tmpid2));
+        assertTrue(!TestUtil.Compare(tmpid1, tmpid2));
 
         //
         // Test: servant_to_reference (IMPLICIT_ACTIVATION, MULTIPLE_ID) -
@@ -657,7 +660,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid1 = multiple.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -676,7 +679,7 @@
         } catch (ServantNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid2 = multiple.reference_to_id(obj);
         } catch (WrongPolicy ex) {
@@ -684,7 +687,7 @@
         } catch (WrongAdapter ex) {
             throw new RuntimeException();
         }
-        TEST(!TestUtil.Compare(tmpid1, tmpid2));
+        assertTrue(!TestUtil.Compare(tmpid1, tmpid2));
 
         unique.destroy(true, true);
         implicit.destroy(true, true);
@@ -728,7 +731,7 @@
         try {
             tmpid = ("bad_id").getBytes();
             retain.id_to_reference(tmpid);
-            TEST(false); // id_to_reference should not have succeeded
+            assertTrue(false); // id_to_reference should not have succeeded
         } catch (ObjectNotActive ex) {
             // expected
         } catch (WrongPolicy ex) {
@@ -758,7 +761,7 @@
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid = retain.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -766,7 +769,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(id1, tmpid));
+        assertTrue(TestUtil.Compare(id1, tmpid));
 
         //
         // Test: servant_to_reference
@@ -778,7 +781,7 @@
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         }
-        TEST(obj != null);
+        assertTrue(obj != null);
         try {
             tmpid = retain.reference_to_id(obj);
         } catch (WrongAdapter ex) {
@@ -786,7 +789,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(id2, tmpid));
+        assertTrue(TestUtil.Compare(id2, tmpid));
 
         retain.destroy(true, true);
     }
@@ -860,7 +863,7 @@
             tmpid = ("bad_id").getBytes();
             obj = retain.create_reference_with_id(tmpid, "IDL:Test:1.0");
             retain.reference_to_servant(obj);
-            TEST(false); // reference_to_servant should not have succeeded
+            assertTrue(false); // reference_to_servant should not have succeeded
         } catch (ObjectNotActive ex) {
             // expected
         } catch (WrongAdapter ex) {
@@ -895,7 +898,7 @@
         } catch (WrongAdapter ex) {
             throw new RuntimeException();
         }
-        TEST(servant1 == tmpservant);
+        assertTrue(servant1 == tmpservant);
         obj = retain.create_reference_with_id(id2, "IDL:Test:1.0");
         try {
             tmpservant = retain.reference_to_servant(obj);
@@ -906,7 +909,7 @@
         } catch (WrongAdapter ex) {
             throw new RuntimeException();
         }
-        TEST(servant2 == tmpservant);
+        assertTrue(servant2 == tmpservant);
 
         //
         // Test: WrongAdapter exception
@@ -914,7 +917,7 @@
         try {
             obj = retain.create_reference_with_id(id1, "IDL:Test:1.0");
             defaultPOA.reference_to_servant(obj);
-            TEST(false); // reference_to_servant should not have succeeded
+            assertTrue(false); // reference_to_servant should not have succeeded
         } catch (ObjectNotActive ex) {
             throw new RuntimeException();
         } catch (WrongPolicy ex) {
@@ -946,7 +949,7 @@
         } catch (WrongAdapter ex) {
             throw new RuntimeException();
         }
-        TEST(servant1 == tmpservant);
+        assertTrue(servant1 == tmpservant);
         obj = defaultPOA.create_reference_with_id(id2, "IDL:Test:1.0");
         try {
             tmpservant = defaultPOA.reference_to_servant(obj);
@@ -957,7 +960,7 @@
         } catch (WrongAdapter ex) {
             throw new RuntimeException();
         }
-        TEST(servant2 == tmpservant);
+        assertTrue(servant2 == tmpservant);
 
         //
         // Test: reference_to_servant (USE_DEFAULT_SERVANT) - should return
@@ -974,7 +977,7 @@
         } catch (WrongAdapter ex) {
             throw new RuntimeException();
         }
-        TEST(tmpservant == def);
+        assertTrue(tmpservant == def);
         tmpservant = null;
 
         retain.destroy(true, true);
@@ -1021,7 +1024,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(tmpid, id1));
+        assertTrue(TestUtil.Compare(tmpid, id1));
         obj = poa.create_reference_with_id(id2, "IDL:Test:1.0");
         try {
             tmpid = poa.reference_to_id(obj);
@@ -1030,7 +1033,7 @@
         } catch (WrongPolicy ex) {
             throw new RuntimeException();
         }
-        TEST(TestUtil.Compare(tmpid, id2));
+        assertTrue(TestUtil.Compare(tmpid, id2));
 
         //
         // Test: WrongAdapter exception
@@ -1038,7 +1041,7 @@
         try {
             obj = poa.create_reference_with_id(id1, "IDL:Test:1.0");
             root.reference_to_id(obj);
-            TEST(false); // reference_to_id should not have succeeded
+            assertTrue(false); // reference_to_id should not have succeeded
         } catch (WrongAdapter ex) {
             // expected
         } catch (WrongPolicy ex) {
diff --git a/yoko-core/src/test/java/test/poa/TestMultipleOrbsThreadedClient.java b/yoko-core/src/test/java/test/poa/TestMultipleOrbsThreadedClient.java
index 2c41e0e..c905e4e 100644
--- a/yoko-core/src/test/java/test/poa/TestMultipleOrbsThreadedClient.java
+++ b/yoko-core/src/test/java/test/poa/TestMultipleOrbsThreadedClient.java
@@ -17,6 +17,8 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.*;
 
 final public class TestMultipleOrbsThreadedClient extends test.common.TestBase {
@@ -47,7 +49,7 @@
             }
 
             TestServer server = TestServerHelper.narrow(obj);
-            TEST(server != null);
+            assertTrue(server != null);
             TestInfo[] info = server.get_info();
 
             //
diff --git a/yoko-core/src/test/java/test/poa/TestPOAManagerClient.java b/yoko-core/src/test/java/test/poa/TestPOAManagerClient.java
index 7cc41fa..730f247 100644
--- a/yoko-core/src/test/java/test/poa/TestPOAManagerClient.java
+++ b/yoko-core/src/test/java/test/poa/TestPOAManagerClient.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -56,7 +59,7 @@
             try {
                 manager.activate();
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             TestInfo[] info = server.get_info();
diff --git a/yoko-core/src/test/java/test/poa/TestPOAManagerCommon.java b/yoko-core/src/test/java/test/poa/TestPOAManagerCommon.java
index 80c59ce..9a5895a 100644
--- a/yoko-core/src/test/java/test/poa/TestPOAManagerCommon.java
+++ b/yoko-core/src/test/java/test/poa/TestPOAManagerCommon.java
@@ -17,49 +17,61 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
 
+import java.util.concurrent.CountDownLatch;
+
 final class TestPOAManagerCommon extends test.common.TestBase {
     final static class TestHoldingState extends Thread {
         private Test test_;
 
-        private int state_;
+        private final CountDownLatch startLatch = new CountDownLatch(1);
+        public volatile Result result = null;
 
-        final static int NONE = 0;
-
-        final static int CALL_STARTED = 1;
-
-        final static int CALL_FAILURE = 2;
-
-        final static int CALL_SUCCESS = 3;
-
-        private synchronized void setState(int val) {
-            state_ = val;
-        }
+        public enum Result { SUCCESS, FAILURE, ERROR };
 
         TestHoldingState(Test test) {
             test_ = test;
-            state_ = NONE;
         }
 
         public void run() {
-            setState(CALL_STARTED);
+            startLatch.countDown();
             try {
                 test_.aMethod();
+                result = Result.SUCCESS;
             } catch (TRANSIENT ex) {
-                setState(CALL_FAILURE);
+                result = Result.FAILURE;
                 return;
             } catch (SystemException ex) {
+                result = Result.ERROR;
                 System.err.println("Unexpected: " + ex);
                 ex.printStackTrace();
             }
-            setState(CALL_SUCCESS);
         }
 
-        synchronized int callState() {
-            return state_;
+        public void waitForStart() {
+            do {
+                try {
+                    startLatch.await();
+                    return;
+                } catch (InterruptedException e) {
+                }
+            } while (true);
+        }
+
+
+
+        public void waitForEnd() {
+            while (isAlive()) {
+                try {
+                    join();
+                } catch (java.lang.InterruptedException e) {
+                }
+            }
         }
     }
 
@@ -68,7 +80,7 @@
             try {
                 manager.activate();
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             info[i].obj.aMethod();
@@ -80,12 +92,12 @@
             // 
             try {
                 manager.discard_requests(true);
-                TEST(false);
+                assertTrue(false);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER e) {
                 // Expected, ensure the state didn't change
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.ACTIVE);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.ACTIVE);
             }
 
             //
@@ -93,14 +105,14 @@
             //
             try {
                 manager.discard_requests(false);
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.DISCARDING);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.DISCARDING);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 info[i].obj.aMethod();
-                TEST(false);
+                assertTrue(false);
             } catch (TRANSIENT ex) {
                 // Expected
             }
@@ -108,7 +120,7 @@
             try {
                 manager.activate();
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             info[i].obj.aMethod();
@@ -120,12 +132,12 @@
             // 
             try {
                 manager.hold_requests(true);
-                TEST(false);
+                assertTrue(false);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER e) {
                 // Expected, ensure the state didn't change
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.ACTIVE);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.ACTIVE);
             }
 
             //
@@ -133,129 +145,79 @@
             //
             try {
                 manager.hold_requests(false);
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.HOLDING);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.HOLDING);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             TestHoldingState t = new TestHoldingState(info[i].obj);
             t.start();
-
-            //
-            // Wait for the call to start
-            //
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException ex) {
-                // Ignore
-            }
-
-            TEST(t.callState() == TestHoldingState.CALL_STARTED);
+            t.waitForStart();
 
             try {
                 manager.activate();
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
+            t.waitForEnd();
+            assertTrue(t.result == TestHoldingState.Result.SUCCESS);
 
-            //
-            // Wait for the call to complete
-            //
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException ex) {
-            }
-
-            TEST(t.callState() == TestHoldingState.CALL_SUCCESS);
 
             //
             // Test discard_requests when holding.
             //
             try {
                 manager.hold_requests(false);
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.HOLDING);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.HOLDING);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             t = new TestHoldingState(info[i].obj);
             t.start();
-
-            //
-            // Wait for the call to start
-            //
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException ex) {
-                // Ignore
-            }
-
-            TEST(t.callState() == TestHoldingState.CALL_STARTED);
-
+            t.waitForStart();
             try {
                 manager.discard_requests(false);
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.DISCARDING);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.DISCARDING);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 info[i].obj.aMethod();
-                TEST(false);
+                assertTrue(false);
             } catch (TRANSIENT ex) {
                 // Expected
             }
 
-            while (t.isAlive()) {
-                try {
-                    t.join();
-                } catch (java.lang.InterruptedException e) {
-                }
-            }
+            t.waitForEnd();
             //
             // Queued call should have been discarded.
             //
-            TEST(t.callState() == TestHoldingState.CALL_FAILURE);
+            assertTrue(t.result == TestHoldingState.Result.FAILURE);
 
             //
             // Test hold_requests when discarding.
             //
             try {
                 manager.hold_requests(false);
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.HOLDING);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.HOLDING);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             t = new TestHoldingState(info[i].obj);
             t.start();
-
-            //
-            // Wait for the call to start
-            //
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException ex) {
-                // Ignore
-            }
-
-            TEST(t.callState() == TestHoldingState.CALL_STARTED);
+            t.waitForStart();
 
             try {
                 manager.activate();
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
-            //
-            // Wait for the call to complete
-            //
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException ex) {
-            }
-
-            TEST(t.callState() == TestHoldingState.CALL_SUCCESS);
+            t.waitForEnd();
+            assertTrue(t.result == TestHoldingState.Result.SUCCESS);
 
             //
             // Try deactivate with wait completion == true,
@@ -264,12 +226,12 @@
             // 
             try {
                 manager.deactivate(true, true);
-                TEST(false);
+                assertTrue(false);
             } catch (test.poa.POAManagerProxyPackage.AdapterInactive ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.CORBA.BAD_INV_ORDER e) {
                 // Expected, ensure the state didn't change
-                TEST(manager.get_state() == test.poa.POAManagerProxyPackage.State.ACTIVE);
+                assertTrue(manager.get_state() == test.poa.POAManagerProxyPackage.State.ACTIVE);
             }
         }
     }
diff --git a/yoko-core/src/test/java/test/poa/TestPOAManagerFactory.java b/yoko-core/src/test/java/test/poa/TestPOAManagerFactory.java
index 7ad5136..1f2cf72 100644
--- a/yoko-core/src/test/java/test/poa/TestPOAManagerFactory.java
+++ b/yoko-core/src/test/java/test/poa/TestPOAManagerFactory.java
@@ -17,7 +17,10 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
@@ -39,7 +42,7 @@
         int count = 1;
 
         managers = pmFactory.list();
-        TEST(managers.length == 1);
+        assertTrue(managers.length == 1);
 
         //
         // Create POA Managers without policies
@@ -53,38 +56,38 @@
             test = pmFactory.create_POAManager("TestPOAManager", pl);
             count++;
         } catch (ManagerAlreadyExists ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (PolicyError ex) {
         }
 
         POAManager tmp = pmFactory.find("TestPOAManager");
-        TEST(tmp == test);
+        assertTrue(tmp == test);
         managers = pmFactory.list();
 
         //
         // count == 2
         //
-        TEST(count == 2);
-        TEST(managers.length == count);
+        assertTrue(count == 2);
+        assertTrue(managers.length == count);
 
         POAManager test2 = null;
         try {
             test2 = pmFactory.create_POAManager("TestPOAManager2", pl);
             count++;
         } catch (ManagerAlreadyExists ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (PolicyError ex) {
         }
 
         tmp = pmFactory.find("TestPOAManager2");
-        TEST(tmp == test2);
+        assertTrue(tmp == test2);
         managers = pmFactory.list();
 
         //
         // count == 3
         //
-        TEST(count == 3);
-        TEST(managers.length == count);
+        assertTrue(count == 3);
+        assertTrue(managers.length == count);
 
         try {
             test2 = pmFactory.create_POAManager("TestPOAManager2", pl);
@@ -93,7 +96,7 @@
             //
             // 'create_POAManager' should not have succeeded
             //
-            TEST(false);
+            assertTrue(false);
         } catch (ManagerAlreadyExists ex) {
             //
             // Expected
@@ -101,16 +104,16 @@
         } catch (PolicyError ex) {
         }
 
-        TEST(tmp == test2);
-        TEST(test != test2);
+        assertTrue(tmp == test2);
+        assertTrue(test != test2);
 
         managers = pmFactory.list();
 
         //
         // count == 3 (still)
         //
-        TEST(count == 3);
-        TEST(managers.length == count);
+        assertTrue(count == 3);
+        assertTrue(managers.length == count);
 
         //
         // Create POA Managers with proprietary policies
@@ -135,12 +138,12 @@
                         policies);
                 count++;
             } catch (ManagerAlreadyExists ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (PolicyError ex) {
             }
 
             tmp = pmFactory.find("ConfigManager");
-            TEST(tmp == configManager);
+            assertTrue(tmp == configManager);
         }
 
         managers = pmFactory.list();
@@ -148,8 +151,8 @@
         //
         // count == 4
         //
-        TEST(count == 4);
-        TEST(managers.length == count);
+        assertTrue(count == 4);
+        assertTrue(managers.length == count);
 
         //
         // Check the policy values
@@ -157,13 +160,13 @@
 
         org.apache.yoko.orb.OBPortableServer.CommunicationsConcurrencyPolicy commsPolicy = org.apache.yoko.orb.OBPortableServer.CommunicationsConcurrencyPolicyHelper
                 .narrow(policies[0]);
-        TEST(commsPolicy.value() == org.apache.yoko.orb.OBPortableServer.COMMUNICATIONS_CONCURRENCY_POLICY_THREADED.value);
-        TEST(commsPolicy.policy_type() == org.apache.yoko.orb.OBPortableServer.COMMUNICATIONS_CONCURRENCY_POLICY_ID.value);
+        assertTrue(commsPolicy.value() == org.apache.yoko.orb.OBPortableServer.COMMUNICATIONS_CONCURRENCY_POLICY_THREADED.value);
+        assertTrue(commsPolicy.policy_type() == org.apache.yoko.orb.OBPortableServer.COMMUNICATIONS_CONCURRENCY_POLICY_ID.value);
 
         org.apache.yoko.orb.OBPortableServer.GIOPVersionPolicy giopPolicy = org.apache.yoko.orb.OBPortableServer.GIOPVersionPolicyHelper
                 .narrow(policies[1]);
-        TEST(giopPolicy.value() == org.apache.yoko.orb.OBPortableServer.GIOP_VERSION_POLICY_1_2.value);
-        TEST(giopPolicy.policy_type() == org.apache.yoko.orb.OBPortableServer.GIOP_VERSION_POLICY_ID.value);
+        assertTrue(giopPolicy.value() == org.apache.yoko.orb.OBPortableServer.GIOP_VERSION_POLICY_1_2.value);
+        assertTrue(giopPolicy.policy_type() == org.apache.yoko.orb.OBPortableServer.GIOP_VERSION_POLICY_ID.value);
 
         //
         // EndpointConfigurationPolicy
@@ -183,7 +186,7 @@
             org.apache.yoko.orb.OBPortableServer.EndpointConfigurationPolicy endpointPolicy = org.apache.yoko.orb.OBPortableServer.EndpointConfigurationPolicyHelper
                     .narrow(policies2[0]);
 
-            TEST(endpointPolicy.policy_type() == org.apache.yoko.orb.OBPortableServer.ENDPOINT_CONFIGURATION_POLICY_ID.value);
+            assertTrue(endpointPolicy.policy_type() == org.apache.yoko.orb.OBPortableServer.ENDPOINT_CONFIGURATION_POLICY_ID.value);
 
             //
             // Create POA Manager with endpoint policy
@@ -194,12 +197,12 @@
                         "EndpointManager", policies2);
                 count++;
             } catch (ManagerAlreadyExists ex) {
-                TEST(false);
+                assertTrue(false);
             } catch (PolicyError ex) {
             }
 
             tmp = pmFactory.find("EndpointManager");
-            TEST(tmp == endpointManager);
+            assertTrue(tmp == endpointManager);
         }
 
         managers = pmFactory.list();
@@ -207,8 +210,8 @@
         //
         // count == 5
         //
-        TEST(count == 5);
-        TEST(managers.length == count);
+        assertTrue(count == 5);
+        assertTrue(managers.length == count);
     }
 
     static void runtests(ORB orb, POA root) {
diff --git a/yoko-core/src/test/java/test/poa/TestPOAManagerServer.java b/yoko-core/src/test/java/test/poa/TestPOAManagerServer.java
index ae691a0..b609416 100644
--- a/yoko-core/src/test/java/test/poa/TestPOAManagerServer.java
+++ b/yoko-core/src/test/java/test/poa/TestPOAManagerServer.java
@@ -17,10 +17,14 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
+
 import java.io.*;
 
 public final class TestPOAManagerServer extends test.common.TestBase {
@@ -113,10 +117,8 @@
             POA retain = null;
             try {
                 retain = root.create_POA("retain", null, policies);
-            } catch (AdapterAlreadyExists ex) {
-                throw new RuntimeException();
-            } catch (InvalidPolicy ex) {
-                throw new RuntimeException();
+            } catch (AdapterAlreadyExists | InvalidPolicy ex) {
+                throw new RuntimeException(ex);
             }
 
             POAManager retainManager = retain.the_POAManager();
@@ -129,12 +131,8 @@
             byte[] oid = ("test").getBytes();
             try {
                 retain.activate_object_with_id(oid, testImpl);
-            } catch (ObjectAlreadyActive ex) {
-                TEST(false);
-            } catch (ServantAlreadyActive ex) {
-                TEST(false);
-            } catch (WrongPolicy ex) {
-                TEST(false);
+            } catch (ObjectAlreadyActive | ServantAlreadyActive | WrongPolicy ex) {
+                throw new RuntimeException(ex);
             }
 
             Test test = testImpl._this();
@@ -143,12 +141,8 @@
             byte[] oidDSI = ("testDSI").getBytes();
             try {
                 retain.activate_object_with_id(oidDSI, testDSIImpl);
-            } catch (ObjectAlreadyActive ex) {
-                TEST(false);
-            } catch (ServantAlreadyActive ex) {
-                TEST(false);
-            } catch (WrongPolicy ex) {
-                TEST(false);
+            } catch (ObjectAlreadyActive | ServantAlreadyActive | WrongPolicy ex) {
+                throw new RuntimeException(ex);
             }
 
             org.omg.CORBA.Object objDSI = retain.create_reference_with_id(
@@ -175,13 +169,7 @@
             //
             PMSTestThread t = new PMSTestThread(test);
             t.start();
-
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException ex) {
-            }
-
-            TEST(t.callState() == PMSTestThread.CALL_STARTED);
+            t.waitForStart();
 
             //
             // Run implementation. This should cause the blocked call in
@@ -191,19 +179,11 @@
                 manager.activate();
                 retainManager.activate();
             } catch (org.omg.PortableServer.POAManagerPackage.AdapterInactive ex) {
-                throw new RuntimeException();
+                throw new RuntimeException(ex);
             }
+            t.waitForEnd();
 
-            //
-            // Wait for the call to complete
-            //
-            try {
-                Thread.sleep(500);
-            } catch (InterruptedException ex) {
-                // Ignore
-            }
-
-            TEST(t.callState() == PMSTestThread.CALL_SUCCESS);
+            assertTrue(t.result == PMSTestThread.Result.SUCCESS);
 
             new TestPOAManagerCommon(proxy, info);
 
diff --git a/yoko-core/src/test/java/test/poa/TestServantActivatorServer.java b/yoko-core/src/test/java/test/poa/TestServantActivatorServer.java
index 919636b..cbf94af 100644
--- a/yoko-core/src/test/java/test/poa/TestServantActivatorServer.java
+++ b/yoko-core/src/test/java/test/poa/TestServantActivatorServer.java
@@ -17,10 +17,13 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
 import org.omg.PortableServer.POAManagerPackage.*;
+
 import java.io.*;
 import java.util.Properties;
 
@@ -198,7 +201,7 @@
             }
             orb.run();
 
-            TEST(activatorImpl.etherealize_called());
+            assertTrue(activatorImpl.etherealize_called());
 
             File file = new File(refFile);
             file.delete();
diff --git a/yoko-core/src/test/java/test/poa/TestServantLocatorServer.java b/yoko-core/src/test/java/test/poa/TestServantLocatorServer.java
index c4fc68b..5916516 100644
--- a/yoko-core/src/test/java/test/poa/TestServantLocatorServer.java
+++ b/yoko-core/src/test/java/test/poa/TestServantLocatorServer.java
@@ -17,11 +17,14 @@
 
 package test.poa;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 import org.omg.PortableServer.*;
 import org.omg.PortableServer.POAPackage.*;
 import org.omg.PortableServer.POAManagerPackage.*;
 import org.omg.PortableServer.ServantLocatorPackage.*;
+
 import java.io.*;
 import java.util.Properties;
 
@@ -82,7 +85,7 @@
             // Check the cookie
             //
             String oidString = new String(oid);
-            TEST(oidString.equals((String) the_cookie));
+            assertTrue(oidString.equals((String) the_cookie));
 
             if (oidString.equals("testEx") && !operation.equals("_locate")) {
                 //
diff --git a/yoko-core/src/test/java/test/retry/Client.java b/yoko-core/src/test/java/test/retry/Client.java
index 0c6d927..01efcaa 100644
--- a/yoko-core/src/test/java/test/retry/Client.java
+++ b/yoko-core/src/test/java/test/retry/Client.java
@@ -17,6 +17,8 @@
 
 package test.retry;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
 
 public class Client extends test.common.TestBase {
@@ -29,10 +31,10 @@
         Test test = server.get_location_forward_object();
         try {
             test.aMethod();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TRANSIENT ex) {
             // Expected
-            TEST(ex.minor == org.apache.yoko.orb.OB.MinorCodes.MinorLocationForwardHopCountExceeded);
+            assertTrue(ex.minor == org.apache.yoko.orb.OB.MinorCodes.MinorLocationForwardHopCountExceeded);
         }
         System.out.println("Done!");
     }
@@ -55,7 +57,7 @@
             return RetryHelper.narrow(obj);
         } catch (org.omg.CORBA.UserException ex) {
             ex.printStackTrace();
-            TEST(false);
+            assertTrue(false);
             return null;
         }
     }
@@ -75,10 +77,10 @@
         retry.raise_exception(1, false);
         try {
             retry.aMethod();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TRANSIENT ex) {
             // Expected
-            TEST(retry.get_count() == 1);
+            assertTrue(retry.get_count() == 1);
         }
 
         //
@@ -89,9 +91,9 @@
         retry.raise_exception(1, false);
         try {
             retry.aMethod();
-            TEST(retry.get_count() == 2);
+            assertTrue(retry.get_count() == 2);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
 
@@ -106,10 +108,10 @@
         retry.raise_exception(1, true);
         try {
             retry.aMethod();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.SystemException ex) {
             // Expected
-            TEST(retry.get_count() == 1);
+            assertTrue(retry.get_count() == 1);
         }
         System.out.println("Done!");
 
@@ -123,10 +125,10 @@
         retry.raise_exception(1, false);
         try {
             retry.aMethod();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TRANSIENT ex) {
             // Expected
-            TEST(retry.get_count() == 1);
+            assertTrue(retry.get_count() == 1);
         }
         System.out.println("Done!");
 
@@ -140,9 +142,9 @@
         retry.raise_exception(1, true);
         try {
             retry.aMethod();
-            TEST(retry.get_count() == 2);
+            assertTrue(retry.get_count() == 2);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
 
@@ -156,9 +158,9 @@
         retry.raise_exception(5, false);
         try {
             retry.aMethod();
-            TEST(retry.get_count() == 6);
+            assertTrue(retry.get_count() == 6);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
@@ -169,10 +171,10 @@
         retry.raise_exception(6, false);
         try {
             retry.aMethod();
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TRANSIENT ex) {
             // Expected
-            TEST(retry.get_count() == 6);
+            assertTrue(retry.get_count() == 6);
         }
         System.out.println("Done!");
 
@@ -188,9 +190,9 @@
             long start = System.currentTimeMillis();
             retry.aMethod();
             long stop = System.currentTimeMillis();
-            TEST((stop - start) > 1000);
+            assertTrue((stop - start) > 1000);
         } catch (org.omg.CORBA.SystemException ex) {
-            TEST(false);
+            assertTrue(false);
         }
         System.out.println("Done!");
     }
@@ -215,7 +217,7 @@
                 System.exit(1);
             }
             RetryServer server = RetryServerHelper.narrow(obj);
-            TEST(server != null);
+            assertTrue(server != null);
 
             testLocationForward(orb, server);
             testRetry(orb, server);
diff --git a/yoko-core/src/test/java/test/rmi/ClientMain.java b/yoko-core/src/test/java/test/rmi/ClientMain.java
index 40e676f..ff12805 100755
--- a/yoko-core/src/test/java/test/rmi/ClientMain.java
+++ b/yoko-core/src/test/java/test/rmi/ClientMain.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -18,323 +18,405 @@
 package test.rmi;
 
 import java.io.BufferedReader;
-import java.io.FileInputStream;
 import java.io.FileReader;
-import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.Vector;
+import java.util.concurrent.TimeUnit;
 
-import javax.rmi.CORBA.Stub;
-import javax.rmi.CORBA.Util;
 import javax.rmi.PortableRemoteObject;
 
+import org.junit.Assert;
 import org.omg.PortableServer.POA;
-import org.omg.PortableServer.Servant;
-
-import junit.framework.Assert;
 
 public class ClientMain extends Assert {
 
-	public static class Test extends Assert {
-		private Sample sample;
-		public Test(Sample sample) {
-			this.sample = sample;
-		}
-		
-		// Test invoking methods with primitive arguments
-		public void testPrimitive() throws RemoteException {
-			sample.setBoolean(true);
-			assertTrue(sample.getBoolean());
-			sample.setByte((byte)64);
-			assertEquals((byte)64, sample.getByte());
-			sample.setShort((short)128);
-			assertEquals((short)128, sample.getShort());
-			sample.setInt(256);
-			assertEquals(256, sample.getInt());
-			sample.setLong(512);
-			assertEquals(512, sample.getLong());	
-			sample.setChar('a');
-			assertEquals('a', sample.getChar());
+    public static class Test extends Assert {
+        private Sample sample;
+        public Test(Sample sample) {
+            this.sample = sample;
+        }
 
-		}
+        // Test invoking methods with primitive arguments
+        public void testPrimitive() throws RemoteException {
+            sample.setBoolean(true);
+            assertTrue(sample.getBoolean());
+            sample.setByte((byte)64);
+            assertEquals((byte)64, sample.getByte());
+            sample.setShort((short)128);
+            assertEquals((short)128, sample.getShort());
+            sample.setInt(256);
+            assertEquals(256, sample.getInt());
+            sample.setLong(512);
+            assertEquals(512, sample.getLong());
+            sample.setChar('a');
+            assertEquals('a', sample.getChar());
 
-		// Test invoking methods with signature conflicts and arrays
-		public void testArray() throws RemoteException {
-                    assertTrue(10 == sample.sendReceiveInt(10));
-                    int[] intA = new int[] {10, 20};
+        }
 
-                    intA = sample.sendReceiveInt(intA); 
-                    assertEquals(2, intA.length); 
-                    assertTrue(20 == intA[0]); 
-                    assertTrue(10 == intA[1]); 
+        // Test invoking methods with signature conflicts and arrays
+        public void testArray() throws RemoteException {
+            assertTrue(10 == sample.sendReceiveInt(10));
+            int[] intA = new int[] {10, 20};
 
-                    assertTrue(10 == sample.sendReceiveShort((short)10));
-                    short[] shortA = new short[] {10, 20};
+            intA = sample.sendReceiveInt(intA);
+            assertEquals(2, intA.length);
+            assertTrue(20 == intA[0]);
+            assertTrue(10 == intA[1]);
 
-                    shortA = sample.sendReceiveShort(shortA); 
-                    assertEquals(2, shortA.length); 
-                    assertTrue(20 == shortA[0]); 
-                    assertTrue(10 == shortA[1]); 
+            assertTrue(10 == sample.sendReceiveShort((short)10));
+            short[] shortA = new short[] {10, 20};
 
-                    assertTrue(10 == sample.sendReceiveChar((char)10));
-                    char[] charA = new char[] {10, 20};
+            shortA = sample.sendReceiveShort(shortA);
+            assertEquals(2, shortA.length);
+            assertTrue(20 == shortA[0]);
+            assertTrue(10 == shortA[1]);
 
-                    charA = sample.sendReceiveChar(charA); 
-                    assertEquals(2, charA.length); 
-                    assertTrue(20 == charA[0]); 
-                    assertTrue(10 == charA[1]); 
+            assertTrue(10 == sample.sendReceiveChar((char)10));
+            char[] charA = new char[] {10, 20};
 
-                    assertTrue(10 == sample.sendReceiveByte((byte)10));
-                    byte[] byteA = new byte[] {10, 20};
+            charA = sample.sendReceiveChar(charA);
+            assertEquals(2, charA.length);
+            assertTrue(20 == charA[0]);
+            assertTrue(10 == charA[1]);
 
-                    byteA = sample.sendReceiveByte(byteA); 
-                    assertEquals(2, byteA.length); 
-                    assertTrue(20 == byteA[0]); 
-                    assertTrue(10 == byteA[1]); 
+            assertTrue(10 == sample.sendReceiveByte((byte)10));
+            byte[] byteA = new byte[] {10, 20};
 
-                    assertTrue(10L == sample.sendReceiveLong(10L));
-                    long[] longA = new long[] {10L, 20L};
+            byteA = sample.sendReceiveByte(byteA);
+            assertEquals(2, byteA.length);
+            assertTrue(20 == byteA[0]);
+            assertTrue(10 == byteA[1]);
 
-                    longA = sample.sendReceiveLong(longA); 
-                    assertEquals(2, longA.length); 
-                    assertTrue(20L == longA[0]); 
-                    assertTrue(10L == longA[1]); 
+            assertTrue(10L == sample.sendReceiveLong(10L));
+            long[] longA = new long[] {10L, 20L};
 
-                    assertTrue(10. == sample.sendReceiveFloat((float)10.));
-                    float[] floatA = new float[] {(float)10., (float)20.};
+            longA = sample.sendReceiveLong(longA);
+            assertEquals(2, longA.length);
+            assertTrue(20L == longA[0]);
+            assertTrue(10L == longA[1]);
 
-                    floatA = sample.sendReceiveFloat(floatA); 
-                    assertEquals(2, floatA.length); 
-                    assertTrue(20. == floatA[0]); 
-                    assertTrue(10. == floatA[1]); 
+            assertTrue(10. == sample.sendReceiveFloat((float)10.));
+            float[] floatA = new float[] {(float)10., (float)20.};
 
-                    assertTrue(10. == sample.sendReceiveDouble(10.));
-                    double[] doubleA = new double[] {10., 20.};
+            floatA = sample.sendReceiveFloat(floatA);
+            assertEquals(2, floatA.length);
+            assertTrue(20. == floatA[0]);
+            assertTrue(10. == floatA[1]);
 
-                    doubleA = sample.sendReceiveDouble(doubleA); 
-                    assertEquals(2, doubleA.length); 
-                    assertTrue(20. == doubleA[0]); 
-                    assertTrue(10. == doubleA[1]); 
+            assertTrue(10. == sample.sendReceiveDouble(10.));
+            double[] doubleA = new double[] {10., 20.};
 
-                    assertTrue(false == sample.sendReceiveBoolean(false));
-                    boolean[] booleanA = new boolean[] {true, false};
+            doubleA = sample.sendReceiveDouble(doubleA);
+            assertEquals(2, doubleA.length);
+            assertTrue(20. == doubleA[0]);
+            assertTrue(10. == doubleA[1]);
 
-                    booleanA = sample.sendReceiveBoolean(booleanA); 
-                    assertEquals(2, booleanA.length); 
-                    assertTrue(false == booleanA[0]); 
-                    assertTrue(true == booleanA[1]); 
+            assertTrue(false == sample.sendReceiveBoolean(false));
+            boolean[] booleanA = new boolean[] {true, false};
 
-                    assertTrue("a".equals(sample.sendReceiveString("a")));
-                    String[] StringA = new String[] {"a", "b"};
+            booleanA = sample.sendReceiveBoolean(booleanA);
+            assertEquals(2, booleanA.length);
+            assertTrue(false == booleanA[0]);
+            assertTrue(true == booleanA[1]);
 
-                    StringA = sample.sendReceiveString(StringA); 
-                    assertEquals(2, StringA.length); 
-                    assertTrue("b".equals(StringA[0])); 
-                    assertTrue("a".equals(StringA[1])); 
+            assertTrue("a".equals(sample.sendReceiveString("a")));
+            String[] StringA = new String[] {"a", "b"};
 
-                    SampleSerializable ser = new SampleSerializable();
-                    ser.setInt(10); 
-                    SampleSerializable ser2 = (SampleSerializable)sample.sendReceiveSerializable(ser); 
-                    assertEquals(10, ser2.getInt()); 
+            StringA = sample.sendReceiveString(StringA);
+            assertEquals(2, StringA.length);
+            assertTrue("b".equals(StringA[0]));
+            assertTrue("a".equals(StringA[1]));
 
-
-                    Serializable[] sA = new Serializable[] { ser };
-                    sA = sample.sendReceiveSerializable(sA); 
-
-                    ser2 = (SampleSerializable)sA[0]; 
-                    assertEquals(10, ser2.getInt()); 
-                    
-                    Remote r = sample.sendReceiveRemote(sample); 
-                    Sample sample2 = (Sample) PortableRemoteObject.narrow(r, Sample.class);
-                    assertEquals(sample, sample2);
-
-                    Remote[] rA = new Remote[] { sample }; 
-                    rA = sample.sendReceiveRemote(rA); 
-                    sample2 = (Sample) PortableRemoteObject.narrow(rA[0], Sample.class);
-                    assertEquals(sample, sample2);
-                }
-		
-		// Invoke method with String argument
-		public void testString() throws RemoteException {
-			sample.setString("hello");
-			assertEquals("hello", sample.getString());
-		}
-		
-		// Make sure that a field definition for a value-type interface 
-        // gets marshaled correctly.  The SampleSerializable object defines a 
-        // List field into which we'll place a Vector object.  This should properly 
-        // be processed as a value type rather than an abstract interface. 
-		public void testVector() throws RemoteException {
-            Vector v = new Vector(10);          
-            v.add("This is a test"); 
             SampleSerializable ser = new SampleSerializable();
-            ser.setList(v);  
-            SampleSerializable ser2 = (SampleSerializable)sample.sendReceiveSerializable(ser); 
+            ser.setInt(10);
+            SampleSerializable ser2 = (SampleSerializable)sample.sendReceiveSerializable(ser);
+            assertEquals(10, ser2.getInt());
+
+
+            Serializable[] sA = new Serializable[] { ser };
+            sA = sample.sendReceiveSerializable(sA);
+
+            ser2 = (SampleSerializable)sA[0];
+            assertEquals(10, ser2.getInt());
+
+            Remote r = sample.sendReceiveRemote(sample);
+            Sample sample2 = (Sample) PortableRemoteObject.narrow(r, Sample.class);
+            assertEquals(sample, sample2);
+
+            Remote[] rA = new Remote[] { sample };
+            rA = sample.sendReceiveRemote(rA);
+            sample2 = (Sample) PortableRemoteObject.narrow(rA[0], Sample.class);
+            assertEquals(sample, sample2);
+        }
+
+        // Invoke method with String argument
+        public void testString() throws RemoteException {
+            sample.setString("hello");
+            assertEquals("hello", sample.getString());
+        }
+
+        // Make sure that a field definition for a value-type interface
+        // gets marshaled correctly.  The SampleSerializable object defines a
+        // List field into which we'll place a Vector object.  This should properly
+        // be processed as a value type rather than an abstract interface.
+        public void testVector() throws RemoteException {
+            Vector v = new Vector(10);
+            v.add("This is a test");
+            SampleSerializable ser = new SampleSerializable();
+            ser.setList(v);
+            SampleSerializable ser2 = (SampleSerializable)sample.sendReceiveSerializable(ser);
             Vector v2 = (Vector)ser2.getList();
-            assertEquals(10, v2.capacity()); 
-            assertEquals(1, v2.size()); 
-            assertEquals("This is a test", v2.elementAt(0)); 
-		}
-		
-		public void testIntArray() throws RemoteException {
-			int[] intArray = new int[] {1, 2, 3};
-			sample.setIntArray(intArray);
-			int[] intArray2 = sample.getIntArray();
-			for(int i = 0; i < intArray.length; i++) {
-				assertEquals(intArray[i], intArray2[i]);
-			}			
-		}
-		
-		public void testBasicSerializable() throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-		}
-		
-		public void testRemoteAttributeOnServer() throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			ser.setRemote(sample);
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-			Sample sample2 = (Sample) PortableRemoteObject.narrow(ser2.getRemote(), Sample.class);
-			assertEquals(sample, sample2);
-			
-		}
-		
-		public void testRemoteAttributeOnClient() throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			SampleRemote sampleRemote = new SampleRemoteImpl();
-			ser.setRemote(sampleRemote);
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-			SampleRemote sampleRemote2 = 
-				(SampleRemote) PortableRemoteObject.narrow(ser2.getRemote(), SampleRemote.class);
-			sampleRemote.setInt(42);
-			assertEquals(42, sampleRemote2.getInt());
-		}
-		
-		public void testComplexRemoteAttributeOnClient() throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			SampleRemoteImpl sampleRemote = new SampleRemoteImpl();
-			ser.setSampleRemote(sampleRemote);
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-			SampleRemote sampleRemote2 = ser2.getSampleRemote();
-			sampleRemote.setInt(42);
-			assertEquals(42, sampleRemote2.getInt());
-		}
-		
-		public void testComplexRemoteArgument() throws RemoteException {
-			SampleRemoteImpl sampleRemote = new SampleRemoteImpl();
-			sample.setSampleRemote(sampleRemote);
-			sample.getSampleRemote();
-		}
-		
-		public void testSerializableAttribute() throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			SampleSerializable attr = new SampleSerializable();
-			ser.setSerializable(attr);
-			attr.setInt(42);
-			sample.setSerializable(ser);
-			SampleSerializable serCopy = (SampleSerializable) sample.getSerializable();
-			SampleSerializable attrCopy = (SampleSerializable) serCopy.getSerializable();
-			assertEquals(attr.getInt(), attrCopy.getInt());
-		}
-		
-		public void testSerializableSelfReference() throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			ser.setSerializableObject(ser);
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-			assertTrue(ser2 == ser2.getSerializableObject());
-		}
-		
-		public void testRemoteObjectAttribute() throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			SampleRemoteImpl sampleRemote = new SampleRemoteImpl();
-			ser.setRemoteObject(sampleRemote);
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-			SampleRemote sampleRemote2 = 
-				(SampleRemote) PortableRemoteObject.narrow(ser2.getRemoteObject(), SampleRemote.class);
-			sampleRemote.setInt(42);
-			assertEquals(42, sampleRemote2.getInt());
-		}
-		
-		public void testCorbaAttribute(SampleCorba corbaRef) throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			ser.setCorbaObj(corbaRef);
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-			SampleCorba corbaRef2 = SampleCorbaHelper.narrow(ser2.getCorbaObj());
-			corbaRef.i(42);
-			assertEquals(42, corbaRef2.i());
-		}
-		
-		public void testComplexCorbaAttribute(SampleCorba corbaRef) throws RemoteException {
-			SampleSerializable ser = new SampleSerializable();
-			ser.setSampleCorba(corbaRef);
-			sample.setSerializable(ser);
-			SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
-			SampleCorba corbaRef2 = ser2.getSampleCorba();
-		}
-		
-		public void testHashMap() throws RemoteException {
-			HashMap map = new HashMap();
-			String str = "hello";
-			map.put(new Integer(0), str);
-			map.put(new Integer(1), str);
-			Integer i = new Integer(2);
-			map.put(new Integer(3), i);
-			map.put(new Integer(4), i);
-			sample.setSerializable(map);
-			HashMap map2 = (HashMap) sample.getSerializable();
-			assertEquals(map, map2);			
-			assertTrue(map2.get(new Integer(3)) == map2.get(new Integer(4)));
-			assertTrue(map2.get(new Integer(0)) == map2.get(new Integer(1)));
-		}
-	}
-	
-	public static void main(String[] args) throws Exception {
-		// Initialize ORB
-		final org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(new String[0], null);
-		POA rootPoa = (POA) orb.resolve_initial_references("RootPOA");
-		rootPoa.the_POAManager().activate();
-		System.out.println("ORB: " + orb.getClass().getName());
-		
-		// Bind a sample CORBA object
-		SampleCorba_impl sampleCorba = new SampleCorba_impl();
-		byte [] id = rootPoa.activate_object(sampleCorba);
-		org.omg.CORBA.Object sampleCorbaRef = rootPoa.create_reference_with_id(id, sampleCorba._all_interfaces(rootPoa, id)[0]);
+            assertEquals(10, v2.capacity());
+            assertEquals(1, v2.size());
+            assertEquals("This is a test", v2.elementAt(0));
+        }
 
-		// Get IOR to Sample on server
-		BufferedReader reader = new BufferedReader(new FileReader("Sample.ref"));
-		String ref = reader.readLine();
-		org.omg.CORBA.Object sampleRef = orb.string_to_object(ref);
-		Sample sample = (Sample) PortableRemoteObject.narrow(sampleRef, Sample.class);
+        public void testIntArray() throws RemoteException {
+            int[] intArray = new int[] {1, 2, 3};
+            sample.setIntArray(intArray);
+            int[] intArray2 = sample.getIntArray();
+            for(int i = 0; i < intArray.length; i++) {
+                assertEquals(intArray[i], intArray2[i]);
+            }
+        }
 
-		// Run RMI tests
-		Test test = new Test(sample);
-        test.testVector(); 
-		test.testPrimitive();
-		test.testArray();
-		test.testString();
-		test.testIntArray();
-		test.testBasicSerializable();
-		test.testRemoteObjectAttribute();
-		test.testRemoteAttributeOnServer();
-		test.testRemoteAttributeOnClient();
-		test.testComplexRemoteAttributeOnClient();
-		test.testComplexRemoteArgument();
-		test.testSerializableAttribute();
-		test.testSerializableSelfReference();
-		test.testCorbaAttribute(SampleCorbaHelper.narrow(sampleCorbaRef));
-		test.testComplexCorbaAttribute(SampleCorbaHelper.narrow(sampleCorbaRef));
-		test.testHashMap();
-		//myORB.destroy();
-        System.out.println("Testing complete"); 
-	}
+        public void testBasicSerializable() throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+        }
+
+        public void testCmsfv2Data() throws RemoteException {
+            SampleCmsfv2ChildData d = new SampleCmsfv2ChildData();
+            for (int i = 0; i < 10; i++) {
+                System.out.println("Discarding " + d);
+                d = new SampleCmsfv2ChildData();
+            }
+
+            sample.setSerializable(d);
+            Serializable s = sample.getSerializable();
+            assertNotSame(d, s);
+            assertEquals(d, s);
+        }
+
+        public void testEnum() throws RemoteException {
+            SampleEnum se = SampleEnum.SAMPLE2;
+            sample.setSerializable(se);
+            Serializable s = sample.getSerializable();
+            assertSame(se, s);
+        }
+
+        public void testEnumArray() throws RemoteException {
+            SampleEnum[] sa = { SampleEnum.SAMPLE3, SampleEnum.SAMPLE1, SampleEnum.SAMPLE3 };
+            sample.setSerializable(sa);
+            Object[] oa = (Object[])sample.getSerializable();
+            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);
+            Serializable s = sample.getSerializable();
+            assertSame(tu, s);
+        }
+
+        public void testTimeUnitArray() throws RemoteException {
+            TimeUnit[] tua = { TimeUnit.NANOSECONDS, TimeUnit.HOURS, TimeUnit.NANOSECONDS };
+            sample.setSerializable(tua);
+            Object[] oa = (Object[])sample.getSerializable();
+            assertTrue(Arrays.deepEquals(tua, oa));
+        }
+
+        public void testRemoteAttributeOnServer() throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            ser.setRemote(sample);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            Sample sample2 = (Sample) PortableRemoteObject.narrow(ser2.getRemote(), Sample.class);
+            assertEquals(sample, sample2);
+
+        }
+
+        public void testRemoteAttributeOnClient() throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            SampleRemote sampleRemote = new SampleRemoteImpl();
+            ser.setRemote(sampleRemote);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            SampleRemote sampleRemote2 =
+                    (SampleRemote) PortableRemoteObject.narrow(ser2.getRemote(), SampleRemote.class);
+            sampleRemote.setInt(42);
+            assertEquals(42, sampleRemote2.getInt());
+        }
+
+        public void testComplexRemoteAttributeOnClient() throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            SampleRemoteImpl sampleRemote = new SampleRemoteImpl();
+            ser.setSampleRemote(sampleRemote);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            SampleRemote sampleRemote2 = ser2.getSampleRemote();
+            sampleRemote.setInt(42);
+            assertEquals(42, sampleRemote2.getInt());
+        }
+
+        public void testComplexRemoteArgument() throws RemoteException {
+            SampleRemoteImpl sampleRemote = new SampleRemoteImpl();
+            sample.setSampleRemote(sampleRemote);
+            sample.getSampleRemote();
+        }
+
+        public void testSerializableAttribute() throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            SampleSerializable attr = new SampleSerializable();
+            ser.setSerializable(attr);
+            attr.setInt(42);
+            sample.setSerializable(ser);
+            SampleSerializable serCopy = (SampleSerializable) sample.getSerializable();
+            SampleSerializable attrCopy = (SampleSerializable) serCopy.getSerializable();
+            assertEquals(attr.getInt(), attrCopy.getInt());
+        }
+
+        public void testSerializableSelfReference() throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            ser.setSerializableObject(ser);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            assertTrue(ser2 == ser2.getSerializableObject());
+        }
+
+        public void testRemoteObjectAttribute() throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            SampleRemoteImpl sampleRemote = new SampleRemoteImpl();
+            ser.setRemoteObject(sampleRemote);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            SampleRemote sampleRemote2 =
+                    (SampleRemote) PortableRemoteObject.narrow(ser2.getRemoteObject(), SampleRemote.class);
+            sampleRemote.setInt(42);
+            assertEquals(42, sampleRemote2.getInt());
+        }
+
+        public void testCorbaAttributeWithHelper(SampleCorba corbaRef) throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            ser.setCorbaObj(corbaRef);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            SampleCorba corbaRef2 = SampleCorbaHelper.narrow(ser2.getCorbaObj());
+            corbaRef.i(42);
+            assertEquals(42, corbaRef2.i());
+            corbaRef.s("Don't panic!");
+            assertEquals("Don't panic!", corbaRef2.s());
+        }
+
+        public void testCorbaAttributeWithPRO(SampleCorba corbaRef) throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            ser.setCorbaObj(corbaRef);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            SampleCorba corbaRef2 = (SampleCorba) PortableRemoteObject.narrow(ser2.getCorbaObj(), SampleCorba.class);
+            corbaRef.i(42);
+            assertEquals(42, corbaRef2.i());
+            corbaRef.s("Don't panic!");
+            assertEquals("Don't panic!", corbaRef2.s());
+        }
+
+        public void testComplexCorbaAttribute(SampleCorba corbaRef) throws RemoteException {
+            SampleSerializable ser = new SampleSerializable();
+            ser.setSampleCorba(corbaRef);
+            sample.setSerializable(ser);
+            SampleSerializable ser2 = (SampleSerializable) sample.getSerializable();
+            SampleCorba corbaRef2 = ser2.getSampleCorba();
+        }
+
+        public void testHashMap() throws RemoteException {
+            HashMap<Integer, Serializable> map = new HashMap<>();
+            String str = new String("hello");
+            map.put(0, str);
+            map.put(1, str);
+            Integer two = new Integer(2);
+            map.put(3, two);
+            map.put(4, two);
+            sample.setSerializable(map);
+            Map<?,?> map2 = (Map<?,?>) sample.getSerializable();
+            assertEquals(map, map2);
+            assertSame(map2.get(3), map2.get(4));
+            assertSame(map2.get(0), map2.get(1));
+        }
+
+        public void testClass() throws RemoteException {
+            final Class<?> type = Object.class;
+            sample.setSerializable(type);
+            Serializable s = sample.getSerializable();
+            assertSame(s, type);
+        }
+
+        public void testClassArray() throws RemoteException {
+            final Class<?>[] types = { Object.class, Map.class, String.class, Map.class };
+            sample.setSerializable(types);
+            Object[] oa = (Object[])sample.getSerializable();
+            assertArrayEquals(types, oa);
+        }
+    }
+
+    public static void main(String[] args) throws Exception {
+        // Initialize ORB
+        final org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(new String[0], null);
+        POA rootPoa = (POA) orb.resolve_initial_references("RootPOA");
+        rootPoa.the_POAManager().activate();
+        System.out.println("ORB: " + orb.getClass().getName());
+
+        // Bind a sample CORBA object
+        SampleCorba_impl sampleCorba = new SampleCorba_impl();
+        byte [] id = rootPoa.activate_object(sampleCorba);
+        org.omg.CORBA.Object sampleCorbaRef = rootPoa.create_reference_with_id(id, sampleCorba._all_interfaces(rootPoa, id)[0]);
+
+        // Get IOR to Sample on server
+        BufferedReader reader = new BufferedReader(new FileReader("Sample.ref"));
+        String ref = reader.readLine();
+        org.omg.CORBA.Object sampleRef = orb.string_to_object(ref);
+        Sample sample = (Sample) PortableRemoteObject.narrow(sampleRef, Sample.class);
+
+        // Run RMI tests
+        Test test = new Test(sample);
+        test.testVector();
+        test.testPrimitive();
+        test.testArray();
+        test.testString();
+        test.testIntArray();
+        test.testBasicSerializable();
+        test.testRemoteObjectAttribute();
+        test.testRemoteAttributeOnServer();
+        test.testRemoteAttributeOnClient();
+        test.testComplexRemoteAttributeOnClient();
+        test.testComplexRemoteArgument();
+        test.testSerializableAttribute();
+        test.testSerializableSelfReference();
+        test.testCorbaAttributeWithHelper(SampleCorbaHelper.narrow(sampleCorbaRef));
+        test.testCorbaAttributeWithPRO((SampleCorba) PortableRemoteObject.narrow(sampleCorbaRef, SampleCorba.class));
+        test.testComplexCorbaAttribute(SampleCorbaHelper.narrow(sampleCorbaRef));
+        test.testHashMap();
+        test.testEnum();
+        test.testEnumArray();
+        test.testData();
+        test.testTimeUnit();
+        test.testTimeUnitArray();
+        test.testCmsfv2Data();
+        test.testClass();
+        test.testClassArray();
+        //myORB.destroy();
+        System.out.println("Testing complete");
+    }
 }
diff --git a/yoko-core/src/test/java/test/rmi/SampleCmsfv2ChildData.java b/yoko-core/src/test/java/test/rmi/SampleCmsfv2ChildData.java
new file mode 100644
index 0000000..c7120ce
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/SampleCmsfv2ChildData.java
@@ -0,0 +1,25 @@
+package test.rmi;
+
+public class SampleCmsfv2ChildData extends SampleCmsfv2ParentData {
+    private static final long serialVersionUID = 1L;
+    private final String value = "splat";
+    
+    @Override
+    public int hashCode() {
+        return 31*super.hashCode() + value.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!super.equals(obj))
+            return false;
+        if (!(obj instanceof SampleCmsfv2ChildData))
+            return false;
+        return value.equals(((SampleCmsfv2ChildData) obj).value);
+    }
+    
+    @Override
+    public String toString() {
+        return String.format("%s:\"%s\"", super.toString(), value);
+    }
+}
diff --git a/yoko-core/src/test/java/test/rmi/SampleCmsfv2ParentData.java b/yoko-core/src/test/java/test/rmi/SampleCmsfv2ParentData.java
new file mode 100644
index 0000000..6cfd675
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/SampleCmsfv2ParentData.java
@@ -0,0 +1,49 @@
+package test.rmi;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+
+/**
+ * A class that writes more data than it reads in.
+ * This is dangerous since a child class may not know where its own data begins.
+ * This is addressed in custom marshaled stream format version 2, which boxes the 
+ * parent data so the reading ORB can skip to the end of any custom marshaled 
+ * parent data before reading in the child data.
+ */
+public class SampleCmsfv2ParentData implements Serializable {
+    private static final long serialVersionUID = 1L;
+    private final byte value = (byte) 0xdd;
+
+    private void readObject(ObjectInputStream ois) throws ClassNotFoundException, IOException {
+        ois.defaultReadObject();
+    }
+
+    private void writeObject(ObjectOutputStream oos) throws IOException {
+        oos.defaultWriteObject();
+        oos.writeObject(new Object[0]);
+        oos.writeByte(0x77);
+    }
+
+    @Override
+    public int hashCode() {
+        return 31 + value;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (!(obj instanceof SampleCmsfv2ParentData))
+            return false;
+        return (value == ((SampleCmsfv2ParentData) obj).value);
+    }
+    
+    @Override
+    public String toString() {
+        return String.format("%s:%02x", super.toString(), value);
+    }
+}
diff --git a/yoko-core/src/test/java/test/rmi/SampleCorba.java b/yoko-core/src/test/java/test/rmi/SampleCorba.java
index 61b29ea..262e5b5 100755
--- a/yoko-core/src/test/java/test/rmi/SampleCorba.java
+++ b/yoko-core/src/test/java/test/rmi/SampleCorba.java
@@ -15,15 +15,14 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package test.rmi;
 
 
 /**
 * test/rmi/SampleCorba.java .
-* Generated by the IDL-to-Java compiler (portable), version "3.2"
-* from src/test/java/test/rmi/SampleCorbaObject.idl
-* 9. maj 2006 14:03:27 CEST
+* Generated by the IDL-to-Java compiler (portable), version "3.0"
+* from SampleCorbaObject.idl
+* Tuesday, 28 April 2015 17:10:49 o'clock BST
 */
 
 public interface SampleCorba extends SampleCorbaOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity 
diff --git a/yoko-core/src/test/java/test/rmi/SampleCorbaHelper.java b/yoko-core/src/test/java/test/rmi/SampleCorbaHelper.java
index d7f08d3..2487689 100755
--- a/yoko-core/src/test/java/test/rmi/SampleCorbaHelper.java
+++ b/yoko-core/src/test/java/test/rmi/SampleCorbaHelper.java
@@ -15,15 +15,14 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package test.rmi;
 
 
 /**
 * test/rmi/SampleCorbaHelper.java .
-* Generated by the IDL-to-Java compiler (portable), version "3.2"
-* from src/test/java/test/rmi/SampleCorbaObject.idl
-* 9. maj 2006 14:03:27 CEST
+* Generated by the IDL-to-Java compiler (portable), version "3.0"
+* from SampleCorbaObject.idl
+* Tuesday, 28 April 2015 17:10:49 o'clock BST
 */
 
 abstract public class SampleCorbaHelper
@@ -40,17 +39,21 @@
 
   public static test.rmi.SampleCorba extract (org.omg.CORBA.Any a)
   {
+    if (!a.type().equal(type()))
+        throw new org.omg.CORBA.BAD_OPERATION("extract() failed.Expected a test.rmi.SampleCorba .");
     return read (a.create_input_stream ());
   }
 
-  private static org.omg.CORBA.TypeCode __typeCode = null;
-  synchronized public static org.omg.CORBA.TypeCode type ()
+  private static volatile org.omg.CORBA.TypeCode __typeCode = null;
+  public static org.omg.CORBA.TypeCode type ()
   {
-    if (__typeCode == null)
+  org.omg.CORBA.TypeCode __localTc = __typeCode;
+    if (__localTc == null)
     {
-      __typeCode = org.omg.CORBA.ORB.init ().create_interface_tc (test.rmi.SampleCorbaHelper.id (), "SampleCorba");
+      __localTc = org.omg.CORBA.ORB.init ().create_interface_tc (test.rmi.SampleCorbaHelper.id (), "SampleCorba");
+      __typeCode = __localTc;
     }
-    return __typeCode;
+    return __localTc;
   }
 
   public static String id ()
@@ -79,9 +82,7 @@
     else
     {
       org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
-      test.rmi._SampleCorbaStub stub = new test.rmi._SampleCorbaStub ();
-      stub._set_delegate(delegate);
-      return stub;
+      return new test.rmi._SampleCorbaStub (delegate);
     }
   }
 
@@ -94,9 +95,7 @@
     else
     {
       org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl)obj)._get_delegate ();
-      test.rmi._SampleCorbaStub stub = new test.rmi._SampleCorbaStub ();
-      stub._set_delegate(delegate);
-      return stub;
+      return new test.rmi._SampleCorbaStub (delegate);
     }
   }
 
diff --git a/yoko-core/src/test/java/test/rmi/SampleCorbaHolder.java b/yoko-core/src/test/java/test/rmi/SampleCorbaHolder.java
index fe8060c..8486467 100755
--- a/yoko-core/src/test/java/test/rmi/SampleCorbaHolder.java
+++ b/yoko-core/src/test/java/test/rmi/SampleCorbaHolder.java
@@ -15,14 +15,13 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package test.rmi;
 
 /**
 * test/rmi/SampleCorbaHolder.java .
-* Generated by the IDL-to-Java compiler (portable), version "3.2"
-* from src/test/java/test/rmi/SampleCorbaObject.idl
-* 9. maj 2006 14:03:27 CEST
+* Generated by the IDL-to-Java compiler (portable), version "3.0"
+* from SampleCorbaObject.idl
+* Tuesday, 28 April 2015 17:10:49 o'clock BST
 */
 
 public final class SampleCorbaHolder implements org.omg.CORBA.portable.Streamable
diff --git a/yoko-core/src/test/java/test/rmi/SampleCorbaObject.idl b/yoko-core/src/test/java/test/rmi/SampleCorbaObject.idl
index 19dea25..abf5097 100755
--- a/yoko-core/src/test/java/test/rmi/SampleCorbaObject.idl
+++ b/yoko-core/src/test/java/test/rmi/SampleCorbaObject.idl
@@ -1,5 +1,5 @@
-/**

- *

+/**
+ *
  * 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.
@@ -7,19 +7,20 @@
 *  (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.

- */

-module test {

-  module rmi {

-    interface SampleCorba {

-      attribute long i;

-    };

-  };

-};
\ No newline at end of file
+ *
+ *     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.
+ */
+module test {
+  module rmi {
+    interface SampleCorba {
+      attribute long i;
+      attribute string s;
+    };
+  };
+};
diff --git a/yoko-core/src/test/java/test/rmi/SampleCorbaOperations.java b/yoko-core/src/test/java/test/rmi/SampleCorbaOperations.java
index ba35c8d..45592b5 100755
--- a/yoko-core/src/test/java/test/rmi/SampleCorbaOperations.java
+++ b/yoko-core/src/test/java/test/rmi/SampleCorbaOperations.java
@@ -15,19 +15,20 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package test.rmi;
 
 
 /**
 * test/rmi/SampleCorbaOperations.java .
-* Generated by the IDL-to-Java compiler (portable), version "3.2"
-* from src/test/java/test/rmi/SampleCorbaObject.idl
-* 9. maj 2006 14:03:27 CEST
+* Generated by the IDL-to-Java compiler (portable), version "3.0"
+* from SampleCorbaObject.idl
+* Tuesday, 28 April 2015 17:10:49 o'clock BST
 */
 
 public interface SampleCorbaOperations 
 {
   int i ();
   void i (int newI);
+  String s ();
+  void s (String newS);
 } // interface SampleCorbaOperations
diff --git a/yoko-core/src/test/java/test/rmi/SampleCorbaPOA.java b/yoko-core/src/test/java/test/rmi/SampleCorbaPOA.java
index 055e57e..0d448bf 100755
--- a/yoko-core/src/test/java/test/rmi/SampleCorbaPOA.java
+++ b/yoko-core/src/test/java/test/rmi/SampleCorbaPOA.java
@@ -15,28 +15,47 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package test.rmi;
 
 
 /**
 * test/rmi/SampleCorbaPOA.java .
-* Generated by the IDL-to-Java compiler (portable), version "3.2"
-* from src/test/java/test/rmi/SampleCorbaObject.idl
-* 9. maj 2006 14:03:27 CEST
+* Generated by the IDL-to-Java compiler (portable), version "3.0"
+* from SampleCorbaObject.idl
+* Tuesday, 28 April 2015 17:10:49 o'clock BST
 */
 
 public abstract class SampleCorbaPOA extends org.omg.PortableServer.Servant
- implements test.rmi.SampleCorbaOperations, org.omg.CORBA.portable.InvokeHandler
+                implements test.rmi.SampleCorbaOperations, org.omg.CORBA.portable.InvokeHandler
 {
 
-  // Constructors
+  public test.rmi.SampleCorba _this() {
+     return test.rmi.SampleCorbaHelper.narrow(
+        super._this_object());
+  }
+
+  public test.rmi.SampleCorba _this(org.omg.CORBA.ORB orb) {
+     return test.rmi.SampleCorbaHelper.narrow(
+        super._this_object(orb));
+  }
+
+  public String[] _all_interfaces(
+     org.omg.PortableServer.POA poa,
+     byte[] objectId) {
+         return (String[])__ids.clone();
+  }
+
+  // Type-specific CORBA::Object operations
+  private static String[] __ids = {
+    "IDL:test/rmi/SampleCorba:1.0"};
 
   private static java.util.Hashtable _methods = new java.util.Hashtable ();
   static
   {
     _methods.put ("_get_i", new java.lang.Integer (0));
     _methods.put ("_set_i", new java.lang.Integer (1));
+    _methods.put ("_get_s", new java.lang.Integer (2));
+    _methods.put ("_set_s", new java.lang.Integer (3));
   }
 
   public org.omg.CORBA.portable.OutputStream _invoke (String $method,
@@ -52,10 +71,10 @@
     {
        case 0:  // test/rmi/SampleCorba/_get_i
        {
-         int $result = (int)0;
-         $result = this.i ();
+         int __result = (int)0;
+         __result = this.i ();
          out = $rh.createReply();
-         out.write_long ($result);
+         out.write_long (__result);
          break;
        }
 
@@ -67,6 +86,23 @@
          break;
        }
 
+       case 2:  // test/rmi/SampleCorba/_get_s
+       {
+         String __result = null;
+         __result = this.s ();
+         out = $rh.createReply();
+         out.write_string (__result);
+         break;
+       }
+
+       case 3:  // test/rmi/SampleCorba/_set_s
+       {
+         String newS = in.read_string ();
+         this.s (newS);
+         out = $rh.createReply();
+         break;
+       }
+
        default:
          throw new org.omg.CORBA.BAD_OPERATION (0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
     }
@@ -74,26 +110,5 @@
     return out;
   } // _invoke
 
-  // Type-specific CORBA::Object operations
-  private static String[] __ids = {
-    "IDL:test/rmi/SampleCorba:1.0"};
 
-  public String[] _all_interfaces (org.omg.PortableServer.POA poa, byte[] objectId)
-  {
-    return (String[])__ids.clone ();
-  }
-
-  public SampleCorba _this() 
-  {
-    return SampleCorbaHelper.narrow(
-    super._this_object());
-  }
-
-  public SampleCorba _this(org.omg.CORBA.ORB orb) 
-  {
-    return SampleCorbaHelper.narrow(
-    super._this_object(orb));
-  }
-
-
-} // class SampleCorbaPOA
+} // class _SampleCorbaPOA
diff --git a/yoko-core/src/test/java/test/rmi/SampleCorba_impl.java b/yoko-core/src/test/java/test/rmi/SampleCorba_impl.java
index 97541d9..9967ae6 100755
--- a/yoko-core/src/test/java/test/rmi/SampleCorba_impl.java
+++ b/yoko-core/src/test/java/test/rmi/SampleCorba_impl.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -18,12 +18,22 @@
 package test.rmi;
 
 public class SampleCorba_impl extends SampleCorbaPOA {
-	private int i;
-	public int i() {
-		return i;
-	}
+    private int i;
+    private String s;
 
-	public void i(int newI) {
-		this.i = newI;
-	}
+    public int i() {
+        return i;
+    }
+
+    public void i(int newI) {
+        this.i = newI;
+    }
+
+    public String s() {
+        return s;
+    }
+
+    public void s(String newS) {
+        s = newS;
+    }
 }
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-core/src/test/java/test/rmi/SampleEnum.java b/yoko-core/src/test/java/test/rmi/SampleEnum.java
new file mode 100644
index 0000000..34ef2b6
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/SampleEnum.java
@@ -0,0 +1,5 @@
+package test.rmi;
+
+public enum SampleEnum {
+    SAMPLE1, SAMPLE2, SAMPLE3
+}
diff --git a/yoko-core/src/test/java/test/rmi/SampleImpl.java b/yoko-core/src/test/java/test/rmi/SampleImpl.java
index c72ea08..0fce5f0 100755
--- a/yoko-core/src/test/java/test/rmi/SampleImpl.java
+++ b/yoko-core/src/test/java/test/rmi/SampleImpl.java
@@ -106,9 +106,11 @@
 	
 	public Serializable getSerializable() {return serializable; }
 	public void setSerializable(Serializable s) {
+	    System.out.println("received: " + s);
 		if(serializable instanceof SampleSerializable) {
 			SampleSerializable ser = (SampleSerializable) serializable;
-			ser.getRemoteObject();
+			Object o = ser.getRemoteObject();
+		     System.out.println("retrieved remote object: " + o);
 		}
 		this.serializable = s; 
 	}
diff --git a/yoko-core/src/test/java/test/rmi/_SampleCorbaStub.java b/yoko-core/src/test/java/test/rmi/_SampleCorbaStub.java
index 16a18fd..0d87652 100755
--- a/yoko-core/src/test/java/test/rmi/_SampleCorbaStub.java
+++ b/yoko-core/src/test/java/test/rmi/_SampleCorbaStub.java
@@ -15,58 +15,193 @@
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  */
-
 package test.rmi;
 
 
 /**
 * test/rmi/_SampleCorbaStub.java .
-* Generated by the IDL-to-Java compiler (portable), version "3.2"
-* from src/test/java/test/rmi/SampleCorbaObject.idl
-* 9. maj 2006 14:03:27 CEST
+* Generated by the IDL-to-Java compiler (portable), version "3.0"
+* from SampleCorbaObject.idl
+* Tuesday, 28 April 2015 17:10:49 o'clock BST
 */
 
-public class _SampleCorbaStub extends org.omg.CORBA.portable.ObjectImpl implements test.rmi.SampleCorba
+public class _SampleCorbaStub extends org.omg.CORBA_2_3.portable.ObjectImpl implements test.rmi.SampleCorba
 {
+  // Constructors
+  // NOTE:  If the default constructor is used, the
+  //        object is useless until _set_delegate (...)
+  //        is called.
+  public _SampleCorbaStub ()
+  {
+    super ();
+  }
+
+  public _SampleCorbaStub (org.omg.CORBA.portable.Delegate delegate)
+  {
+    super ();
+    _set_delegate (delegate);
+  }
 
   public int i ()
   {
-            org.omg.CORBA.portable.InputStream $in = null;
-            try {
-                org.omg.CORBA.portable.OutputStream $out = _request ("_get_i", true);
-                $in = _invoke ($out);
-                int $result = $in.read_long ();
-                return $result;
-            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
-                $in = $ex.getInputStream ();
-                String _id = $ex.getId ();
-                throw new org.omg.CORBA.MARSHAL (_id);
-            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
-                return i (        );
-            } finally {
-                _releaseReply ($in);
-            }
+    while(true) {
+      if ( !this._is_local() ) {
+        org.omg.CORBA.portable.InputStream _in = null;
+        try {
+          org.omg.CORBA.portable.OutputStream _out = _request ("_get_i",true);
+          _in = _invoke (_out);
+          int __result = _in.read_long ();
+          return __result;
+        } catch (org.omg.CORBA.portable.ApplicationException _ex) {
+          _in = _ex.getInputStream ();
+          String _id = _ex.getId ();
+          throw new org.omg.CORBA.UNKNOWN( "Unexpected User Exception: " + _id );
+        } catch (org.omg.CORBA.portable.RemarshalException _rm) {
+          continue;
+        } catch (org.omg.CORBA.portable.UnknownException _ue) {
+          Throwable _oe = _ue.originalEx;
+          if (_oe instanceof Error)
+              throw (Error)_oe;
+          else if (_oe instanceof RuntimeException)
+              throw (RuntimeException)_oe;
+          else
+              throw _ue;
+        } finally { _releaseReply (_in); }
+      }
+      else {
+        org.omg.CORBA.portable.ServantObject _so =
+          _servant_preinvoke( "_get_i",_opsClass );
+        if ( _so == null ) { 
+          continue;
+        }
+        try {
+          int __result = ((test.rmi.SampleCorbaOperations)_so.servant).i(  );
+          return __result;
+        } finally { _servant_postinvoke( _so ); }
+      }
+    }
   } // i
 
   public void i (int newI)
   {
-            org.omg.CORBA.portable.InputStream $in = null;
-            try {
-                org.omg.CORBA.portable.OutputStream $out = _request ("_set_i", true);
-                $out.write_long (newI);
-                $in = _invoke ($out);
-                return;
-            } catch (org.omg.CORBA.portable.ApplicationException $ex) {
-                $in = $ex.getInputStream ();
-                String _id = $ex.getId ();
-                throw new org.omg.CORBA.MARSHAL (_id);
-            } catch (org.omg.CORBA.portable.RemarshalException $rm) {
-                i (newI        );
-            } finally {
-                _releaseReply ($in);
-            }
+    while(true) {
+      if ( !this._is_local() ) {
+        org.omg.CORBA.portable.InputStream _in = null;
+        try {
+          org.omg.CORBA.portable.OutputStream _out = _request ("_set_i",true);
+          _out.write_long (newI);
+          _in = _invoke (_out);
+          return;
+        } catch (org.omg.CORBA.portable.ApplicationException _ex) {
+          _in = _ex.getInputStream ();
+          String _id = _ex.getId ();
+          throw new org.omg.CORBA.UNKNOWN( "Unexpected User Exception: " + _id );
+        } catch (org.omg.CORBA.portable.RemarshalException _rm) {
+          continue;
+        } catch (org.omg.CORBA.portable.UnknownException _ue) {
+          Throwable _oe = _ue.originalEx;
+          if (_oe instanceof Error)
+              throw (Error)_oe;
+          else if (_oe instanceof RuntimeException)
+              throw (RuntimeException)_oe;
+          else
+              throw _ue;
+        } finally { _releaseReply (_in); }
+      }
+      else {
+        org.omg.CORBA.portable.ServantObject _so =
+          _servant_preinvoke( "_set_i",_opsClass );
+        if ( _so == null ) { 
+          continue;
+        }
+        try {
+          ((test.rmi.SampleCorbaOperations)_so.servant).i( newI );
+          return;
+        } finally { _servant_postinvoke( _so ); }
+      }
+    }
   } // i
 
+  public String s ()
+  {
+    while(true) {
+      if ( !this._is_local() ) {
+        org.omg.CORBA.portable.InputStream _in = null;
+        try {
+          org.omg.CORBA.portable.OutputStream _out = _request ("_get_s",true);
+          _in = _invoke (_out);
+          String __result = _in.read_string ();
+          return __result;
+        } catch (org.omg.CORBA.portable.ApplicationException _ex) {
+          _in = _ex.getInputStream ();
+          String _id = _ex.getId ();
+          throw new org.omg.CORBA.UNKNOWN( "Unexpected User Exception: " + _id );
+        } catch (org.omg.CORBA.portable.RemarshalException _rm) {
+          continue;
+        } catch (org.omg.CORBA.portable.UnknownException _ue) {
+          Throwable _oe = _ue.originalEx;
+          if (_oe instanceof Error)
+              throw (Error)_oe;
+          else if (_oe instanceof RuntimeException)
+              throw (RuntimeException)_oe;
+          else
+              throw _ue;
+        } finally { _releaseReply (_in); }
+      }
+      else {
+        org.omg.CORBA.portable.ServantObject _so =
+          _servant_preinvoke( "_get_s",_opsClass );
+        if ( _so == null ) { 
+          continue;
+        }
+        try {
+          String __result = ((test.rmi.SampleCorbaOperations)_so.servant).s(  );
+          return __result;
+        } finally { _servant_postinvoke( _so ); }
+      }
+    }
+  } // s
+
+  public void s (String newS)
+  {
+    while(true) {
+      if ( !this._is_local() ) {
+        org.omg.CORBA.portable.InputStream _in = null;
+        try {
+          org.omg.CORBA.portable.OutputStream _out = _request ("_set_s",true);
+          _out.write_string (newS);
+          _in = _invoke (_out);
+          return;
+        } catch (org.omg.CORBA.portable.ApplicationException _ex) {
+          _in = _ex.getInputStream ();
+          String _id = _ex.getId ();
+          throw new org.omg.CORBA.UNKNOWN( "Unexpected User Exception: " + _id );
+        } catch (org.omg.CORBA.portable.RemarshalException _rm) {
+          continue;
+        } catch (org.omg.CORBA.portable.UnknownException _ue) {
+          Throwable _oe = _ue.originalEx;
+          if (_oe instanceof Error)
+              throw (Error)_oe;
+          else if (_oe instanceof RuntimeException)
+              throw (RuntimeException)_oe;
+          else
+              throw _ue;
+        } finally { _releaseReply (_in); }
+      }
+      else {
+        org.omg.CORBA.portable.ServantObject _so =
+          _servant_preinvoke( "_set_s",_opsClass );
+        if ( _so == null ) { 
+          continue;
+        }
+        try {
+          ((test.rmi.SampleCorbaOperations)_so.servant).s( newS );
+          return;
+        } finally { _servant_postinvoke( _so ); }
+      }
+    }
+  } // s
+
   // Type-specific CORBA::Object operations
   private static String[] __ids = {
     "IDL:test/rmi/SampleCorba:1.0"};
@@ -76,21 +211,20 @@
     return (String[])__ids.clone ();
   }
 
+  final public static java.lang.Class _opsClass =
+    test.rmi.SampleCorbaOperations.class;
+
   private void readObject (java.io.ObjectInputStream s) throws java.io.IOException
   {
-     String str = s.readUTF ();
-     String[] args = null;
-     java.util.Properties props = null;
-     org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init (args, props).string_to_object (str);
-     org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
-     _set_delegate (delegate);
+    String str = s.readUTF ();
+    org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init ((String[])null, null).string_to_object (str);
+    org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate ();
+    _set_delegate (delegate);
   }
 
   private void writeObject (java.io.ObjectOutputStream s) throws java.io.IOException
   {
-     String[] args = null;
-     java.util.Properties props = null;
-     String str = org.omg.CORBA.ORB.init (args, props).object_to_string (this);
-     s.writeUTF (str);
+    String str = org.omg.CORBA.ORB.init ((String[])null, null).object_to_string (this);
+    s.writeUTF (str);
   }
 } // class _SampleCorbaStub
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/MyAppException.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyAppException.java
new file mode 100644
index 0000000..662705b
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyAppException.java
@@ -0,0 +1,3 @@
+package test.rmi.exceptionhandling;
+
+public class MyAppException extends Exception {}
\ No newline at end of file
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/MyClientRequestInterceptor.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyClientRequestInterceptor.java
new file mode 100644
index 0000000..1f05ee5
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyClientRequestInterceptor.java
@@ -0,0 +1,64 @@
+package test.rmi.exceptionhandling;
+
+import org.omg.CORBA.LocalObject;
+import org.omg.PortableInterceptor.ClientRequestInfo;
+import org.omg.PortableInterceptor.ClientRequestInterceptor;
+import org.omg.PortableInterceptor.ForwardRequest;
+import org.omg.PortableInterceptor.ORBInitInfo;
+import org.omg.PortableInterceptor.ORBInitializer;
+import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
+
+public class MyClientRequestInterceptor extends LocalObject implements ClientRequestInterceptor, ORBInitializer {
+
+    @Override
+    public void receive_exception(ClientRequestInfo arg0) throws ForwardRequest {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("receive_exception(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void receive_other(ClientRequestInfo arg0) throws ForwardRequest {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("receive_other(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void receive_reply(ClientRequestInfo arg0) {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("receive_reply(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void send_poll(ClientRequestInfo arg0) {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("send_poll(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void send_request(ClientRequestInfo arg0) throws ForwardRequest {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("send_request(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+    @Override
+    public String name() {
+        return this.getClass().getName();
+    }
+
+    @Override
+    public void post_init(ORBInitInfo arg0) {
+        try {
+            arg0.add_client_request_interceptor(this);
+        } catch (DuplicateName e) {
+            throw new Error(e);
+        }
+    }
+
+    @Override
+    public void pre_init(ORBInitInfo arg0) {
+    }
+}
\ No newline at end of file
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/MyRuntimeException.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyRuntimeException.java
new file mode 100644
index 0000000..cf1de8c
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyRuntimeException.java
@@ -0,0 +1,3 @@
+package test.rmi.exceptionhandling;
+
+public class MyRuntimeException extends RuntimeException {}
\ No newline at end of file
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/MyServerRequestInterceptor.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyServerRequestInterceptor.java
new file mode 100644
index 0000000..56ceaaf
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/MyServerRequestInterceptor.java
@@ -0,0 +1,64 @@
+package test.rmi.exceptionhandling;
+
+import org.omg.CORBA.LocalObject;
+import org.omg.PortableInterceptor.ForwardRequest;
+import org.omg.PortableInterceptor.ORBInitInfo;
+import org.omg.PortableInterceptor.ORBInitializer;
+import org.omg.PortableInterceptor.ServerRequestInfo;
+import org.omg.PortableInterceptor.ServerRequestInterceptor;
+import org.omg.PortableInterceptor.ORBInitInfoPackage.DuplicateName;
+
+public class MyServerRequestInterceptor extends LocalObject implements ServerRequestInterceptor, ORBInitializer {
+
+    @Override
+    public void receive_request(ServerRequestInfo arg0) throws ForwardRequest {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("receive_request(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void receive_request_service_contexts(ServerRequestInfo arg0) throws ForwardRequest {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("receive_request_service_contexts(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void send_exception(ServerRequestInfo arg0) throws ForwardRequest {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("send_exception(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void send_other(ServerRequestInfo arg0) throws ForwardRequest {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("send_other(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void send_reply(ServerRequestInfo arg0) {
+        System.out.printf("%08x: ", Thread.currentThread().getId());
+        System.out.println("send_reply(" + arg0.operation() + ")");
+    }
+
+    @Override
+    public void destroy() {
+    }
+
+    @Override
+    public String name() {
+        return this.getClass().getName();
+    }
+
+    @Override
+    public void post_init(ORBInitInfo arg0) {
+        try {
+            arg0.add_server_request_interceptor(this);
+        } catch (DuplicateName e) {
+            throw new Error(e);
+        }
+    }
+
+    @Override
+    public void pre_init(ORBInitInfo arg0) {
+    }
+}
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/Thrower.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/Thrower.java
new file mode 100644
index 0000000..b8b9a02
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/Thrower.java
@@ -0,0 +1,9 @@
+package test.rmi.exceptionhandling;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+
+public interface Thrower extends Remote {
+    void throwAppException() throws RemoteException, MyAppException;
+    void throwRuntimeException() throws RemoteException;
+}
\ No newline at end of file
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/ThrowerImpl.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/ThrowerImpl.java
new file mode 100644
index 0000000..4d2ee9e
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/ThrowerImpl.java
@@ -0,0 +1,25 @@
+package test.rmi.exceptionhandling;
+
+import java.rmi.RemoteException;
+
+import org.omg.CORBA.ORB;
+
+public class ThrowerImpl implements Thrower {
+    public static MyRuntimeException myRuntimeException;
+    public static MyAppException myAppException;
+    final ORB orb;
+
+    public ThrowerImpl(ORB orb) {
+        this.orb = orb;
+    }
+
+    @Override
+    public void throwAppException() throws RemoteException, MyAppException {
+        throw myAppException;
+    }
+
+    @Override
+    public void throwRuntimeException() throws RemoteException {
+        throw myRuntimeException;
+    }
+}
\ No newline at end of file
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/_ThrowerImpl_Tie.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/_ThrowerImpl_Tie.java
new file mode 100644
index 0000000..434e16a
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/_ThrowerImpl_Tie.java
@@ -0,0 +1,113 @@
+// POA Tie class generated by rmic, do not edit.
+// Contents subject to change without notice.
+
+package test.rmi.exceptionhandling;
+
+import java.lang.ClassCastException;
+import java.lang.String;
+import java.lang.Throwable;
+import java.rmi.Remote;
+import javax.rmi.CORBA.Tie;
+import org.omg.CORBA.BAD_OPERATION;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Object;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.ResponseHandler;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAPackage.ObjectNotActive;
+import org.omg.PortableServer.POAPackage.ServantNotActive;
+import org.omg.PortableServer.POAPackage.WrongPolicy;
+
+public class _ThrowerImpl_Tie extends org.omg.PortableServer.Servant implements Tie {
+    
+    private ThrowerImpl target = null;
+    
+    private static final String[] _type_ids = {
+        "RMI:test.rmi.exceptionhandling.Thrower:0000000000000000"
+    };
+    
+    public void setTarget(Remote target) {
+        this.target = (ThrowerImpl) target;
+    }
+    
+    public Remote getTarget() {
+        return target;
+    }
+    
+    public Object thisObject() {
+        return _this_object();
+    }
+    
+    public void deactivate() {
+        try {
+            _poa().deactivate_object(_poa().servant_to_id(this));
+        }
+        catch(WrongPolicy e) { }
+        catch(ObjectNotActive e) { }
+        catch(ServantNotActive e) { }
+    }
+    
+    public ORB orb() {
+        return _orb();
+    }
+    
+    public void orb(ORB orb) {
+        try {
+            ((org.omg.CORBA_2_3.ORB)orb).set_delegate(this);
+        }
+        catch(ClassCastException e) {
+            throw new BAD_PARAM("POA Servant needs an org.omg.CORBA_2_3.ORB");
+        }
+    }
+    
+    public String[] _all_interfaces(POA poa, byte[] objectId) { 
+        return (String [] )  _type_ids.clone();
+    }
+    
+    public OutputStream _invoke(String method, InputStream _in, ResponseHandler reply) throws SystemException {
+        try {
+            org.omg.CORBA_2_3.portable.InputStream in = 
+                (org.omg.CORBA_2_3.portable.InputStream) _in;
+            switch (method.length()) {
+                case 17: 
+                    if (method.equals("throwAppException")) {
+                        return throwAppException(in, reply);
+                    }
+                case 21: 
+                    if (method.equals("throwRuntimeException")) {
+                        return throwRuntimeException(in, reply);
+                    }
+            }
+            throw new BAD_OPERATION();
+        } catch (SystemException ex) {
+            throw ex;
+        } catch (Throwable ex) {
+            throw new UnknownException(ex);
+        }
+    }
+    
+    private OutputStream throwAppException(org.omg.CORBA_2_3.portable.InputStream in , ResponseHandler reply) throws Throwable {
+        try {
+            target.throwAppException();
+        } catch (MyAppException ex) {
+            String id = "IDL:test/rmi/exceptionhandling/MyAppEx:1.0";
+            org.omg.CORBA_2_3.portable.OutputStream out = 
+                (org.omg.CORBA_2_3.portable.OutputStream) reply.createExceptionReply();
+            out.write_string(id);
+            out.write_value(ex,MyAppException.class);
+            return out;
+        }
+        OutputStream out = reply.createReply();
+        return out;
+    }
+    
+    private OutputStream throwRuntimeException(org.omg.CORBA_2_3.portable.InputStream in , ResponseHandler reply) throws Throwable {
+        target.throwRuntimeException();
+        OutputStream out = reply.createReply();
+        return out;
+    }
+}
diff --git a/yoko-core/src/test/java/test/rmi/exceptionhandling/_Thrower_Stub.java b/yoko-core/src/test/java/test/rmi/exceptionhandling/_Thrower_Stub.java
new file mode 100644
index 0000000..884897e
--- /dev/null
+++ b/yoko-core/src/test/java/test/rmi/exceptionhandling/_Thrower_Stub.java
@@ -0,0 +1,112 @@
+// Stub class generated by rmic, do not edit.
+// Contents subject to change without notice.
+
+package test.rmi.exceptionhandling;
+
+import java.lang.String;
+import java.lang.Throwable;
+import java.rmi.RemoteException;
+import java.rmi.UnexpectedException;
+import javax.rmi.CORBA.Stub;
+import javax.rmi.CORBA.Util;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.ApplicationException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.RemarshalException;
+import org.omg.CORBA.portable.ServantObject;
+
+public class _Thrower_Stub extends Stub implements Thrower {
+    
+    private static final String[] _type_ids = {
+        "RMI:test.rmi.exceptionhandling.Thrower:0000000000000000"
+    };
+    
+    public String[] _ids() { 
+        return (String [] )  _type_ids.clone();
+    }
+    
+    public void throwAppException() throws RemoteException, MyAppException {
+        while(true) {
+            if (!Util.isLocal(this)) {
+                org.omg.CORBA_2_3.portable.InputStream in = null;
+                try {
+                    try {
+                        OutputStream out = _request("throwAppException", true);
+                        _invoke(out);
+                        return;
+                    } catch (ApplicationException ex) {
+                        in = (org.omg.CORBA_2_3.portable.InputStream) ex.getInputStream();
+                        String id = in.read_string();
+                        if (id.equals("IDL:test/rmi/exceptionhandling/MyAppEx:1.0")) {
+                            throw (MyAppException) in.read_value(MyAppException.class);
+                        }
+                        throw new UnexpectedException(id);
+                    } catch (RemarshalException ex) {
+                        continue;
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                } finally {
+                    _releaseReply(in);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("throwAppException",test.rmi.exceptionhandling.Thrower.class);
+                if (so == null) {
+                    continue;
+                }
+                try {
+                    ((test.rmi.exceptionhandling.Thrower)so.servant).throwAppException();
+                    return;
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    if (exCopy instanceof MyAppException) {
+                        throw (MyAppException)exCopy;
+                    }
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
+    
+    public void throwRuntimeException() throws RemoteException {
+        while(true) {
+            if (!Util.isLocal(this)) {
+                InputStream in = null;
+                try {
+                    try {
+                        OutputStream out = _request("throwRuntimeException", true);
+                        _invoke(out);
+                        return;
+                    } catch (ApplicationException ex) {
+                        in = ex.getInputStream();
+                        String id = in.read_string();
+                        throw new UnexpectedException(id);
+                    } catch (RemarshalException ex) {
+                        continue;
+                    }
+                } catch (SystemException ex) {
+                    throw Util.mapSystemException(ex);
+                } finally {
+                    _releaseReply(in);
+                }
+            } else {
+                ServantObject so = _servant_preinvoke("throwRuntimeException",test.rmi.exceptionhandling.Thrower.class);
+                if (so == null) {
+                    continue;
+                }
+                try {
+                    ((test.rmi.exceptionhandling.Thrower)so.servant).throwRuntimeException();
+                    return;
+                } catch (Throwable ex) {
+                    Throwable exCopy = (Throwable)Util.copyObject(ex,_orb());
+                    throw Util.wrapException(exCopy);
+                } finally {
+                    _servant_postinvoke(so);
+                }
+            }
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/tnaming/Client.java b/yoko-core/src/test/java/test/tnaming/Client.java
index 5ddd6c0..c7a0500 100644
--- a/yoko-core/src/test/java/test/tnaming/Client.java
+++ b/yoko-core/src/test/java/test/tnaming/Client.java
@@ -1,174 +1,236 @@
 /**
  *
  * 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
+ *  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
+ *  Unless required by applicable law or agreed to in writing, softwares
  *  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.
  */
 
-
 /**
  * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
  */
 
 package test.tnaming;
 
-import org.omg.CORBA.*;
-import org.omg.PortableServer.*;
-import org.omg.CosNaming.*;
-import org.omg.CosNaming.NamingContextPackage.*;
-import org.omg.CosNaming.NamingContextExtPackage.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static test.tnaming.Client.NameServiceType.READ_ONLY;
 
 import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
+import java.rmi.Remote;
 import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
 
-public class Client extends test.common.TestBase {
-    public static int run(ORB orb, String[] args)
-            throws org.omg.CORBA.UserException {
-        //
-        // Resolve Root POA
-        //
-        POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+import org.junit.Assert;
+import org.omg.CORBA.NO_PERMISSION;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.UserException;
+import org.omg.CosNaming.Binding;
+import org.omg.CosNaming.BindingHolder;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextExtHelper;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAHelper;
 
-        //
-        // Get a reference to the POA manager and activate it
-        //
-        POAManager manager = poa.the_POAManager();
-        manager.activate();
+final class Client extends test.common.TestBase implements AutoCloseable {
+    enum NameServiceType {
+        READ_ONLY, INTEGRAL, STANDALONE
+    };
+    final NameServiceType accessibility;
+    final ORB orb;
+    final POA rootPoa;
+    final NamingContextExt rootNamingContext;
+    final String name1, name2, name3;
+    final Test test1, test2, test3;
 
-        String refFile = "Test.ref";
-        String ref1;
-        String name1;
-        String ref2;
-        String name2;
-        String ref3;
-        String name3;
-        try {
-            BufferedReader file = new BufferedReader(new FileReader(refFile));
-            ref1 = file.readLine();
-            name1 = file.readLine();
-            ref2 = file.readLine();
-            name2 = file.readLine();
-            ref3 = file.readLine();
-            name3 = file.readLine();
-            file.close();
-        } catch (java.io.IOException ex) {
-            System.err.println("Can't read from '" + ex.getMessage() + "'");
-            return 1;
-        }
+    Client(NameServiceType accessibility, final String refFile, Properties props, String... args) throws Exception {
+        assertNotNull(accessibility);
+        this.accessibility = accessibility;
+        this.orb = ORB.init(args, props);
+        this.rootPoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+        this.rootPoa.the_POAManager().activate();
+        this.rootNamingContext = NamingContextExtHelper.narrow(orb.resolve_initial_references("NameService"));
         //
         // Get "test" objects
         //
-        org.omg.CORBA.Object obj1 = orb.string_to_object(ref1);
-        org.omg.CORBA.Object obj2 = orb.string_to_object(ref2);
-        org.omg.CORBA.Object obj3 = orb.string_to_object(ref3);
-        if (obj1 == null || obj2 == null || obj3 == null) {
-            System.err.println("cannot read IOR from Test.ref");
-            return 1;
+        System.out.println("Started ORB, getting test object IORs from file");
+        try (BufferedReader file = openFileReader(refFile)) {
+            String[] refStrings = new String[2];
+            readRef(file, refStrings);
+            test1 = getTestObjectFromReference(refStrings[0]);
+            name1 = refStrings[1];
+
+            readRef(file, refStrings);
+            test2 = getTestObjectFromReference(refStrings[0]);
+            name2 = refStrings[1];
+
+            readRef(file, refStrings);
+            test3 = getTestObjectFromReference(refStrings[0]);
+            name3 = refStrings[1];
+        } catch (java.io.IOException ex) {
+            System.err.println("Can't read from '" + ex.getMessage() + "'");
+            throw ex;
         }
-
-        Test test1 = TestHelper.narrow(obj1);
-        TEST(test1 != null);
-
-        Test test2 = TestHelper.narrow(obj2);
-        TEST(test2 != null);
-
-        Test test3 = TestHelper.narrow(obj3);
-        TEST(test3 != null);
-
-        org.omg.CORBA.Object obj = orb.resolve_initial_references("NameService");
-        NamingContextExt initialContext = NamingContextExtHelper.narrow(obj);
-
-        Test test1a = TestHelper.narrow(initialContext.resolve_str(name1));
-        TEST(test1a != null);
-        TEST(test1a.get_id().equals(test1.get_id()));
-
-        Test test2a = TestHelper.narrow(initialContext.resolve_str(name2));
-        TEST(test2a != null);
-        TEST(test2a.get_id().equals(test2.get_id()));
-
-        Test test3a = TestHelper.narrow(initialContext.resolve_str(name3));
-        TEST(test3a != null);
-        TEST(test3a.get_id().equals(test3.get_id()));
-
-        NamingContext nc = initialContext.bind_new_context(new NameComponent[] { new NameComponent("iterator", "") } );
-
-        for (int i = 0; i < 10; i++) {
-            String name = "Test" + i;
-            org.omg.CORBA.Object test = new Test_impl(poa, name)._this_object(orb);
-            nc.bind(new NameComponent[] { new NameComponent(name, "") }, test);
-        }
-
-        BindingListHolder blh = new BindingListHolder();
-        BindingIteratorHolder bih = new BindingIteratorHolder();
-        BindingHolder bh = new BindingHolder();
-
-        nc.list(10, blh, bih);
-
-        System.out.println("List returned count = " + blh.value.length);
-
-        TEST(blh.value.length == 10);
-        TEST(!bih.value.next_one(bh));
-        TEST(bh.value.binding_name.length == 0);
-
-        nc.list(9, blh, bih);
-
-        TEST(blh.value.length == 9);
-        TEST(bih.value.next_one(bh));
-        TEST(bh.value.binding_name.length == 1);
-
-        nc.list(11, blh, bih);
-
-        TEST(blh.value.length == 10);
-        TEST(!bih.value.next_one(bh));
-        TEST(bh.value.binding_name.length == 0);
-
-        // now shutdown the server orb
-        test1.shutdown();
-
-        return 0;
     }
 
-    public static void main(String args[]) {
-        java.util.Properties props = new Properties();
-        props.putAll(System.getProperties());
-        props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
-        props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
+    private Test getTestObjectFromReference(String ref) {
+        assertNotNull("Reference should not have been null", ref);
+        org.omg.CORBA.Object obj = orb.string_to_object(ref);
+        assertNotNull("Orb should have created a non-null stub", obj);
+        Test result = TestHelper.narrow(obj);
+        assertNotNull("Should have been able to narrow stub to a Test", result);
+        return result;
+    }
 
-        args = new String[] { "-ORBInitRef", "NameService=" + Server.NS_LOC };
-
-        int status = 0;
-        ORB orb = null;
-
-        try {
-            orb = ORB.init(args, props);
-            status = run(orb, args);
-        } catch (Exception ex) {
-            ex.printStackTrace();
-            status = 1;
+    void run() throws Exception {
+        System.out.println("Running naming client tests");
+        switch (accessibility) {
+            case READ_ONLY :
+                testReadOnly();
+                testBoundReferences();
+                testIterators();
+                testObjectFactories();
+                break;
+            case INTEGRAL:
+                testBoundReferences();
+                testIterators();
+                testObjectFactories();
+                break;
+            case STANDALONE:
+            	testBoundReferences();
+                testIterators();
+                break;
         }
+    }
 
-        if (orb != null) {
+    private void testBoundReferences() throws UserException {
+        System.out.println("Testing bound reference 1");
+        Util.assertTestIsBound(test1, rootNamingContext, name1);
+        System.out.println("Testing bound reference 2");
+        Util.assertTestIsBound(test2, rootNamingContext, name2);
+        System.out.println("Testing bound reference 3");
+        Util.assertTestIsBound(test3, rootNamingContext, name3);
+        System.out.println("Testing bound reference 1 via corbaname");
+        Util.assertCorbanameIsBound(test1, orb, "corbaname:rir:/NameService#"+name1);
+        System.out.println("Testing bound references complete.");
+    }
+
+    private void testIterators() throws Exception {
+        System.out.println("Testing iterators: narrowing context");
+        NamingContextExt nc = NamingContextExtHelper.narrow(rootNamingContext.resolve(Util.ITERATOR_TEST_CONTEXT_PATH));
+        // check the behaviour of the binding iterators
+        for (int listSize = 0; listSize <= Util.EXPECTED_NAMES.size() + 1; listSize++) {
+            System.out.println("Testing iterators: list size " + listSize);
+            final BindingListHolder blh = new BindingListHolder();
+            final BindingIteratorHolder bih = new BindingIteratorHolder();
+            final BindingHolder bh = new BindingHolder();
+            final Set<String> actualNames = new TreeSet<>();
+
+            nc.list(listSize, blh, bih); // <-- this is what we are testing
+
+            System.out.println("List returned count = " + blh.value.length);
+
+            final int expectedListSize = Math.min(listSize, Util.EXPECTED_NAMES.size());
+            assertEquals("Should have as many elements in the list as requested or available", expectedListSize,
+                    blh.value.length);
+            for (Binding b : blh.value) {
+                String name = b.binding_name[0].id;
+                assertTrue("Name '" + name + "' should be an expected one", Util.EXPECTED_NAMES.contains(name));
+                assertFalse("Name '" + name + "' should not be a dupe", actualNames.contains(name));
+                actualNames.add(name);
+            }
+            for (int i = expectedListSize; i < Util.EXPECTED_NAMES.size(); i++) {
+                assertTrue(bih.value.next_one(bh));
+                String name = bh.value.binding_name[0].id;
+                assertTrue("Name '" + name + "' should be an expected one", Util.EXPECTED_NAMES.contains(name));
+                assertFalse("Name '" + name + "' should not be a dupe", actualNames.contains(name));
+                actualNames.add(name);
+            }
+            assertFalse(bih.value.next_one(bh));
+            assertEquals(0, bh.value.binding_name.length);
+            assertEquals(Util.EXPECTED_NAMES, actualNames);
+        }
+        System.out.println("Testing iterators complete.");
+    }
+
+    private enum WriteMethod {
+        bind, bind_context, bind_new_context, destroy, new_context, rebind_context, rebind, unbind
+    };
+
+    private void testReadOnly() throws Exception {
+        final NameComponent[] foo = Util.makeName("foo");
+        for (WriteMethod method : WriteMethod.values()) {
             try {
-                orb.destroy();
-            } catch (Exception ex) {
-                ex.printStackTrace();
-                status = 1;
+                switch (method) {
+                    case bind :
+                        rootNamingContext.bind(foo, rootNamingContext);
+                        break;
+                    case bind_context :
+                        rootNamingContext.bind_context(foo, rootNamingContext);
+                        break;
+                    case bind_new_context :
+                        rootNamingContext.bind_new_context(foo);
+                        break;
+                    case destroy :
+                        rootNamingContext.destroy();
+                        break;
+                    case new_context :
+                        rootNamingContext.new_context();
+                        break;
+                    case rebind :
+                        rootNamingContext.rebind(foo, rootNamingContext);
+                        break;
+                    case rebind_context :
+                        rootNamingContext.rebind_context(foo, rootNamingContext);
+                        break;
+                    case unbind :
+                        rootNamingContext.unbind(foo);
+                        break;
+                }
+                Assert.fail(method + " should have thrown a NO_PERMISSION exception");
+            } catch (NO_PERMISSION expected) {
+                System.out.println(method + "() threw a NO_PERMISSION as expected.");
             }
         }
+    }
 
-        System.exit(status);
+    public void testObjectFactories() throws CannotProceed, InvalidName {
+        System.out.println("Testing object factories: resolvable");
+        Util.assertFactoryIsBound(rootNamingContext, Server.RESOLVABLE_TEST);
+        System.out.println("Testing object factories: resolver");
+        Util.assertFactoryIsBound(rootNamingContext, Server.RESOLVER_TEST);
+        System.out.println("Testing object factories complete.");
+    }
+
+    @Override
+    public void close() throws Exception {
+        try {
+            if (accessibility != READ_ONLY)
+                Util.unbindEverything(rootNamingContext);
+        } finally {
+            try {
+                test1.shutdown();
+            } finally {
+                orb.destroy();
+            }
+        }
     }
 }
diff --git a/yoko-core/src/test/java/test/tnaming/ClientForReadOnlyNameService.java b/yoko-core/src/test/java/test/tnaming/ClientForReadOnlyNameService.java
new file mode 100644
index 0000000..4b4aefa
--- /dev/null
+++ b/yoko-core/src/test/java/test/tnaming/ClientForReadOnlyNameService.java
@@ -0,0 +1,20 @@
+package test.tnaming;
+
+import static test.tnaming.Client.NameServiceType.READ_ONLY;
+
+import java.util.Properties;
+
+public class ClientForReadOnlyNameService {
+    public static void main(String args[]) throws Exception {
+        final String refFile = args[0];
+        java.util.Properties props = new Properties();
+        props.putAll(System.getProperties());
+        props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
+        props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
+
+        try (Client client = new Client(READ_ONLY, refFile, props, "-ORBInitRef", "NameService=" + Util.NS_LOC )) {
+            client.run();
+        }
+    }
+
+}
diff --git a/yoko-core/src/test/java/test/tnaming/ClientForReadWriteNameService.java b/yoko-core/src/test/java/test/tnaming/ClientForReadWriteNameService.java
new file mode 100644
index 0000000..d5f2e68
--- /dev/null
+++ b/yoko-core/src/test/java/test/tnaming/ClientForReadWriteNameService.java
@@ -0,0 +1,20 @@
+package test.tnaming;
+
+import java.util.Properties;
+
+import static test.tnaming.Client.NameServiceType.*;
+
+public class ClientForReadWriteNameService {
+    public static void main(String args[]) throws Exception {
+        final String refFile = args[0];
+        java.util.Properties props = new Properties();
+        props.putAll(System.getProperties());
+        props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
+        props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
+
+        try (Client client = new Client(STANDALONE, refFile, props, "-ORBInitRef", "NameService=" + Util.NS_LOC)) {
+            Util.createBindingsOverWhichToIterate(client.orb, client.rootNamingContext);
+            client.run();
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/tnaming/Server.java b/yoko-core/src/test/java/test/tnaming/Server.java
index 125dfd7..232f30e 100644
--- a/yoko-core/src/test/java/test/tnaming/Server.java
+++ b/yoko-core/src/test/java/test/tnaming/Server.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -16,222 +16,176 @@
  *  limitations under the License.
  */
 
-
 /**
  * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
  */
 
 package test.tnaming;
 
-import org.omg.CORBA.*;
-import org.omg.PortableServer.*;
-import org.apache.yoko.orb.CosNaming.tnaming.TransientNameService;
-import org.apache.yoko.orb.CosNaming.tnaming.TransientServiceException;
-import org.omg.CosNaming.*;
-import org.omg.CosNaming.NamingContextPackage.*;
-import org.omg.CosNaming.NamingContextExtPackage.*;
-
+import java.io.BufferedWriter;
+import java.io.FileWriter;
 import java.io.PrintWriter;
-import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.Properties;
 
-public class Server extends test.common.TestBase {
-    public static final int NS_PORT = 40001;
-    public static final String NS_LOC = "corbaloc::localhost:40001/TNameService";
+import org.apache.yoko.orb.spi.naming.Resolvable;
+import org.apache.yoko.orb.spi.naming.Resolver;
+import org.omg.CORBA.ORB;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextExtHelper;
+import org.omg.CosNaming.NamingContextPackage.AlreadyBound;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAHelper;
 
-    public static int run(ORB orb, String[] args)
-            throws org.omg.CORBA.UserException {
-        //
-        // Resolve Root POA
-        //
-        POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+final class Server extends test.common.TestBase implements AutoCloseable {
+    private static final NameComponent LEVEL1 = new NameComponent("level1", "test");
+    private static final NameComponent LEVEL2 = new NameComponent("level2", "");
 
-        //
-        // Get a reference to the POA manager and activate it
-        //
-        POAManager manager = poa.the_POAManager();
-        manager.activate();
+    private static final NameComponent TEST1 = new NameComponent("Test1", "");
+    private static final NameComponent TEST2 = new NameComponent("Test2", "");
+    private static final NameComponent TEST3 = new NameComponent("Test3", "");
 
-        System.out.println("Attempting to resolve NameService reference");
-        org.omg.CORBA.Object obj = orb.resolve_initial_references("NameService");
-        System.out.println("Resolved NameService reference=" + obj);
-        NamingContextExt initialContext = NamingContextExtHelper.narrow(obj);
+    public static final NameComponent RESOLVABLE_TEST = new NameComponent("ResolvableTest", "");
+    public static final NameComponent RESOLVER_TEST = new NameComponent("ResolverTest", "");
 
-        NameComponent level1 = new NameComponent("level1", "test");
-        NameComponent level2 = new NameComponent("level2", "");
+    final String refFile;
+    final ORB orb;
+    final POA rootPoa;
+    final NamingContextExt rootNamingContext;
+    final Test test1, test2, test3;
+    final Resolvable resolvable;
+    final Resolver resolver;
 
-        NameComponent ncTest1 = new NameComponent("Test1", "");
-        NameComponent ncTest2 = new NameComponent("Test2", "");
-        NameComponent ncTest3 = new NameComponent("Test3", "");
-
-
-        NamingContext nc1 = initialContext.new_context();
-
-        System.out.println("Binding context level1");
-        initialContext.bind_context(new NameComponent[] { level1 }, nc1);
-
-        NamingContext nc2 = initialContext.bind_new_context(new NameComponent[] { level1, level2} );
-
+    public Server(String refFile, Properties props, String... args) throws Exception {
+        this.refFile = refFile;
         try {
-            org.omg.CORBA.Object o = initialContext.resolve(new NameComponent[] { ncTest1 });
-            TEST(false);
-        } catch (NotFound e) {
-            // expected exception
+            System.out.println("About to init ORB");
+            this.orb = ORB.init(args, props);
+            System.out.println("create ORB");
+            this.rootPoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+            System.out.println("got root poa");
+            this.rootPoa.the_POAManager().activate();
+            System.out.println("activated root poa");
+            this.rootNamingContext = NamingContextExtHelper.narrow(orb.resolve_initial_references("NameService"));
+            System.out.println("got root context");
+
+            //
+            // Create implementation objects
+            //
+            test1 = TestHelper.narrow(new Test_impl(rootPoa, "Test1")._this_object(orb));
+            test2 = TestHelper.narrow(new Test_impl(rootPoa, "Test2")._this_object(orb));
+            test3 = TestHelper.narrow(new Test_impl(rootPoa, "Test3")._this_object(orb));
+
+            // two ways to provide a Resolvable - both should be treated identically
+            resolvable = new TestFactory_impl (rootPoa, orb, RESOLVABLE_TEST.id);
+            resolver = new Resolver(){
+                @Override
+                public org.omg.CORBA.Object resolve() {
+                    return resolvable.resolve();
+                }
+            };
+
+            System.out.println("created references");
+        } catch (Throwable t) {
+            System.err.println("Caught throwable: " + t);
+            t.printStackTrace();
+            throw t;
         }
+    }
 
-        //
-        // Create implementation objects
-        //
-        org.omg.CORBA.Object test1 = new Test_impl(poa, "Test1")._this_object(orb);
-        org.omg.CORBA.Object test2 = new Test_impl(poa, "Test2")._this_object(orb);
-        org.omg.CORBA.Object test3 = new Test_impl(poa, "Test3")._this_object(orb);
-        org.omg.CORBA.Object test3a = new Test_impl(poa, "Test3a")._this_object(orb);
+    void run() throws Exception {
+        System.out.println("server starting to run");
 
-        try {
-            org.omg.CORBA.Object o = initialContext.resolve(new NameComponent[] { ncTest1 });
-            TEST(false);
-        } catch (NotFound e) {
-            // expected exception
-        }
+        // use a temporary file to avoid the client picking up an empty file when debugging the server
+        Path tmp = Files.createTempFile(refFile, "");
+        try (PrintWriter out = new PrintWriter(new FileWriter(tmp.toFile()))) {
+            System.out.println("server opened file for writing");
+            try {
+                NamingContext nc1 = rootNamingContext.new_context();
+                System.out.println("server created new naming context");
 
-        initialContext.bind(new NameComponent[] { ncTest1 }, test1);
+                System.out.println("Binding context level1");
+                rootNamingContext.bind_context(new NameComponent[]{LEVEL1}, nc1);
+                System.out.println("server binding context");
 
-        try {
-            org.omg.CORBA.Object o = initialContext.resolve(new NameComponent[] { ncTest1 });
-            Test test = TestHelper.narrow(o);
-            TEST(test.get_id().equals("Test1"));
-        } catch (NotFound e) {
-            TEST(false);
-        }
+                NamingContext nc2 = rootNamingContext.bind_new_context(new NameComponent[]{LEVEL1, LEVEL2});
 
-        nc1.bind(new NameComponent[] { ncTest2 }, test2);
+                Util.assertNameNotBound(rootNamingContext, TEST1);
 
-        try {
-            org.omg.CORBA.Object o = initialContext.resolve(new NameComponent[] { level1, ncTest2 });
-            Test test = TestHelper.narrow(o);
-            TEST(test.get_id().equals("Test2"));
-        } catch (NotFound e) {
-            TEST(false);
-        }
+                Util.assertNameNotBound(rootNamingContext, TEST1);
 
-        initialContext.bind(new NameComponent[] { level1, level2, ncTest3 }, test3);
+                rootNamingContext.bind(new NameComponent[]{TEST1}, test1);
 
-        try {
-            org.omg.CORBA.Object o = initialContext.resolve(new NameComponent[] { level1, level2, ncTest3 });
-            Test test = TestHelper.narrow(o);
-            TEST(test.get_id().equals("Test3"));
-        } catch (NotFound e) {
-            TEST(false);
-        }
+                Util.assertTestIsBound("Test1", rootNamingContext, TEST1);
 
-        nc2.rebind(new NameComponent[] { ncTest3 }, test3a);
+                nc1.bind(new NameComponent[]{TEST2}, test2);
+                Util.assertTestIsBound("Test2", rootNamingContext, LEVEL1, TEST2);
 
-        try {
-            org.omg.CORBA.Object o = initialContext.resolve(new NameComponent[] { level1, level2, ncTest3 });
-            Test test = TestHelper.narrow(o);
-            TEST(test.get_id().equals("Test3a"));
-        } catch (NotFound e) {
-            TEST(false);
-        }
+                rootNamingContext.bind(new NameComponent[]{LEVEL1, LEVEL2, TEST3}, test3);
+                Util.assertTestIsBound("Test3", rootNamingContext, LEVEL1, LEVEL2, TEST3);
 
-        initialContext.unbind(new NameComponent[] { level1, level2, ncTest3 });
+                Test test3a = TestHelper.narrow(new Test_impl(rootPoa, "Test3a")._this_object(orb));
+                nc2.rebind(new NameComponent[]{TEST3}, test3a);
+                Util.assertTestIsBound("Test3a", rootNamingContext, LEVEL1, LEVEL2, TEST3);
 
-        try {
-            org.omg.CORBA.Object o = nc2.resolve(new NameComponent[] { ncTest3 });
-            TEST(false);
-        } catch (NotFound e) {
-            // expected exception
-        }
+                rootNamingContext.unbind(new NameComponent[]{LEVEL1, LEVEL2, TEST3});
+                Util.assertNameNotBound(nc2, TEST3);
 
-        nc2.bind(new NameComponent[] { ncTest3 }, test3);
-        nc1.unbind(new NameComponent[] { level2 });
+                nc2.bind(new NameComponent[]{TEST3}, test3);
+                Util.assertTestIsBound("Test3", rootNamingContext, LEVEL1, LEVEL2, TEST3);
 
-        try {
-            org.omg.CORBA.Object o = initialContext.resolve(new NameComponent[] { level1, level2, ncTest3 });
-            TEST(false);
-        } catch (NotFound e) {
-            // expected exception
-        }
+                nc1.unbind(new NameComponent[]{LEVEL2});
+                Util.assertNameNotBound(rootNamingContext, LEVEL1, LEVEL2, TEST3);
 
-        nc1.rebind_context(new NameComponent[] { level2 }, nc2);
-
-
-        //
-        // Save reference. This must be done after POA manager
-        // activation, otherwise there is a potential for a race
-        // condition between the client sending a request and the
-        // server not being ready yet.
-        //
-        String refFile = "Test.ref";
-        try {
-            java.io.FileOutputStream file = new java.io.FileOutputStream(
-                    refFile);
-            java.io.PrintWriter out = new java.io.PrintWriter(file);
-            writeRef(orb, out, test1, initialContext, new NameComponent[] { ncTest1 });
-            writeRef(orb, out, test2, initialContext, new NameComponent[] { level1, ncTest2 });
-            writeRef(orb, out, test3, initialContext, new NameComponent[] { level1, level2, ncTest3 });
+                nc1.rebind_context(new NameComponent[]{LEVEL2}, nc2);
+                System.out.println("All contexts bound");
+            } catch (Exception e) {
+                e.printStackTrace(out);
+                throw e;
+            }
+            //
+            // Save reference. This must be done after POA manager
+            // activation, otherwise there is a potential for a race
+            // condition between the client sending a request and the
+            // server not being ready yet.
+            //
+            System.out.println("Writing IORs to file");
+            writeRef(orb, out, test1, rootNamingContext, new NameComponent[]{TEST1});
+            writeRef(orb, out, test2, rootNamingContext, new NameComponent[]{LEVEL1, TEST2});
+            writeRef(orb, out, test3, rootNamingContext, new NameComponent[]{LEVEL1, LEVEL2, TEST3});
             out.flush();
-            file.close();
+            System.out.println("IORs written to file");
         } catch (java.io.IOException ex) {
             System.err.println("Can't write to `" + ex.getMessage() + "'");
-            return 1;
+            throw ex;
         }
 
-        //
-        // Run implementation
-        //
+        // rename the completed file
+        Files.move(tmp, Paths.get(refFile));
+
         orb.run();
-
-        //
-        // Delete file
-        //
-        new java.io.File(refFile).delete();
-
-        return 0;
     }
 
-    private static void writeRef(ORB orb, PrintWriter out, org.omg.CORBA.Object obj, NamingContextExt context, NameComponent[] name) throws InvalidName {
-        String ref = orb.object_to_string(obj);
-        out.println(ref);
-        String nameString = context.to_string(name);
-        out.println(nameString);
+    public void bindObjectFactories() throws NotFound, CannotProceed, InvalidName, AlreadyBound {
+        rootNamingContext.bind(new NameComponent[]{RESOLVABLE_TEST}, resolvable);
+        Util.assertFactoryIsBound(rootNamingContext, RESOLVABLE_TEST);
+        rootNamingContext.bind(new NameComponent[]{RESOLVER_TEST}, resolver);
+        Util.assertFactoryIsBound(rootNamingContext, RESOLVER_TEST);
     }
 
-    public static void main(String args[]) throws TransientServiceException {
-
-        ORB orb = null;
-        int status = 0;
+    @Override
+    public void close() throws Exception {
         try {
-            TransientNameService service = new TransientNameService("localhost", NS_PORT);
-            System.out.println("Starting transient name service");
-            service.run();
-            System.out.println("Transient name service started");
-
-            java.util.Properties props = new Properties();
-            props.putAll(System.getProperties());
-            props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
-            props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
-            props.put("yoko.orb.oa.endpoint", "iiop --host localhost --port 40002");
-
-            args = new String[] { "-ORBInitRef", "NameService=" + NS_LOC };
-
-
-            orb = ORB.init(args, props);
-            status = run(orb, args);
-        } catch (Throwable ex) {
-            ex.printStackTrace();
-            status = 1;
+            Util.unbindEverything(rootNamingContext);
+        } finally {
+            orb.destroy();
         }
-
-        if (orb != null) {
-            try {
-                orb.destroy();
-            } catch (Exception ex) {
-                ex.printStackTrace();
-                status = 1;
-            }
-        }
-
-        System.exit(status);
     }
 }
diff --git a/yoko-core/src/test/java/test/tnaming/ServerWithReadOnlyIntegralNameService.java b/yoko-core/src/test/java/test/tnaming/ServerWithReadOnlyIntegralNameService.java
new file mode 100644
index 0000000..aef0f83
--- /dev/null
+++ b/yoko-core/src/test/java/test/tnaming/ServerWithReadOnlyIntegralNameService.java
@@ -0,0 +1,22 @@
+package test.tnaming;
+
+import static org.apache.yoko.orb.spi.naming.NameServiceInitializer.NS_ORB_INIT_PROP;
+import static org.apache.yoko.orb.spi.naming.NameServiceInitializer.NS_REMOTE_ACCESS_ARG;
+import static org.apache.yoko.orb.spi.naming.RemoteAccess.readOnly;
+
+import java.util.Properties;
+
+public class ServerWithReadOnlyIntegralNameService {
+    public static void main(String args[]) throws Exception {
+        final String refFile = args[0];
+        Properties props = new Properties();
+        props.put(NS_ORB_INIT_PROP, "");
+        props.put("yoko.orb.oa.endpoint", "iiop --host localhost --port " + Util.NS_PORT);
+        try (Server s = new Server(refFile, props, NS_REMOTE_ACCESS_ARG, readOnly.name())) {
+            Util.createBindingsOverWhichToIterate(s.orb, s.rootNamingContext);
+            s.bindObjectFactories();
+            s.run();
+            
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/tnaming/ServerWithReadWriteIntegralNameService.java b/yoko-core/src/test/java/test/tnaming/ServerWithReadWriteIntegralNameService.java
new file mode 100644
index 0000000..eabaaa3
--- /dev/null
+++ b/yoko-core/src/test/java/test/tnaming/ServerWithReadWriteIntegralNameService.java
@@ -0,0 +1,26 @@
+package test.tnaming;
+
+import static org.apache.yoko.orb.spi.naming.NameServiceInitializer.NS_ORB_INIT_PROP;
+import static org.apache.yoko.orb.spi.naming.NameServiceInitializer.NS_REMOTE_ACCESS_ARG;
+import static org.apache.yoko.orb.spi.naming.RemoteAccess.readWrite;
+
+import java.util.Properties;
+
+public class ServerWithReadWriteIntegralNameService {
+    public static void main(String args[]) throws Exception {
+        final String refFile = args[0];
+        System.out.println("1");
+        Properties props = new Properties();
+        System.out.println("2");
+        props.put(NS_ORB_INIT_PROP, "");
+        System.out.println("3");
+        props.put("yoko.orb.oa.endpoint", "iiop --host localhost --port " + Util.NS_PORT);
+        System.out.println("4");
+        try (Server s = new Server(refFile, props, NS_REMOTE_ACCESS_ARG, readWrite.name())) {
+            System.out.println("5");
+            s.bindObjectFactories();
+            s.run();
+            
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/tnaming/ServerWithReadWriteStandaloneNameService.java b/yoko-core/src/test/java/test/tnaming/ServerWithReadWriteStandaloneNameService.java
new file mode 100644
index 0000000..194adc8
--- /dev/null
+++ b/yoko-core/src/test/java/test/tnaming/ServerWithReadWriteStandaloneNameService.java
@@ -0,0 +1,24 @@
+package test.tnaming;
+
+import java.util.Properties;
+
+import org.apache.yoko.orb.CosNaming.tnaming.TransientNameService;
+
+public class ServerWithReadWriteStandaloneNameService {
+    public static void main(String args[]) throws Exception {
+        final String refFile = args[0];
+        try (TransientNameService service = new TransientNameService("localhost", Util.NS_PORT)) {
+            System.out.println("Starting transient name service");
+            service.run();
+            System.out.println("Transient name service started");
+            Properties props = new Properties();
+            props.put("yoko.orb.oa.endpoint", "iiop --host localhost --port " + (Util.NS_PORT+1));
+            props.put("org.omg.CORBA.ORBClass", "org.apache.yoko.orb.CORBA.ORB");
+            props.put("org.omg.CORBA.ORBSingletonClass", "org.apache.yoko.orb.CORBA.ORBSingleton");
+            
+            try (Server s = new Server(refFile, props, "-ORBInitRef", "NameService=" + Util.NS_LOC)) {
+                s.run();
+            }
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/tnaming/TestFactory_impl.java b/yoko-core/src/test/java/test/tnaming/TestFactory_impl.java
new file mode 100644
index 0000000..82b3858
--- /dev/null
+++ b/yoko-core/src/test/java/test/tnaming/TestFactory_impl.java
@@ -0,0 +1,29 @@
+package test.tnaming;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.yoko.orb.spi.naming.Resolvable;
+import org.omg.CORBA.LocalObject;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.Object;
+import org.omg.PortableServer.POA;
+
+public class TestFactory_impl extends LocalObject implements Resolvable{
+
+	POA _poa;
+	ORB _orb;
+	String _baseName;
+	static final AtomicInteger _count = new AtomicInteger (0); 
+	
+	public TestFactory_impl (POA poa, ORB orb, String baseName) { 
+		_poa = poa;
+		_orb = orb;
+	}
+	
+	@Override
+	public Object resolve() {
+		String thisOnesName = "_baseName" + _count.incrementAndGet();
+		return new Test_impl(_poa, thisOnesName)._this_object(_orb);
+	}
+	
+}
diff --git a/yoko-core/src/test/java/test/tnaming/Test_impl.java b/yoko-core/src/test/java/test/tnaming/Test_impl.java
index 14a6fcc..56911a1 100644
--- a/yoko-core/src/test/java/test/tnaming/Test_impl.java
+++ b/yoko-core/src/test/java/test/tnaming/Test_impl.java
@@ -1,11 +1,11 @@
 /**
  *
  * 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
+ *  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
  *
@@ -16,7 +16,6 @@
  *  limitations under the License.
  */
 
-
 /**
  * @version $Rev: 491396 $ $Date: 2006-12-30 22:06:13 -0800 (Sat, 30 Dec 2006) $
  */
@@ -45,7 +44,7 @@
             return super._default_POA();
     }
 
-    public String get_id () {
+    public String get_id() {
         return name_;
     }
 
diff --git a/yoko-core/src/test/java/test/tnaming/Util.java b/yoko-core/src/test/java/test/tnaming/Util.java
new file mode 100644
index 0000000..2288de0
--- /dev/null
+++ b/yoko-core/src/test/java/test/tnaming/Util.java
@@ -0,0 +1,122 @@
+package test.tnaming;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.junit.Assert;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.UserException;
+import org.omg.CosNaming.BindingHolder;
+import org.omg.CosNaming.BindingIterator;
+import org.omg.CosNaming.BindingIteratorHolder;
+import org.omg.CosNaming.BindingListHolder;
+import org.omg.CosNaming.BindingType;
+import org.omg.CosNaming.NameComponent;
+import org.omg.CosNaming.NamingContext;
+import org.omg.CosNaming.NamingContextExt;
+import org.omg.CosNaming.NamingContextHelper;
+import org.omg.CosNaming.NamingContextPackage.CannotProceed;
+import org.omg.CosNaming.NamingContextPackage.InvalidName;
+import org.omg.CosNaming.NamingContextPackage.NotFound;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAHelper;
+
+public class Util {
+    static final NameComponent[] ITERATOR_TEST_CONTEXT_PATH = Util.makeName("iteratorTest");
+    static final Set<String> EXPECTED_NAMES = Collections.unmodifiableSet(new TreeSet<>(Arrays.asList("test0 test1 test2 test3 test4 test5 test6 test7 test8 test9".split(" "))));
+    static final int NS_PORT = 40001;
+    static final String NS_LOC = "corbaloc::localhost:40001/NameService";
+    
+    static void assertTestIsBound(String expectedId, NamingContextExt ctx, NameComponent ...path) throws CannotProceed, InvalidName {
+        assertNotNull(path);
+        assertNotEquals(0, path.length);
+        try {
+            org.omg.CORBA.Object o = ctx.resolve(path);
+            Test test = TestHelper.narrow(o);
+            assertTrue(test.get_id().equals(expectedId));
+        } catch (NotFound e) {
+            fail("Should have found Test object at path: " + ctx.to_string(path) );
+        }
+    }
+    
+    static void assertFactoryIsBound(NamingContextExt ctx, NameComponent ...path) throws CannotProceed, InvalidName {
+    	assertNotNull(path);
+    	assertNotEquals(0, path.length);
+
+    	try { 
+    		org.omg.CORBA.Object o1 = ctx.resolve(path);
+    		org.omg.CORBA.Object o2 = ctx.resolve(path);
+    		assertFalse(o1._is_equivalent(o2));
+    		
+    		String id1 = TestHelper.narrow(o1).get_id();
+    		String id2 = TestHelper.narrow(o2).get_id();
+    		assertNotEquals(id1, id2);
+    		
+    	} catch (NotFound nf) { 
+    		fail("Should have found Test object at path: " + ctx.to_string(path) );
+    	}
+    }
+
+    
+    static void assertNameNotBound(NamingContext initialContext, NameComponent...path) throws CannotProceed, InvalidName {
+        try {
+            initialContext.resolve(path);
+            fail("Expected NotFound exception");
+        } catch (NotFound e) {
+            // expected exception
+        }
+    }
+    static NameComponent[] makeName(String name) {
+        return new NameComponent[]{new NameComponent(name, "")};
+    }
+
+    static void assertTestIsBound(Test expected, NamingContextExt initialContext, String name) throws UserException {
+        Test test1a = TestHelper.narrow(initialContext.resolve_str(name));
+        assertNotNull(test1a);
+        assertEquals(test1a.get_id(),expected.get_id());
+    }
+
+    static void assertCorbanameIsBound(Test expected, ORB orb, String corbaname) throws UserException {
+        Test test1a = TestHelper.narrow(orb.string_to_object(corbaname));
+        assertNotNull(test1a);
+        assertEquals(test1a.get_id(),expected.get_id());
+    }
+
+    static void createBindingsOverWhichToIterate(ORB orb, NamingContext initialContext) throws Exception {
+        System.out.println("creating bindings");
+        // get the root poa
+        POA rootPoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
+        System.out.println("got poa");
+        // create the context
+        NamingContext nc = initialContext.bind_new_context(ITERATOR_TEST_CONTEXT_PATH);
+        // add the bindings
+        for (String name : EXPECTED_NAMES) 
+            nc.bind(makeName(name), new Test_impl(rootPoa, name)._this_object(orb));
+    }
+
+    public static void unbindEverything(NamingContext ctx) throws Exception {
+        BindingIteratorHolder iterHolder = new BindingIteratorHolder();
+        ctx.list(0, new BindingListHolder(), iterHolder);
+        BindingIterator bi = iterHolder.value;
+        BindingHolder bh = new BindingHolder();
+        while (bi.next_one(bh)) {
+            if (bh.value.binding_type.value() == BindingType._ncontext) {
+                org.omg.CORBA.Object o = ctx.resolve(bh.value.binding_name);
+                NamingContext nestedCtx = NamingContextHelper.narrow(o);
+                assertNotNull(nestedCtx);
+                unbindEverything(nestedCtx);
+                nestedCtx.destroy();
+            }
+            ctx.unbind(bh.value.binding_name);
+        }
+    }
+}
diff --git a/yoko-core/src/test/java/test/types/TestAny.java b/yoko-core/src/test/java/test/types/TestAny.java
index 9afda6a..76559fc 100644
--- a/yoko-core/src/test/java/test/types/TestAny.java
+++ b/yoko-core/src/test/java/test/types/TestAny.java
@@ -17,8 +17,11 @@
 
 package test.types;
 
+import static org.junit.Assert.assertTrue;
+
 import java.math.*;
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 
 public class TestAny extends test.common.TestBase {
@@ -34,9 +37,9 @@
             any.insert_short(v);
             v = any.extract_short();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_short(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -46,9 +49,9 @@
             any.insert_ushort(v);
             v = any.extract_ushort();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_ushort(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -58,9 +61,9 @@
             any.insert_long(v);
             v = any.extract_long();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_long(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -70,9 +73,9 @@
             any.insert_ulong(v);
             v = any.extract_ulong();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_ulong(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -82,9 +85,9 @@
             any.insert_longlong(v);
             v = any.extract_longlong();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_longlong(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -94,9 +97,9 @@
             any.insert_ulonglong(v);
             v = any.extract_ulonglong();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_ulonglong(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -106,9 +109,9 @@
             any.insert_float(v);
             v = any.extract_float();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_float(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -118,9 +121,9 @@
             any.insert_double(v);
             v = any.extract_double();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_double(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -130,9 +133,9 @@
             any.insert_octet(v);
             v = any.extract_octet();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_octet(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -142,9 +145,9 @@
             any.insert_char(v);
             v = any.extract_char();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_char(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -154,9 +157,9 @@
             any.insert_wchar(v);
             v = any.extract_wchar();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_wchar(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -166,9 +169,9 @@
             any.insert_boolean(v);
             v = any.extract_boolean();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_boolean(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -178,9 +181,9 @@
             any.insert_string(v);
             v = any.extract_string();
 
-            TEST(v.equals(vSave));
+            assertTrue(v.equals(vSave));
             anyEq.insert_string(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -190,9 +193,9 @@
             any.insert_wstring(v);
             v = any.extract_wstring();
 
-            TEST(v.equals(vSave));
+            assertTrue(v.equals(vSave));
             anyEq.insert_wstring(v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -202,9 +205,9 @@
             any.insert_fixed(v1, orb.create_fixed_tc((short) 24, (short) 0));
             v1 = any.extract_fixed();
 
-            TEST(v1.compareTo(v1Save) == 0);
+            assertTrue(v1.compareTo(v1Save) == 0);
             anyEq.insert_fixed(v1, orb.create_fixed_tc((short) 24, (short) 0));
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
 
             BigDecimal v2 = new BigDecimal("1.23456789");
             BigDecimal v2Save = v2;
@@ -212,9 +215,9 @@
             any.insert_fixed(v2, orb.create_fixed_tc((short) 24, (short) 8));
             v2 = any.extract_fixed();
 
-            TEST(v2.compareTo(v2Save) == 0);
+            assertTrue(v2.compareTo(v2Save) == 0);
             anyEq.insert_fixed(v2, orb.create_fixed_tc((short) 24, (short) 8));
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -238,9 +241,9 @@
             any7 = any6.extract_any();
             v = any7.extract_double();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_any(any3);
-            TEST(any4.equal(anyEq));
+            assertTrue(any4.equal(anyEq));
         }
 
         {
@@ -264,9 +267,9 @@
             any7 = any6.extract_any();
             v = any7.extract_string();
 
-            TEST(v.equals(vSave));
+            assertTrue(v.equals(vSave));
             anyEq.insert_any(any3);
-            TEST(any4.equal(anyEq));
+            assertTrue(any4.equal(anyEq));
         }
 
         {
@@ -291,9 +294,9 @@
             any7 = any6.extract_any();
             v = any7.extract_char();
 
-            TEST(v == vSave);
+            assertTrue(v == vSave);
             anyEq.insert_any(any3);
-            TEST(any4.equal(anyEq));
+            assertTrue(any4.equal(anyEq));
         }
 
         {
@@ -310,15 +313,15 @@
             TestStruct1Helper.insert(any, v);
             v = TestStruct1Helper.extract(any);
 
-            TEST(v.s == vSave.s);
-            TEST(v.l == vSave.l);
-            TEST(v.d == vSave.d);
-            TEST(v.c == vSave.c);
-            TEST(v.b == vSave.b);
-            TEST(v.o == vSave.o);
-            TEST(v.str.equals(vSave.str));
+            assertTrue(v.s == vSave.s);
+            assertTrue(v.l == vSave.l);
+            assertTrue(v.d == vSave.d);
+            assertTrue(v.c == vSave.c);
+            assertTrue(v.b == vSave.b);
+            assertTrue(v.o == vSave.o);
+            assertTrue(v.str.equals(vSave.str));
             TestStruct1Helper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
 
             TestStruct2 v2 = new TestStruct2();
             v2.da = new double[10][20][30];
@@ -335,37 +338,37 @@
             TestStruct2Helper.insert(any2, v2);
             v2 = TestStruct2Helper.extract(any2);
 
-            TEST(v2.s.s == vSave.s);
-            TEST(v2.s.l == vSave.l);
-            TEST(v2.s.d == vSave.d);
-            TEST(v2.s.c == vSave.c);
-            TEST(v2.s.b == vSave.b);
-            TEST(v2.s.o == vSave.o);
-            TEST(v2.s.str.equals(vSave.str));
-            TEST(v2.da[0][0][0] == 1.23);
-            TEST(v2.da[2][3][4] == -1.11);
-            TEST(v2.sa[50].equals("Hi!"));
+            assertTrue(v2.s.s == vSave.s);
+            assertTrue(v2.s.l == vSave.l);
+            assertTrue(v2.s.d == vSave.d);
+            assertTrue(v2.s.c == vSave.c);
+            assertTrue(v2.s.b == vSave.b);
+            assertTrue(v2.s.o == vSave.o);
+            assertTrue(v2.s.str.equals(vSave.str));
+            assertTrue(v2.da[0][0][0] == 1.23);
+            assertTrue(v2.da[2][3][4] == -1.11);
+            assertTrue(v2.sa[50].equals("Hi!"));
             v = TestStruct1Helper.extract(v2.a);
-            TEST(v.s == vSave.s);
-            TEST(v.l == vSave.l);
-            TEST(v.d == vSave.d);
-            TEST(v.c == vSave.c);
-            TEST(v.b == vSave.b);
-            TEST(v.o == vSave.o);
-            TEST(v.str.equals(vSave.str));
+            assertTrue(v.s == vSave.s);
+            assertTrue(v.l == vSave.l);
+            assertTrue(v.d == vSave.d);
+            assertTrue(v.c == vSave.c);
+            assertTrue(v.b == vSave.b);
+            assertTrue(v.o == vSave.o);
+            assertTrue(v.str.equals(vSave.str));
 
             TestStruct2Helper.insert(anyEq, v2);
-            TEST(any2.equal(anyEq));
+            assertTrue(any2.equal(anyEq));
         }
 
         {
             TestEnum v = TestEnum.B;
             TestEnumHelper.insert(any, v);
             v = TestEnumHelper.extract(any);
-            TEST(v == TestEnum.B);
+            assertTrue(v == TestEnum.B);
 
             TestEnumHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -381,10 +384,10 @@
             v = OctetSeqHelper.extract(any);
 
             for (o = 0; o < 100; o++)
-                TEST(v[o] == o);
+				assertTrue(v[o] == o);
 
             OctetSeqHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -401,10 +404,10 @@
             double[] v2 = DoubleSeqHelper.extract(any);
 
             for (i = 0, d = 0; d < 10; i++, d += 0.1)
-                TEST(v2[i] == v[i]);
+				assertTrue(v2[i] == v[i]);
 
             DoubleSeqHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -417,10 +420,10 @@
             double[] v2 = Double10SeqHelper.extract(any);
 
             for (i = 0; i < 10; i++)
-                TEST(v2[i] == v[i]);
+				assertTrue(v2[i] == v[i]);
 
             Double10SeqHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -436,10 +439,10 @@
             v = CharSeqHelper.extract(any);
 
             for (o = 0; o < 100; o++)
-                TEST(v[o] == o);
+				assertTrue(v[o] == o);
 
             CharSeqHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -452,10 +455,10 @@
             v = String40SeqHelper.extract(any);
 
             for (i = 0; i < 40; i++)
-                TEST(v[i].equals("abc"));
+				assertTrue(v[i].equals("abc"));
 
             String40SeqHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -484,24 +487,24 @@
             TestStruct1SeqHelper.insert(any, v);
             v = TestStruct1SeqHelper.extract(any);
 
-            TEST(v[0].s == vSave[0].s);
-            TEST(v[0].l == vSave[0].l);
-            TEST(v[0].d == vSave[0].d);
-            TEST(v[0].b == vSave[0].b);
-            TEST(v[0].c == vSave[0].c);
-            TEST(v[0].o == vSave[0].o);
-            TEST(v[0].str.equals(vSave[0].str));
+            assertTrue(v[0].s == vSave[0].s);
+            assertTrue(v[0].l == vSave[0].l);
+            assertTrue(v[0].d == vSave[0].d);
+            assertTrue(v[0].b == vSave[0].b);
+            assertTrue(v[0].c == vSave[0].c);
+            assertTrue(v[0].o == vSave[0].o);
+            assertTrue(v[0].str.equals(vSave[0].str));
 
-            TEST(v[1].s == vSave[1].s);
-            TEST(v[1].l == vSave[1].l);
-            TEST(v[1].d == vSave[1].d);
-            TEST(v[1].b == vSave[1].b);
-            TEST(v[1].c == vSave[1].c);
-            TEST(v[1].o == vSave[1].o);
-            TEST(v[1].str.equals(vSave[1].str));
+            assertTrue(v[1].s == vSave[1].s);
+            assertTrue(v[1].l == vSave[1].l);
+            assertTrue(v[1].d == vSave[1].d);
+            assertTrue(v[1].b == vSave[1].b);
+            assertTrue(v[1].c == vSave[1].c);
+            assertTrue(v[1].o == vSave[1].o);
+            assertTrue(v[1].str.equals(vSave[1].str));
 
             TestStruct1SeqHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -513,12 +516,12 @@
             DoubleArrayHelper.insert(any, v);
             v = DoubleArrayHelper.extract(any);
 
-            TEST(v[0][0][0] == -999);
-            TEST(v[1][2][3] == 1.23);
-            TEST(v[9][19][29] == 9.1929);
+            assertTrue(v[0][0][0] == -999);
+            assertTrue(v[1][2][3] == 1.23);
+            assertTrue(v[9][19][29] == 9.1929);
 
             DoubleArrayHelper.insert(anyEq, v);
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
 
         {
@@ -526,10 +529,10 @@
 
             any.insert_TypeCode(TestStruct1Helper.type());
             tc = any.extract_TypeCode();
-            TEST(tc.equal(TestStruct1Helper.type()));
+            assertTrue(tc.equal(TestStruct1Helper.type()));
 
             anyEq.insert_TypeCode(TestStruct1Helper.type());
-            TEST(any.equal(anyEq));
+            assertTrue(any.equal(anyEq));
         }
     }
 
diff --git a/yoko-core/src/test/java/test/types/TestConst.java b/yoko-core/src/test/java/test/types/TestConst.java
index acf6ffb..f2e30ab 100644
--- a/yoko-core/src/test/java/test/types/TestConst.java
+++ b/yoko-core/src/test/java/test/types/TestConst.java
@@ -17,126 +17,129 @@
 
 package test.types;
 
+import static org.junit.Assert.assertTrue;
+
 import java.math.*;
+
 import org.omg.CORBA.*;
 
 public class TestConst extends test.common.TestBase {
     public TestConst() {
         {
             final Measurement constEnum = Measurement.FURLONGS;
-            TEST(constEnum == ConstEnum.value);
+            assertTrue(constEnum == ConstEnum.value);
 
             final int constLong = -1234;
-            TEST(constLong == ConstLong.value);
+            assertTrue(constLong == ConstLong.value);
 
             final long constLongLong = constLong * constLong;
-            TEST(constLongLong == ConstLongLong.value);
+            assertTrue(constLongLong == ConstLongLong.value);
 
             final long constLongLongMin = -9223372036854775807L - 1L;
-            TEST(constLongLongMin == ConstLongLongMin.value);
+            assertTrue(constLongLongMin == ConstLongLongMin.value);
 
             final long constLongLongMax = 9223372036854775807L;
-            TEST(constLongLongMax == ConstLongLongMax.value);
+            assertTrue(constLongLongMax == ConstLongLongMax.value);
 
             final int constULong = (5432 + constLong) * 100 % 124;
-            TEST(constULong == ConstULong.value);
+            assertTrue(constULong == ConstULong.value);
 
             final long constULongLong = constULong + (constULong << 20);
-            TEST(constULongLong == ConstULongLong.value);
+            assertTrue(constULongLong == ConstULongLong.value);
 
             //
             // 18446744073709551615 is represented as -1
             //
             final long constULongLongMax = -1L;
-            TEST(constULongLongMax == ConstULongLongMax.value);
+            assertTrue(constULongLongMax == ConstULongLongMax.value);
 
             final double constDouble = 50.23 - 1532.718 * 0.029;
-            TEST(constDouble == ConstDouble.value);
+            assertTrue(constDouble == ConstDouble.value);
 
             final float constFloat = (float) (constDouble * 1.11);
-            TEST(constFloat == ConstFloat.value);
+            assertTrue(constFloat == ConstFloat.value);
 
             final short constShort = (short) (-23 % 10);
-            TEST(constShort == ConstShort.value);
+            assertTrue(constShort == ConstShort.value);
 
             final boolean constBoolean = true;
-            TEST(constBoolean == ConstBoolean.value);
+            assertTrue(constBoolean == ConstBoolean.value);
 
             final byte constOctet = (byte) 254;
-            TEST(constOctet == ConstOctet.value);
+            assertTrue(constOctet == ConstOctet.value);
 
             final BigDecimal constFixed = new BigDecimal("275.189").multiply(
                     new BigDecimal("1.163")).add(new BigDecimal("48.0093"));
-            TEST(constFixed.equals(ConstFixed.value));
+            assertTrue(constFixed.equals(ConstFixed.value));
 
             final String constString = "This is ConstString";
-            TEST(constString.equals(ConstString.value));
+            assertTrue(constString.equals(ConstString.value));
 
             final String constEmptyString = "";
-            TEST(constEmptyString.equals(ConstEmptyString.value));
+            assertTrue(constEmptyString.equals(ConstEmptyString.value));
 
             final String constWString = "This is ConstWString";
-            TEST(constWString.equals(ConstWString.value));
+            assertTrue(constWString.equals(ConstWString.value));
 
             final String constEmptyWString = "";
-            TEST(constEmptyWString.equals(ConstEmptyWString.value));
+            assertTrue(constEmptyWString.equals(ConstEmptyWString.value));
         }
 
         {
             final int constLong = 12345678;
-            TEST(constLong == test.types.TestConstModule.ConstLong.value);
+            assertTrue(constLong == test.types.TestConstModule.ConstLong.value);
 
             final double constDouble = ConstDouble.value / 2.0;
-            TEST(constDouble == test.types.TestConstModule.ConstDouble.value);
+            assertTrue(constDouble == test.types.TestConstModule.ConstDouble.value);
 
             final boolean constBoolean = false;
-            TEST(constBoolean == test.types.TestConstModule.ConstBoolean.value);
+            assertTrue(constBoolean == test.types.TestConstModule.ConstBoolean.value);
 
             final String constString = "This is ConstString in a module";
-            TEST(constString
-                    .equals(test.types.TestConstModule.ConstString.value));
+            assertTrue(constString
+			.equals(test.types.TestConstModule.ConstString.value));
 
             final String constWString = "This is ConstWString in a module";
-            TEST(constWString
-                    .equals(test.types.TestConstModule.ConstWString.value));
+            assertTrue(constWString
+			.equals(test.types.TestConstModule.ConstWString.value));
 
             final Measurement constEnum = Measurement.METERS;
-            TEST(constEnum == test.types.TestConstModule.ConstEnum.value);
+            assertTrue(constEnum == test.types.TestConstModule.ConstEnum.value);
         }
 
         {
             final int constLong = (0xf | 0xf000) & 0xfffe;
-            TEST(constLong == TestConstInterface.ConstLong);
+            assertTrue(constLong == TestConstInterface.ConstLong);
 
             final int constULong = (int) 0xFFFFFFFF;
-            TEST(constULong == TestConstInterface.ConstULong);
+            assertTrue(constULong == TestConstInterface.ConstULong);
 
             final char constChar0 = (char) 0;
-            TEST(constChar0 == TestConstInterface.ConstChar0);
+            assertTrue(constChar0 == TestConstInterface.ConstChar0);
 
             final char constChar1 = 'c';
-            TEST(constChar1 == TestConstInterface.ConstChar1);
+            assertTrue(constChar1 == TestConstInterface.ConstChar1);
 
             final char constChar2 = '\n';
-            TEST(constChar2 == TestConstInterface.ConstChar2);
+            assertTrue(constChar2 == TestConstInterface.ConstChar2);
 
             final char constChar3 = '\377';
-            TEST(constChar3 == TestConstInterface.ConstChar3);
+            assertTrue(constChar3 == TestConstInterface.ConstChar3);
 
             final char constChar4 = '\210';
-            TEST(constChar4 == TestConstInterface.ConstChar4);
+            assertTrue(constChar4 == TestConstInterface.ConstChar4);
 
             final char constChar5 = '\'';
-            TEST(constChar5 == TestConstInterface.ConstChar5);
+            assertTrue(constChar5 == TestConstInterface.ConstChar5);
 
             final char constWChar = 'Z';
-            TEST(constWChar == TestConstInterface.ConstWChar);
+            assertTrue(constWChar == TestConstInterface.ConstWChar);
 
             final String constString = "\n\t\013\b\r\f\007\\?\'\"\377\377\007";
-            TEST(constString.equals(TestConstInterface.ConstString));
+            assertTrue(constString.equals(TestConstInterface.ConstString));
 
             final String constWString = "\n\t\013\b\r\f\007\\?\'\"\377\377\007";
-            TEST(constWString.equals(TestConstInterface.ConstWString));
+            assertTrue(constWString.equals(TestConstInterface.ConstWString));
         }
     }
 
diff --git a/yoko-core/src/test/java/test/types/TestDynAny.java b/yoko-core/src/test/java/test/types/TestDynAny.java
index 32e6a0e..ff3c8d7 100644
--- a/yoko-core/src/test/java/test/types/TestDynAny.java
+++ b/yoko-core/src/test/java/test/types/TestDynAny.java
@@ -17,13 +17,17 @@
 
 package test.types;
 
+import static org.junit.Assert.assertTrue;
+
 import java.math.*;
 import java.util.Properties;
+
 import org.omg.CORBA.Any;
 import org.omg.CORBA.TypeCode;
 import org.omg.CORBA.TCKind;
 import org.omg.CORBA.ORB;
 import org.omg.DynamicAny.*;
+
 import test.types.DynAnyTypes.*;
 
 public class TestDynAny extends test.common.TestBase {
@@ -120,7 +124,7 @@
             //
             d1 = factory.create_dyn_any_from_type_code(tc);
             TypeCode tcv = d1.type();
-            TEST(tc.equal(tcv));
+            assertTrue(tc.equal(tcv));
             d1.destroy();
 
             //
@@ -130,7 +134,7 @@
                 d1 = factory.create_dyn_any_from_type_code(tc);
                 d2 = factory.create_dyn_any(badAny);
                 d1.assign(d2);
-                TEST("assign() should not have succeeded" == null);
+                assertTrue("assign() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 d1.destroy();
@@ -143,7 +147,7 @@
             try {
                 d1 = factory.create_dyn_any_from_type_code(tc);
                 d1.from_any(badAny);
-                TEST("from_any() should not have succeeded" == null);
+                assertTrue("from_any() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 d1.destroy();
@@ -169,7 +173,7 @@
                     a.type(tc);
                     d1 = factory.create_dyn_any_from_type_code(tc);
                     d1.from_any(a);
-                    TEST("from_any() should not have succeeded" == null);
+                    assertTrue("from_any() should not have succeeded" == null);
                 } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                     // expected
                     d1.destroy();
@@ -185,35 +189,35 @@
                     count = d1.component_count();
                 else
                     count = origTC.member_count();
-                TEST(count > 0);
+                assertTrue(count > 0);
 
                 //
                 // Test: seek
                 //
-                TEST(d1.seek(0) == true);
-                TEST(d1.seek(-1) == false);
-                TEST(d1.seek(count) == false);
-                TEST(d1.seek(count - 1) == true);
+                assertTrue(d1.seek(0) == true);
+                assertTrue(d1.seek(-1) == false);
+                assertTrue(d1.seek(count) == false);
+                assertTrue(d1.seek(count - 1) == true);
 
                 //
                 // Test: next
                 //
                 d1.seek(-1);
-                TEST(d1.next() == true);
+                assertTrue(d1.next() == true);
                 d1.seek(count - 1);
-                TEST(d1.next() == false);
+                assertTrue(d1.next() == false);
 
                 //
                 // Test: component_count()
                 //
-                TEST(d1.component_count() == count);
+                assertTrue(d1.component_count() == count);
 
                 //
                 // Test: current_component
                 //
                 d1.rewind();
                 d2 = d1.current_component();
-                TEST(d2 != null);
+                assertTrue(d2 != null);
 
                 //
                 // Test: destroy
@@ -226,7 +230,7 @@
                 //
                 d1.seek(-9);
                 d3 = d1.current_component();
-                TEST(d3 == null);
+                assertTrue(d3 == null);
 
                 d1.destroy();
             } else {
@@ -235,25 +239,25 @@
                 //
                 // Test: seek
                 //
-                TEST(d1.seek(0) == false);
-                TEST(d1.seek(-1) == false);
+                assertTrue(d1.seek(0) == false);
+                assertTrue(d1.seek(-1) == false);
 
                 //
                 // Test: next
                 //
-                TEST(d1.next() == false);
+                assertTrue(d1.next() == false);
 
                 //
                 // Test: component_count()
                 //
-                TEST(d1.component_count() == 0);
+                assertTrue(d1.component_count() == 0);
 
                 //
                 // Test: current_component TypeMismatch exception
                 //
                 try {
                     d1.current_component();
-                    TEST("current_component() should not have succeeded" == null);
+                    assertTrue("current_component() should not have succeeded" == null);
                 } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                     // expected
                 }
@@ -261,13 +265,13 @@
                 d1.destroy();
             }
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -284,28 +288,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_short);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_short() == (short) 0);
+            assertTrue(d1.get_short() == (short) 0);
             d1.insert_short((short) -53);
-            TEST(d1.get_short() == (short) -53);
+            assertTrue(d1.get_short() == (short) -53);
             d1.insert_short((short) 32000);
-            TEST(d1.get_short() == (short) 32000);
+            assertTrue(d1.get_short() == (short) 32000);
 
             av = d1.to_any();
             short shortVal = av.extract_short();
-            TEST(shortVal == (short) 32000);
+            assertTrue(shortVal == (short) 32000);
 
             any.insert_short((short) 32000);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_short() == (short) 32000);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_short() == (short) 32000);
 
             any.insert_short((short) -99);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -318,28 +322,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_ushort);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_ushort() == (short) 0);
+            assertTrue(d1.get_ushort() == (short) 0);
             d1.insert_ushort((short) 199);
-            TEST(d1.get_ushort() == (short) 199);
+            assertTrue(d1.get_ushort() == (short) 199);
             d1.insert_ushort((short) 65001);
-            TEST(d1.get_ushort() == (short) 65001);
+            assertTrue(d1.get_ushort() == (short) 65001);
 
             av = d1.to_any();
             short ushortVal = av.extract_ushort();
-            TEST(ushortVal == (short) 65001);
+            assertTrue(ushortVal == (short) 65001);
 
             any.insert_ushort((short) 65001);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_ushort() == (short) 65001);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_ushort() == (short) 65001);
 
             any.insert_ushort((short) 501);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -352,28 +356,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_long);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_long() == 0);
+            assertTrue(d1.get_long() == 0);
             d1.insert_long(-530000);
-            TEST(d1.get_long() == -530000);
+            assertTrue(d1.get_long() == -530000);
             d1.insert_long(3200000);
-            TEST(d1.get_long() == 3200000);
+            assertTrue(d1.get_long() == 3200000);
 
             av = d1.to_any();
             int longVal = av.extract_long();
-            TEST(longVal == 3200000);
+            assertTrue(longVal == 3200000);
 
             any.insert_long(3200000);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_long() == 3200000);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_long() == 3200000);
 
             any.insert_long(-99000);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -386,28 +390,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_ulong);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_ulong() == 0);
+            assertTrue(d1.get_ulong() == 0);
             d1.insert_ulong(199000);
-            TEST(d1.get_ulong() == 199000);
+            assertTrue(d1.get_ulong() == 199000);
             d1.insert_ulong(65001000);
-            TEST(d1.get_ulong() == 65001000);
+            assertTrue(d1.get_ulong() == 65001000);
 
             av = d1.to_any();
             int ulongVal = av.extract_ulong();
-            TEST(ulongVal == 65001000);
+            assertTrue(ulongVal == 65001000);
 
             any.insert_ulong(65001000);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_ulong() == 65001000);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_ulong() == 65001000);
 
             any.insert_ulong(501000);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -420,28 +424,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_float);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_float() == 0.0f);
+            assertTrue(d1.get_float() == 0.0f);
             d1.insert_float(199.001f);
-            TEST(d1.get_float() > 199.0f && d1.get_float() < 199.1f);
+            assertTrue(d1.get_float() > 199.0f && d1.get_float() < 199.1f);
             d1.insert_float(6500.10001f);
-            TEST(d1.get_float() > 6500.0f && d1.get_float() < 6501.0f);
+            assertTrue(d1.get_float() > 6500.0f && d1.get_float() < 6501.0f);
 
             av = d1.to_any();
             float floatVal = av.extract_float();
-            TEST(floatVal > 6500.1 && floatVal < 6500.2);
+            assertTrue(floatVal > 6500.1 && floatVal < 6500.2);
 
             any.insert_float((float) 6500.10001);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_float() > 6500.1 && copy.get_float() < 6500.2);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_float() > 6500.1 && copy.get_float() < 6500.2);
 
             any.insert_float((float) 501.001);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -454,28 +458,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_double);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_double() == 0.0);
+            assertTrue(d1.get_double() == 0.0);
             d1.insert_double(199000.001);
-            TEST(d1.get_double() > 199000.0 && d1.get_double() < 199000.1);
+            assertTrue(d1.get_double() > 199000.0 && d1.get_double() < 199000.1);
             d1.insert_double(6500000.10001);
-            TEST(d1.get_double() > 6500000.1 && d1.get_double() < 6500000.2);
+            assertTrue(d1.get_double() > 6500000.1 && d1.get_double() < 6500000.2);
 
             av = d1.to_any();
             double doubleVal = av.extract_double();
-            TEST(doubleVal > 6500000.1 && doubleVal < 6500000.2);
+            assertTrue(doubleVal > 6500000.1 && doubleVal < 6500000.2);
 
             any.insert_double(6500000.10001);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_double() > 6500000.1 && copy.get_double() < 6500000.2);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_double() > 6500000.1 && copy.get_double() < 6500000.2);
 
             any.insert_double(501000.001);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -488,28 +492,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_boolean);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_boolean() == false);
+            assertTrue(d1.get_boolean() == false);
             d1.insert_boolean(false);
-            TEST(d1.get_boolean() == false);
+            assertTrue(d1.get_boolean() == false);
             d1.insert_boolean(true);
-            TEST(d1.get_boolean() == true);
+            assertTrue(d1.get_boolean() == true);
 
             av = d1.to_any();
             boolean boolVal = av.extract_boolean();
-            TEST(boolVal == true);
+            assertTrue(boolVal == true);
 
             any.insert_boolean(true);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_boolean() == true);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_boolean() == true);
 
             any.insert_boolean(false);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -522,28 +526,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_char);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_char() == 0);
+            assertTrue(d1.get_char() == 0);
             d1.insert_char('A');
-            TEST(d1.get_char() == 'A');
+            assertTrue(d1.get_char() == 'A');
             d1.insert_char('z');
-            TEST(d1.get_char() == 'z');
+            assertTrue(d1.get_char() == 'z');
 
             av = d1.to_any();
             char charVal = av.extract_char();
-            TEST(charVal == 'z');
+            assertTrue(charVal == 'z');
 
             any.insert_char('z');
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_char() == 'z');
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_char() == 'z');
 
             any.insert_char('@');
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -556,28 +560,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_octet);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_octet() == 0);
+            assertTrue(d1.get_octet() == 0);
             d1.insert_octet((byte) 255);
-            TEST(d1.get_octet() == (byte) 255);
+            assertTrue(d1.get_octet() == (byte) 255);
             d1.insert_octet((byte) 1);
-            TEST(d1.get_octet() == (byte) 1);
+            assertTrue(d1.get_octet() == (byte) 1);
 
             av = d1.to_any();
             byte octetVal = av.extract_octet();
-            TEST(octetVal == (byte) 1);
+            assertTrue(octetVal == (byte) 1);
 
             any.insert_octet((byte) 1);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_octet() == (byte) 1);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_octet() == (byte) 1);
 
             any.insert_octet((byte) 127);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -594,27 +598,27 @@
             d1.insert_any(any);
             av = d1.get_any();
             longVal = av.extract_long();
-            TEST(longVal == 345678);
+            assertTrue(longVal == 345678);
 
             Any anyVal = orb.create_any();
             anyVal.insert_long(345678);
             any.insert_any(anyVal);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             av = d1.to_any();
             Any cap = av.extract_any();
             longVal = cap.extract_long();
-            TEST(longVal == 345678);
+            assertTrue(longVal == 345678);
 
             anyVal.insert_string("anyValue");
             any.insert_any(anyVal);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
 
             d1.destroy();
             d2.destroy();
@@ -630,30 +634,30 @@
             d1 = factory.create_dyn_any_from_type_code(type);
             tcVal = d1.get_typecode();
             TypeCode tcNull = orb.get_primitive_tc(TCKind.tk_null);
-            TEST(tcVal.equal(tcNull));
+            assertTrue(tcVal.equal(tcNull));
             TypeCode tcFloat = orb.get_primitive_tc(TCKind.tk_float);
             d1.insert_typecode(tcFloat);
             tcVal = d1.get_typecode();
-            TEST(tcVal.equal(tcFloat));
+            assertTrue(tcVal.equal(tcFloat));
 
             av = d1.to_any();
             tcVal = av.extract_TypeCode();
-            TEST(tcVal.equal(tcFloat));
+            assertTrue(tcVal.equal(tcFloat));
 
             any.insert_TypeCode(tcFloat);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             tcVal = copy.get_typecode();
-            TEST(tcVal.equal(tcFloat));
+            assertTrue(tcVal.equal(tcFloat));
 
             TypeCode tcDouble = orb.get_primitive_tc(TCKind.tk_double);
             any.insert_TypeCode(tcDouble);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -666,34 +670,34 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_objref);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_reference() == null);
+            assertTrue(d1.get_reference() == null);
             org.omg.CORBA.Object objVal1, objVal2;
             objVal1 = orb.string_to_object("corbaloc::localhost:9999/SomeKey");
             d1.insert_reference(objVal1);
             objVal2 = d1.get_reference();
-            TEST(objVal1._is_equivalent(objVal2));
+            assertTrue(objVal1._is_equivalent(objVal2));
 
             av = d1.to_any();
             objVal2 = av.extract_Object();
-            TEST(objVal1._is_equivalent(objVal2));
+            assertTrue(objVal1._is_equivalent(objVal2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
 
             d2 = factory.create_dyn_any_from_type_code(type);
             any.insert_Object(objVal2);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.insert_reference(null);
             objVal1 = d1.get_reference();
-            TEST(objVal1 == null);
+            assertTrue(objVal1 == null);
             d2.assign(d1);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             copy.destroy();
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
 
             d1.destroy();
             d2.destroy();
@@ -708,28 +712,28 @@
             String stringVal;
             d1 = factory.create_dyn_any_from_type_code(type);
             stringVal = d1.get_string();
-            TEST(stringVal.length() == 0);
+            assertTrue(stringVal.length() == 0);
             d1.insert_string("polymorph");
             stringVal = d1.get_string();
-            TEST(stringVal.equals("polymorph"));
+            assertTrue(stringVal.equals("polymorph"));
 
             av = d1.to_any();
             String ccp = av.extract_string();
-            TEST(ccp.equals("polymorph"));
+            assertTrue(ccp.equals("polymorph"));
 
             any.insert_string("polymorph");
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             stringVal = copy.get_string();
-            TEST(stringVal.equals("polymorph"));
+            assertTrue(stringVal.equals("polymorph"));
 
             any.insert_string("cloister");
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -743,28 +747,28 @@
             long ll1 = -530000999L, ll2 = 3200000999L, ll3 = -99000999L;
             type = orb.get_primitive_tc(TCKind.tk_longlong);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_longlong() == 0);
+            assertTrue(d1.get_longlong() == 0);
             d1.insert_longlong(ll1);
-            TEST(d1.get_longlong() == ll1);
+            assertTrue(d1.get_longlong() == ll1);
             d1.insert_longlong(ll2);
-            TEST(d1.get_longlong() == ll2);
+            assertTrue(d1.get_longlong() == ll2);
 
             av = d1.to_any();
             long longlongVal = av.extract_longlong();
-            TEST(longlongVal == ll2);
+            assertTrue(longlongVal == ll2);
 
             any.insert_longlong(ll2);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_longlong() == ll2);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_longlong() == ll2);
 
             any.insert_longlong(ll3);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -778,28 +782,28 @@
             long ul1 = 199000999L, ul2 = 65001000999L, ul3 = 501000999L;
             type = orb.get_primitive_tc(TCKind.tk_ulonglong);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_ulonglong() == 0);
+            assertTrue(d1.get_ulonglong() == 0);
             d1.insert_ulonglong(ul1);
-            TEST(d1.get_ulonglong() == ul1);
+            assertTrue(d1.get_ulonglong() == ul1);
             d1.insert_ulonglong(ul2);
-            TEST(d1.get_ulonglong() == ul2);
+            assertTrue(d1.get_ulonglong() == ul2);
 
             av = d1.to_any();
             long ulonglongVal = av.extract_ulonglong();
-            TEST(ulonglongVal == ul2);
+            assertTrue(ulonglongVal == ul2);
 
             any.insert_ulonglong(ul2);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_ulonglong() == ul2);
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_ulonglong() == ul2);
 
             any.insert_ulonglong(ul3);
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -812,28 +816,28 @@
             //
             type = orb.get_primitive_tc(TCKind.tk_wchar);
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.get_wchar() == 0);
+            assertTrue(d1.get_wchar() == 0);
             d1.insert_wchar('A');
-            TEST(d1.get_wchar() == 'A');
+            assertTrue(d1.get_wchar() == 'A');
             d1.insert_wchar('z');
-            TEST(d1.get_wchar() == 'z');
+            assertTrue(d1.get_wchar() == 'z');
 
             av = d1.to_any();
             char wcharVal = av.extract_wchar();
-            TEST(wcharVal == 'z');
+            assertTrue(wcharVal == 'z');
 
             any.insert_wchar('z');
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
-            TEST(copy.get_wchar() == 'z');
+            assertTrue(d1.equal(copy));
+            assertTrue(copy.get_wchar() == 'z');
 
             any.insert_wchar('@');
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -848,29 +852,29 @@
             String wstringVal;
             d1 = factory.create_dyn_any_from_type_code(type);
             wstringVal = d1.get_wstring();
-            TEST(wstringVal.length() == 0);
+            assertTrue(wstringVal.length() == 0);
             d1.insert_wstring("polymorph");
             wstringVal = d1.get_wstring();
             String wstr = "polymorph";
-            TEST(wstringVal.equals(wstr));
+            assertTrue(wstringVal.equals(wstr));
 
             av = d1.to_any();
             String cwp = av.extract_wstring();
-            TEST(cwp.equals(wstr));
+            assertTrue(cwp.equals(wstr));
 
             any.insert_wstring(wstr);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             wstringVal = copy.get_wstring();
-            TEST(wstringVal.equals(wstr));
+            assertTrue(wstringVal.equals(wstr));
 
             any.insert_wstring("cloister");
             d2.from_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
 
             d1.destroy();
             d2.destroy();
@@ -885,7 +889,7 @@
             d1 = factory.create_dyn_any_from_type_code(type);
             av = d1.to_any();
             tc = av.type();
-            TEST(tc.equal(type));
+            assertTrue(tc.equal(type));
             d2 = d1.copy();
             d1.assign(d2);
             d1.destroy();
@@ -900,7 +904,7 @@
             d1 = factory.create_dyn_any_from_type_code(type);
             av = d1.to_any();
             tc = av.type();
-            TEST(tc.equal(type));
+            assertTrue(tc.equal(type));
             d2 = d1.copy();
             d1.assign(d2);
             d1.destroy();
@@ -918,11 +922,11 @@
             d2 = factory.create_dyn_any(any);
             d1.insert_dyn_any(d2);
             copy = d1.get_dyn_any();
-            TEST(copy.get_boolean() == true);
+            assertTrue(copy.get_boolean() == true);
             anyVal.insert_short((short) 53);
             d1.insert_any(anyVal);
             copy = d1.get_dyn_any();
-            TEST(copy.get_short() == (short) 53);
+            assertTrue(copy.get_short() == (short) 53);
             d1.destroy();
             d2.destroy();
 
@@ -933,11 +937,11 @@
             d1 = factory.create_dyn_any_from_type_code(type);
             d1.insert_string("123");
             stringVal = d1.get_string();
-            TEST(stringVal.equals("123"));
+            assertTrue(stringVal.equals("123"));
 
             try {
                 d1.insert_string("four");
-                TEST("insert_string() should not have succeeded" == null);
+                assertTrue("insert_string() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -951,21 +955,21 @@
             d1 = factory.create_dyn_any_from_type_code(type);
             d1.insert_wstring(wstr);
             wstringVal = d1.get_wstring();
-            TEST(wstringVal.equals(wstr));
+            assertTrue(wstringVal.equals(wstr));
 
             try {
                 d1.insert_wstring("four");
-                TEST("insert_wstring() should not have succeeded" == null);
+                assertTrue("insert_wstring() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -991,15 +995,15 @@
             f1 = DynFixedHelper.narrow(d1);
             str = f1.get_value();
             f = new BigDecimal(str);
-            TEST(f.equals(new BigDecimal("0")));
+            assertTrue(f.equals(new BigDecimal("0")));
 
             //
             // Test: set_value()
             //
-            TEST(f1.set_value("1.1"));
-            TEST(f1.set_value("123.1"));
-            TEST(f1.set_value("123.12"));
-            TEST(!f1.set_value("123.123"));
+            assertTrue(f1.set_value("1.1"));
+            assertTrue(f1.set_value("123.1"));
+            assertTrue(f1.set_value("123.12"));
+            assertTrue(!f1.set_value("123.123"));
 
             //
             // Test: from_any()
@@ -1013,13 +1017,13 @@
             //
             av = f1.to_any();
             f = av.extract_fixed();
-            TEST(f.equals(new BigDecimal("98")));
+            assertTrue(f.equals(new BigDecimal("98")));
 
             //
             // Test: copy
             //
             copy = f1.copy();
-            TEST(f1.equal(copy));
+            assertTrue(f1.equal(copy));
 
             f1.destroy();
             copy.destroy();
@@ -1031,7 +1035,7 @@
                 d1 = factory.create_dyn_any_from_type_code(tc);
                 f1 = DynFixedHelper.narrow(d1);
                 f1.set_value("");
-                TEST("set_value() should not have succeeded" == null);
+                assertTrue("set_value() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
                 d1.destroy();
@@ -1044,7 +1048,7 @@
                 d1 = factory.create_dyn_any_from_type_code(tc);
                 f1 = DynFixedHelper.narrow(d1);
                 f1.set_value("-123D?");
-                TEST("set_value() should not have succeeded" == null);
+                assertTrue("set_value() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 d1.destroy();
@@ -1057,7 +1061,7 @@
                 d1 = factory.create_dyn_any_from_type_code(tc);
                 f1 = DynFixedHelper.narrow(d1);
                 f1.set_value("12345.123"); // too many digits
-                TEST("set_value() should not have succeeded" == null);
+                assertTrue("set_value() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
                 d1.destroy();
@@ -1072,7 +1076,7 @@
                 d1 = factory.create_dyn_any(any);
                 d2 = factory.create_dyn_any_from_type_code(tc);
                 d2.assign(d1);
-                TEST("assign() should not have succeeded" == null);
+                assertTrue("assign() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 d1.destroy();
@@ -1087,7 +1091,7 @@
                 any.insert_fixed(f, orb.create_fixed_tc((short) 4, (short) 2));
                 d1 = factory.create_dyn_any_from_type_code(tc);
                 d1.from_any(any);
-                TEST("from_any() should not have succeeded" == null);
+                assertTrue("from_any() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 d1.destroy();
@@ -1095,11 +1099,11 @@
 
             testOps(orb, factory, tc, false);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -1118,33 +1122,33 @@
             //
             d1 = factory.create_dyn_any_from_type_code(type);
             e1 = DynEnumHelper.narrow(d1);
-            TEST(e1.get_as_ulong() == 0);
+            assertTrue(e1.get_as_ulong() == 0);
             str = e1.get_as_string();
-            TEST(str.equals("red"));
+            assertTrue(str.equals("red"));
 
             //
             // Test: set_as_string()
             //
             e1.set_as_string("green");
-            TEST(e1.get_as_ulong() == 1);
+            assertTrue(e1.get_as_ulong() == 1);
             str = e1.get_as_string();
-            TEST(str.equals("green"));
+            assertTrue(str.equals("green"));
             e1.set_as_string("blue");
-            TEST(e1.get_as_ulong() == 2);
+            assertTrue(e1.get_as_ulong() == 2);
             str = e1.get_as_string();
-            TEST(str.equals("blue"));
+            assertTrue(str.equals("blue"));
 
             //
             // Test: set_as_ulong()
             //
             e1.set_as_ulong(1);
-            TEST(e1.get_as_ulong() == 1);
+            assertTrue(e1.get_as_ulong() == 1);
             str = e1.get_as_string();
-            TEST(str.equals("green"));
+            assertTrue(str.equals("green"));
             e1.set_as_ulong(2);
-            TEST(e1.get_as_ulong() == 2);
+            assertTrue(e1.get_as_ulong() == 2);
             str = e1.get_as_string();
-            TEST(str.equals("blue"));
+            assertTrue(str.equals("blue"));
 
             //
             // Test: from_any()
@@ -1158,13 +1162,13 @@
             //
             av = e1.to_any();
             e = test.types.DynAnyTypes.TestEnumHelper.extract(av);
-            TEST(e == test.types.DynAnyTypes.TestEnum.green);
+            assertTrue(e == test.types.DynAnyTypes.TestEnum.green);
 
             //
             // Test: copy
             //
             copy = e1.copy();
-            TEST(e1.equal(copy));
+            assertTrue(e1.equal(copy));
 
             e1.destroy();
             copy.destroy();
@@ -1176,7 +1180,7 @@
                 d1 = factory.create_dyn_any_from_type_code(type);
                 e1 = DynEnumHelper.narrow(d1);
                 e1.set_as_ulong(3);
-                TEST("set_as_ulong() should not have succeeded" == null);
+                assertTrue("set_as_ulong() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
                 d1.destroy();
@@ -1189,7 +1193,7 @@
                 // additional test case not required for C++.
                 //
                 e1.set_as_ulong(-1);
-                TEST("set_as_ulong() should not have succeeded" == null);
+                assertTrue("set_as_ulong() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
                 d1.destroy();
@@ -1202,7 +1206,7 @@
                 d1 = factory.create_dyn_any_from_type_code(type);
                 e1 = DynEnumHelper.narrow(d1);
                 e1.set_as_string("alizarin");
-                TEST("set_as_string() should not have succeeded" == null);
+                assertTrue("set_as_string() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
                 d1.destroy();
@@ -1210,11 +1214,11 @@
 
             testOps(orb, factory, TestEnumHelper.type(), false);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -1281,23 +1285,23 @@
     }
 
     static void checkStruct(final TestStruct ts) {
-        TEST(ts.shortVal == SHORT_VALUE);
-        TEST(ts.ushortVal == USHORT_VALUE);
-        TEST(ts.longVal == LONG_VALUE);
-        TEST(ts.ulongVal == ULONG_VALUE);
-        TEST(ts.floatVal == FLOAT_VALUE);
-        TEST(ts.doubleVal == DOUBLE_VALUE);
-        TEST(ts.boolVal == BOOLEAN_VALUE);
-        TEST(ts.charVal == CHAR_VALUE);
-        TEST(ts.octetVal == OCTET_VALUE);
-        TEST(ts.anyVal.extract_string().equals(ANY_VALUE));
-        TEST(ts.tcVal.equal(TYPECODE_VALUE));
-        TEST(ts.objectVal == null);
-        TEST(ts.stringVal.equals(STRING_VALUE));
-        TEST(ts.longlongVal == LONGLONG_VALUE);
-        TEST(ts.ulonglongVal == ULONGLONG_VALUE);
-        TEST(ts.wcharVal == WCHAR_VALUE);
-        TEST(ts.wstringVal.equals(WSTRING_VALUE));
+        assertTrue(ts.shortVal == SHORT_VALUE);
+        assertTrue(ts.ushortVal == USHORT_VALUE);
+        assertTrue(ts.longVal == LONG_VALUE);
+        assertTrue(ts.ulongVal == ULONG_VALUE);
+        assertTrue(ts.floatVal == FLOAT_VALUE);
+        assertTrue(ts.doubleVal == DOUBLE_VALUE);
+        assertTrue(ts.boolVal == BOOLEAN_VALUE);
+        assertTrue(ts.charVal == CHAR_VALUE);
+        assertTrue(ts.octetVal == OCTET_VALUE);
+        assertTrue(ts.anyVal.extract_string().equals(ANY_VALUE));
+        assertTrue(ts.tcVal.equal(TYPECODE_VALUE));
+        assertTrue(ts.objectVal == null);
+        assertTrue(ts.stringVal.equals(STRING_VALUE));
+        assertTrue(ts.longlongVal == LONGLONG_VALUE);
+        assertTrue(ts.ulonglongVal == ULONGLONG_VALUE);
+        assertTrue(ts.wcharVal == WCHAR_VALUE);
+        assertTrue(ts.wstringVal.equals(WSTRING_VALUE));
     }
 
     static void testStruct(ORB orb, DynAnyFactory factory) {
@@ -1324,72 +1328,72 @@
             // Test: current_member_name, current_member_kind
             //
             str = s1.current_member_name();
-            TEST(str.equals("shortVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_short);
+            assertTrue(str.equals("shortVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_short);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("ushortVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_ushort);
+            assertTrue(str.equals("ushortVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_ushort);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("longVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_long);
+            assertTrue(str.equals("longVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_long);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("ulongVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_ulong);
+            assertTrue(str.equals("ulongVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_ulong);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("floatVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_float);
+            assertTrue(str.equals("floatVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_float);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("doubleVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_double);
+            assertTrue(str.equals("doubleVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_double);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("boolVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_boolean);
+            assertTrue(str.equals("boolVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_boolean);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("charVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_char);
+            assertTrue(str.equals("charVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_char);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("octetVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_octet);
+            assertTrue(str.equals("octetVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_octet);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("anyVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_any);
+            assertTrue(str.equals("anyVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_any);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("tcVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_TypeCode);
+            assertTrue(str.equals("tcVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_TypeCode);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("objectVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_objref);
+            assertTrue(str.equals("objectVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_objref);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("stringVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_string);
+            assertTrue(str.equals("stringVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_string);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("longlongVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_longlong);
+            assertTrue(str.equals("longlongVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_longlong);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("ulonglongVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_ulonglong);
+            assertTrue(str.equals("ulonglongVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_ulonglong);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("wcharVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_wchar);
+            assertTrue(str.equals("wcharVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_wchar);
             s1.next();
             str = s1.current_member_name();
-            TEST(str.equals("wstringVal"));
-            TEST(s1.current_member_kind() == TCKind.tk_wstring);
+            assertTrue(str.equals("wstringVal"));
+            assertTrue(s1.current_member_kind() == TCKind.tk_wstring);
 
             //
             // Test: insert values into members
@@ -1435,44 +1439,44 @@
             // Test: get values from members
             //
             s1.rewind();
-            TEST(s1.get_short() == SHORT_VALUE);
+            assertTrue(s1.get_short() == SHORT_VALUE);
             s1.next();
-            TEST(s1.get_ushort() == USHORT_VALUE);
+            assertTrue(s1.get_ushort() == USHORT_VALUE);
             s1.next();
-            TEST(s1.get_long() == LONG_VALUE);
+            assertTrue(s1.get_long() == LONG_VALUE);
             s1.next();
-            TEST(s1.get_ulong() == ULONG_VALUE);
+            assertTrue(s1.get_ulong() == ULONG_VALUE);
             s1.next();
-            TEST(s1.get_float() == FLOAT_VALUE);
+            assertTrue(s1.get_float() == FLOAT_VALUE);
             s1.next();
-            TEST(s1.get_double() == DOUBLE_VALUE);
+            assertTrue(s1.get_double() == DOUBLE_VALUE);
             s1.next();
-            TEST(s1.get_boolean() == BOOLEAN_VALUE);
+            assertTrue(s1.get_boolean() == BOOLEAN_VALUE);
             s1.next();
-            TEST(s1.get_char() == CHAR_VALUE);
+            assertTrue(s1.get_char() == CHAR_VALUE);
             s1.next();
-            TEST(s1.get_octet() == OCTET_VALUE);
+            assertTrue(s1.get_octet() == OCTET_VALUE);
             s1.next();
             av = s1.get_any();
             s1.next();
-            TEST(av.extract_string().equals(ANY_VALUE));
+            assertTrue(av.extract_string().equals(ANY_VALUE));
             tc = s1.get_typecode();
             s1.next();
-            TEST(tc.equal(TYPECODE_VALUE));
-            TEST(s1.get_reference() == null);
+            assertTrue(tc.equal(TYPECODE_VALUE));
+            assertTrue(s1.get_reference() == null);
             s1.next();
             str = s1.get_string();
             s1.next();
-            TEST(str.equals(STRING_VALUE));
-            TEST(s1.get_longlong() == LONGLONG_VALUE);
+            assertTrue(str.equals(STRING_VALUE));
+            assertTrue(s1.get_longlong() == LONGLONG_VALUE);
             s1.next();
-            TEST(s1.get_ulonglong() == ULONGLONG_VALUE);
+            assertTrue(s1.get_ulonglong() == ULONGLONG_VALUE);
             s1.next();
-            TEST(s1.get_wchar() == WCHAR_VALUE);
+            assertTrue(s1.get_wchar() == WCHAR_VALUE);
             s1.next();
             wstr = s1.get_wstring();
             s1.next();
-            TEST(wstr.equals(WSTRING_VALUE));
+            assertTrue(wstr.equals(WSTRING_VALUE));
 
             //
             // Initialize struct
@@ -1484,7 +1488,7 @@
             //
             TestStructHelper.insert(any, ts);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
 
             //
@@ -1503,7 +1507,7 @@
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             copy.destroy();
 
             //
@@ -1513,10 +1517,10 @@
             s1.rewind();
             for (i = 0; i < nvpseq.length; i++) {
                 str = s1.current_member_name();
-                TEST(str.equals(nvpseq[i].id));
+                assertTrue(str.equals(nvpseq[i].id));
                 DynAny dv = factory.create_dyn_any(nvpseq[i].value);
                 DynAny comp = s1.current_component();
-                TEST(dv.equal(comp));
+                assertTrue(dv.equal(comp));
                 dv.destroy();
                 s1.next();
             }
@@ -1527,10 +1531,10 @@
             s1.set_members(nvpseq);
             d2 = s1.current_component();
             tc = d2.type();
-            TEST(tc.kind() == TCKind.tk_short); // ensure index is reset to 0
+            assertTrue(tc.kind() == TCKind.tk_short); // ensure index is reset to 0
             TestStructHelper.insert(any, ts);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
 
             //
@@ -1540,7 +1544,7 @@
                 str = nvpseq[2].id;
                 nvpseq[2].id = "totally_wrong";
                 s1.set_members(nvpseq);
-                TEST("set_members should not have succeeded" == null);
+                assertTrue("set_members should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 nvpseq[2].id = str; // restore value
@@ -1553,7 +1557,7 @@
                 any = nvpseq[2].value;
                 nvpseq[2].value.insert_string("this is not a long");
                 s1.set_members(nvpseq);
-                TEST("set_members should not have succeeded" == null);
+                assertTrue("set_members should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 nvpseq[2].value = any; // restore value
@@ -1565,7 +1569,7 @@
             try {
                 nvpseq = new NameValuePair[0];
                 s1.set_members(nvpseq);
-                TEST("set_members should not have succeeded" == null);
+                assertTrue("set_members should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -1577,7 +1581,7 @@
             s1.rewind();
             for (i = 0; i < ndpseq.length; i++) {
                 str = s1.current_member_name();
-                TEST(str.equals(ndpseq[i].id));
+                assertTrue(str.equals(ndpseq[i].id));
                 s1.next();
             }
 
@@ -1587,10 +1591,10 @@
             s1.set_members_as_dyn_any(ndpseq);
             d2 = s1.current_component();
             tc = d2.type();
-            TEST(tc.kind() == TCKind.tk_short); // ensure index is reset to 0
+            assertTrue(tc.kind() == TCKind.tk_short); // ensure index is reset to 0
             TestStructHelper.insert(any, ts);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
 
             //
@@ -1600,7 +1604,7 @@
                 str = ndpseq[2].id;
                 ndpseq[2].id = "totally_wrong";
                 s1.set_members_as_dyn_any(ndpseq);
-                TEST("set_members_as_dyn_any should not have succeeded" == null);
+                assertTrue("set_members_as_dyn_any should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 ndpseq[2].id = str; // restore value
@@ -1614,7 +1618,7 @@
                 any.insert_boolean(false);
                 ndpseq[2].value = factory.create_dyn_any(any);
                 s1.set_members_as_dyn_any(ndpseq);
-                TEST("set_members_as_dyn_any should not have succeeded" == null);
+                assertTrue("set_members_as_dyn_any should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 ndpseq[2].value.destroy();
@@ -1627,7 +1631,7 @@
             try {
                 ndpseq = new NameDynAnyPair[0];
                 s1.set_members_as_dyn_any(ndpseq);
-                TEST("set_members_as_dyn_any should not have succeeded" == null);
+                assertTrue("set_members_as_dyn_any should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -1645,22 +1649,22 @@
             TestEmptyException ex = new TestEmptyException();
             TestEmptyExceptionHelper.insert(any, ex);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d1.assign(d2);
             d1.from_any(any);
             nvpseq = s1.get_members();
-            TEST(nvpseq.length == 0);
+            assertTrue(nvpseq.length == 0);
             s1.set_members(nvpseq);
             d1.destroy();
             d2.destroy();
 
             testOps(orb, factory, type, false);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -1683,11 +1687,11 @@
             TestEmptyException ex = new TestEmptyException();
             TestEmptyExceptionHelper.insert(any, ex);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d1.assign(d2);
             d1.from_any(any);
             nvpseq = s1.get_members();
-            TEST(nvpseq.length == 0);
+            assertTrue(nvpseq.length == 0);
             s1.set_members(nvpseq);
             d1.destroy();
             d2.destroy();
@@ -1710,25 +1714,25 @@
                     1, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
             org.omg.CORBA.OBJECT_NOT_EXISTHelper.insert(any, one);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d1.assign(d2);
             d1.from_any(any);
             nvpseq = s1.get_members();
-            TEST(nvpseq.length == 2);
+            assertTrue(nvpseq.length == 2);
             av = d1.to_any();
             one = org.omg.CORBA.OBJECT_NOT_EXISTHelper.extract(av);
-            TEST(one.minor == 1);
-            TEST(one.completed == org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
+            assertTrue(one.minor == 1);
+            assertTrue(one.completed == org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
             d1.destroy();
             d2.destroy();
 
             testOps(orb, factory, type, true);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -1751,13 +1755,13 @@
             discType = orb.get_primitive_tc(TCKind.tk_short);
             d1 = factory.create_dyn_any_from_type_code(type);
             u1 = DynUnionHelper.narrow(d1);
-            TEST(u1.discriminator_kind() == TCKind.tk_short);
+            assertTrue(u1.discriminator_kind() == TCKind.tk_short);
             str = u1.member_name();
-            TEST(str.equals("a"));
-            TEST(u1.member_kind() == TCKind.tk_long);
+            assertTrue(str.equals("a"));
+            assertTrue(u1.member_kind() == TCKind.tk_long);
             disc = u1.get_discriminator();
-            TEST(disc.get_short() == (short) 0);
-            TEST(u1.component_count() == 2);
+            assertTrue(disc.get_short() == (short) 0);
+            assertTrue(u1.component_count() == 2);
 
             //
             // Test: set_discriminator() - ensure member is not deactivated
@@ -1769,14 +1773,14 @@
             disc.insert_short((short) 1); // change disc to 1
             u1.set_discriminator(disc);
             str = u1.member_name();
-            TEST(str.equals("a"));
-            TEST(u1.member_kind() == TCKind.tk_long);
-            TEST(u1.get_long() == 55); // also tests current position
+            assertTrue(str.equals("a"));
+            assertTrue(u1.member_kind() == TCKind.tk_long);
+            assertTrue(u1.get_long() == 55); // also tests current position
             disc.destroy();
             disc = u1.get_discriminator();
-            TEST(disc.get_short() == (short) 1);
+            assertTrue(disc.get_short() == (short) 1);
             u1.rewind();
-            TEST(u1.get_short() == (short) 1);
+            assertTrue(u1.get_short() == (short) 1);
 
             //
             // Test: set_discriminator() - ensure member is deactivated when
@@ -1786,15 +1790,15 @@
             disc.insert_short((short) 3); // change disc to 3
             u1.set_discriminator(disc);
             str = u1.member_name();
-            TEST(str.equals("b"));
-            TEST(u1.member_kind() == TCKind.tk_float);
-            TEST(u1.get_float() == (float) 0);
+            assertTrue(str.equals("b"));
+            assertTrue(u1.member_kind() == TCKind.tk_float);
+            assertTrue(u1.get_float() == (float) 0);
             u1.insert_float(99.99f);
             disc.destroy();
             disc = u1.get_discriminator();
-            TEST(disc.get_short() == (short) 3);
+            assertTrue(disc.get_short() == (short) 3);
             u1.rewind();
-            TEST(u1.get_short() == (short) 3);
+            assertTrue(u1.get_short() == (short) 3);
 
             //
             // Test: set_discriminator() - use discriminator value that
@@ -1804,18 +1808,18 @@
             disc.insert_short((short) 9); // change disc to 9
             u1.set_discriminator(disc);
             str = u1.member_name();
-            TEST(str.equals("c"));
-            TEST(u1.member_kind() == TCKind.tk_string);
+            assertTrue(str.equals("c"));
+            assertTrue(u1.member_kind() == TCKind.tk_string);
             str = u1.get_string();
-            TEST(str.length() == 0);
+            assertTrue(str.length() == 0);
             u1.insert_string("hi there");
             disc.insert_short((short) 23); // change disc again - still
             // default member
             u1.set_discriminator(disc);
             str = u1.member_name();
-            TEST(str.equals("c"));
+            assertTrue(str.equals("c"));
             str = u1.get_string();
-            TEST(str.equals("hi there"));
+            assertTrue(str.equals("hi there"));
             disc.destroy();
 
             //
@@ -1826,7 +1830,7 @@
             disc.insert_ushort((short) 55);
             try {
                 u1.set_discriminator(disc);
-                TEST("set_discriminator() should not have succeeded" == null);
+                assertTrue("set_discriminator() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -1838,10 +1842,10 @@
             //
             u1.set_to_default_member();
             str = u1.member_name();
-            TEST(str.equals("c"));
+            assertTrue(str.equals("c"));
             u1.next();
             str = u1.get_string();
-            TEST(str.equals("hi there"));
+            assertTrue(str.equals("hi there"));
 
             //
             // Test: set_to_default_member() - force a new member to be
@@ -1853,8 +1857,8 @@
             disc.destroy();
             u1.set_to_default_member();
             str = u1.member_name();
-            TEST(str.equals("c"));
-            TEST(u1.component_count() == 2);
+            assertTrue(str.equals("c"));
+            assertTrue(u1.component_count() == 2);
 
             //
             // Test: is_set_to_default_member()
@@ -1862,38 +1866,38 @@
             disc = factory.create_dyn_any_from_type_code(discType);
             disc.insert_short((short) 0);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 1);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 3);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 2);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == true);
+            assertTrue(u1.is_set_to_default_member() == true);
             disc.destroy();
             disc = u1.get_discriminator();
             disc.insert_short((short) 0);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 1);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 3);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 2);
-            TEST(u1.is_set_to_default_member() == true);
+            assertTrue(u1.is_set_to_default_member() == true);
 
             //
             // Test: has_no_active_member()
             //
-            TEST(u1.has_no_active_member() == false);
+            assertTrue(u1.has_no_active_member() == false);
 
             //
             // Test: set_to_no_active_member() TypeMismatch exception
             //
             try {
                 u1.set_to_no_active_member();
-                TEST("set_to_no_active_member() should not have succeeded" == null);
+                assertTrue("set_to_no_active_member() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -1907,10 +1911,10 @@
             disc = u1.current_component();
             disc.insert_short((short) 0);
             str = u1.member_name();
-            TEST(str.equals("a"));
+            assertTrue(str.equals("a"));
             u1.insert_long(55);
             disc.insert_short((short) 1);
-            TEST(u1.get_long() == 55);
+            assertTrue(u1.get_long() == 55);
 
             //
             // Test: to_any
@@ -1922,8 +1926,8 @@
             u1.insert_long(49);
             av = u1.to_any();
             ptu1 = test.types.DynAnyTypes.TestUnion1Helper.extract(av);
-            TEST(ptu1.discriminator() == (short) 1);
-            TEST(ptu1.a() == 49);
+            assertTrue(ptu1.discriminator() == (short) 1);
+            assertTrue(ptu1.a() == 49);
 
             //
             // Test: assign
@@ -1932,30 +1936,30 @@
             test.types.DynAnyTypes.TestUnion1Helper.insert(any, tu1);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             str = u1.member_name();
-            TEST(str.equals("c"));
+            assertTrue(str.equals("c"));
             u1.seek(1);
             str = u1.get_string();
-            TEST(str.equals("hi there"));
+            assertTrue(str.equals("hi there"));
             d2.destroy();
 
             //
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             copy.destroy();
 
             d1.destroy();
 
             testOps(orb, factory, type, true);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -1978,13 +1982,13 @@
             discType = orb.get_primitive_tc(TCKind.tk_boolean);
             d1 = factory.create_dyn_any_from_type_code(type);
             u1 = DynUnionHelper.narrow(d1);
-            TEST(u1.discriminator_kind() == TCKind.tk_boolean);
+            assertTrue(u1.discriminator_kind() == TCKind.tk_boolean);
             str = u1.member_name();
-            TEST(str.equals("a"));
-            TEST(u1.member_kind() == TCKind.tk_long);
+            assertTrue(str.equals("a"));
+            assertTrue(u1.member_kind() == TCKind.tk_long);
             disc = u1.get_discriminator();
-            TEST(disc.get_boolean() == true);
-            TEST(u1.component_count() == 2);
+            assertTrue(disc.get_boolean() == true);
+            assertTrue(u1.component_count() == 2);
 
             //
             // Test: set_discriminator() - sets union to have no active member
@@ -1992,31 +1996,31 @@
             disc = factory.create_dyn_any_from_type_code(discType);
             disc.insert_boolean(false);
             u1.set_discriminator(disc);
-            TEST(u1.component_count() == 1);
+            assertTrue(u1.component_count() == 1);
             disc.destroy();
 
             //
             // Test: seek - with no active member, 0 is only valid position
             //
-            TEST(!u1.seek(1));
+            assertTrue(!u1.seek(1));
 
             //
             // Test: next - with no active member, 0 is only valid position
             //
             u1.rewind();
-            TEST(!u1.next());
+            assertTrue(!u1.next());
 
             //
             // Test: copy
             //
             copy = u1.copy();
-            TEST(u1.equal(copy));
+            assertTrue(u1.equal(copy));
             copy.destroy();
 
             //
             // Test: has_no_active_member()
             //
-            TEST(u1.has_no_active_member());
+            assertTrue(u1.has_no_active_member());
 
             //
             // Test: set_discriminator() TypeMismatch exception
@@ -2026,7 +2030,7 @@
             disc.insert_ushort((short) 55);
             try {
                 u1.set_discriminator(disc);
-                TEST("set_discriminator() should not have succeeded" == null);
+                assertTrue("set_discriminator() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2037,7 +2041,7 @@
             //
             try {
                 u1.set_to_default_member();
-                TEST("set_to_default_member() should not have succeeded" == null);
+                assertTrue("set_to_default_member() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2048,23 +2052,23 @@
             disc = factory.create_dyn_any_from_type_code(discType);
             disc.insert_boolean(true);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_boolean(false);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.destroy();
             disc = u1.get_discriminator();
             disc.insert_boolean(true);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_boolean(false);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
 
             //
             // Test: member() InvalidValue exception
             //
             try {
                 member = u1.member();
-                TEST("member() should not have succeeded" == null);
+                assertTrue("member() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -2074,7 +2078,7 @@
             //
             try {
                 str = u1.member_name();
-                TEST("member_name() should not have succeeded" == null);
+                assertTrue("member_name() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -2084,7 +2088,7 @@
             //
             try {
                 u1.member_kind();
-                TEST("member_kind() should not have succeeded" == null);
+                assertTrue("member_kind() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -2097,9 +2101,9 @@
             u1.set_discriminator(disc);
             disc.destroy();
             u1.insert_long(49);
-            TEST(!u1.has_no_active_member());
+            assertTrue(!u1.has_no_active_member());
             u1.set_to_no_active_member();
-            TEST(u1.has_no_active_member());
+            assertTrue(u1.has_no_active_member());
 
             //
             // Test: change discriminator by manipulating the components
@@ -2107,12 +2111,12 @@
             //
             u1.set_to_no_active_member();
             disc = u1.current_component();
-            TEST(disc.get_boolean() == false);
+            assertTrue(disc.get_boolean() == false);
             disc.insert_boolean(true);
             str = u1.member_name();
-            TEST(str.equals("a"));
+            assertTrue(str.equals("a"));
             u1.insert_long(55);
-            TEST(u1.get_long() == 55);
+            assertTrue(u1.get_long() == 55);
 
             //
             // Test: to_any
@@ -2124,8 +2128,8 @@
             u1.insert_long(49);
             av = u1.to_any();
             ptu2 = test.types.DynAnyTypes.TestUnion2Helper.extract(av);
-            TEST(ptu2.discriminator() == true);
-            TEST(ptu2.a() == 49);
+            assertTrue(ptu2.discriminator() == true);
+            assertTrue(ptu2.a() == 49);
 
             //
             // Test: assign
@@ -2134,29 +2138,29 @@
             test.types.DynAnyTypes.TestUnion2Helper.insert(any, tu2);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             str = u1.member_name();
-            TEST(str.equals("a"));
+            assertTrue(str.equals("a"));
             u1.seek(1);
-            TEST(u1.get_long() == 199);
+            assertTrue(u1.get_long() == 199);
             d2.destroy();
 
             //
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             copy.destroy();
 
             d1.destroy();
 
             testOps(orb, factory, type, true);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -2180,14 +2184,14 @@
             discType = test.types.DynAnyTypes.TestEnumHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             u1 = DynUnionHelper.narrow(d1);
-            TEST(u1.discriminator_kind() == TCKind.tk_enum);
+            assertTrue(u1.discriminator_kind() == TCKind.tk_enum);
             str = u1.member_name();
-            TEST(str.equals("a"));
-            TEST(u1.member_kind() == TCKind.tk_long);
+            assertTrue(str.equals("a"));
+            assertTrue(u1.member_kind() == TCKind.tk_long);
             disc = u1.get_discriminator();
             e = DynEnumHelper.narrow(disc);
-            TEST(e.get_as_ulong() == 0);
-            TEST(u1.component_count() == 2);
+            assertTrue(e.get_as_ulong() == 0);
+            assertTrue(u1.component_count() == 2);
 
             //
             // Test: set_discriminator()
@@ -2197,9 +2201,9 @@
             e.set_as_string("green");
             u1.set_discriminator(disc);
             str = u1.member_name();
-            TEST(str.equals("b"));
-            TEST(u1.member_kind() == TCKind.tk_double);
-            TEST(u1.component_count() == 2);
+            assertTrue(str.equals("b"));
+            assertTrue(u1.member_kind() == TCKind.tk_double);
+            assertTrue(u1.component_count() == 2);
 
             //
             // Test: change discriminator by manipulating the components
@@ -2208,22 +2212,22 @@
             e.set_as_string("blue");
             u1.set_discriminator(disc);
             str = u1.member_name();
-            TEST(str.equals("c"));
-            TEST(u1.member_kind() == TCKind.tk_char);
-            TEST(u1.component_count() == 2);
+            assertTrue(str.equals("c"));
+            assertTrue(u1.member_kind() == TCKind.tk_char);
+            assertTrue(u1.component_count() == 2);
             disc.destroy();
 
             //
             // Test: copy
             //
             copy = u1.copy();
-            TEST(u1.equal(copy));
+            assertTrue(u1.equal(copy));
             copy.destroy();
 
             //
             // Test: has_no_active_member()
             //
-            TEST(!u1.has_no_active_member());
+            assertTrue(!u1.has_no_active_member());
 
             //
             // Test: set_discriminator() TypeMismatch exception
@@ -2233,7 +2237,7 @@
             disc.insert_ushort((short) 55);
             try {
                 u1.set_discriminator(disc);
-                TEST("set_discriminator() should not have succeeded" == null);
+                assertTrue("set_discriminator() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2244,7 +2248,7 @@
             //
             try {
                 u1.set_to_default_member();
-                TEST("set_to_default_member() should not have succeeded" == null);
+                assertTrue("set_to_default_member() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2256,29 +2260,29 @@
             e = DynEnumHelper.narrow(disc);
             e.set_as_string("red");
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             e.set_as_string("green");
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             e.set_as_string("blue");
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.destroy();
             disc = u1.get_discriminator();
             e = DynEnumHelper.narrow(disc);
             e.set_as_string("red");
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             e.set_as_string("green");
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             e.set_as_string("blue");
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
 
             //
             // Test: set_to_no_active_member() exception
             //
             try {
                 u1.set_to_no_active_member();
-                TEST("set_to_no_active_member() should not have succeeded" == null);
+                assertTrue("set_to_no_active_member() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2292,8 +2296,8 @@
             u1.insert_char('Z');
             av = u1.to_any();
             ptu3 = test.types.DynAnyTypes.TestUnion3Helper.extract(av);
-            TEST(ptu3.discriminator() == test.types.DynAnyTypes.TestEnum.blue);
-            TEST(ptu3.c() == 'Z');
+            assertTrue(ptu3.discriminator() == test.types.DynAnyTypes.TestEnum.blue);
+            assertTrue(ptu3.c() == 'Z');
 
             //
             // Test: assign
@@ -2302,22 +2306,22 @@
             test.types.DynAnyTypes.TestUnion3Helper.insert(any, tu3);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             str = u1.member_name();
-            TEST(str.equals("b"));
+            assertTrue(str.equals("b"));
             u1.seek(1);
-            TEST(u1.get_double() >= 1.99);
+            assertTrue(u1.get_double() >= 1.99);
             d2.destroy();
 
             d1.destroy();
 
             testOps(orb, factory, type, true);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -2341,12 +2345,12 @@
             discType = orb.get_primitive_tc(TCKind.tk_short);
             d1 = factory.create_dyn_any_from_type_code(type);
             u1 = DynUnionHelper.narrow(d1);
-            TEST(u1.discriminator_kind() == TCKind.tk_short);
+            assertTrue(u1.discriminator_kind() == TCKind.tk_short);
             str = u1.member_name();
-            TEST(str.equals("a"));
-            TEST(u1.member_kind() == TCKind.tk_long);
+            assertTrue(str.equals("a"));
+            assertTrue(u1.member_kind() == TCKind.tk_long);
             disc = u1.get_discriminator();
-            TEST(u1.component_count() == 2);
+            assertTrue(u1.component_count() == 2);
 
             //
             // Test: set_discriminator()
@@ -2355,9 +2359,9 @@
             disc.insert_short((short) 99);
             u1.set_discriminator(disc);
             str = u1.member_name();
-            TEST(str.equals("b"));
-            TEST(u1.member_kind() == TCKind.tk_float);
-            TEST(u1.component_count() == 2);
+            assertTrue(str.equals("b"));
+            assertTrue(u1.member_kind() == TCKind.tk_float);
+            assertTrue(u1.component_count() == 2);
             disc.destroy();
 
             //
@@ -2367,24 +2371,24 @@
             disc = u1.get_discriminator();
             disc.insert_short((short) 33);
             str = u1.member_name();
-            TEST(str.equals("a"));
-            TEST(u1.member_kind() == TCKind.tk_long);
-            TEST(u1.component_count() == 2);
+            assertTrue(str.equals("a"));
+            assertTrue(u1.member_kind() == TCKind.tk_long);
+            assertTrue(u1.component_count() == 2);
             u1.insert_long(444);
             disc.insert_short((short) 66);
-            TEST(u1.get_long() == 444);
+            assertTrue(u1.get_long() == 444);
 
             //
             // Test: copy
             //
             copy = u1.copy();
-            TEST(u1.equal(copy));
+            assertTrue(u1.equal(copy));
             copy.destroy();
 
             //
             // Test: has_no_active_member()
             //
-            TEST(!u1.has_no_active_member());
+            assertTrue(!u1.has_no_active_member());
 
             //
             // Test: set_discriminator() TypeMismatch exception
@@ -2394,7 +2398,7 @@
             disc.insert_ushort((short) 55);
             try {
                 u1.set_discriminator(disc);
-                TEST("set_discriminator() should not have succeeded" == null);
+                assertTrue("set_discriminator() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2407,7 +2411,7 @@
             disc.insert_short((short) 99); // select "b"
             u1.set_to_default_member();
             str = u1.member_name();
-            TEST(str.equals("a"));
+            assertTrue(str.equals("a"));
 
             //
             // Test: is_set_to_default_member()
@@ -2415,23 +2419,23 @@
             disc = factory.create_dyn_any_from_type_code(discType);
             disc.insert_short((short) 99);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 0);
             u1.set_discriminator(disc);
-            TEST(u1.is_set_to_default_member() == true);
+            assertTrue(u1.is_set_to_default_member() == true);
             disc.destroy();
             disc = u1.get_discriminator();
             disc.insert_short((short) 99);
-            TEST(u1.is_set_to_default_member() == false);
+            assertTrue(u1.is_set_to_default_member() == false);
             disc.insert_short((short) 0);
-            TEST(u1.is_set_to_default_member() == true);
+            assertTrue(u1.is_set_to_default_member() == true);
 
             //
             // Test: set_to_no_active_member() exception
             //
             try {
                 u1.set_to_no_active_member();
-                TEST("set_to_no_active_member() should not have succeeded" == null);
+                assertTrue("set_to_no_active_member() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2444,7 +2448,7 @@
             u1.insert_long(888);
             av = u1.to_any();
             ptu4 = test.types.DynAnyTypes.TestUnion4Helper.extract(av);
-            TEST(ptu4.a() == 888);
+            assertTrue(ptu4.a() == 888);
 
             //
             // Test: assign
@@ -2453,22 +2457,22 @@
             test.types.DynAnyTypes.TestUnion4Helper.insert(any, tu4);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             str = u1.member_name();
-            TEST(str.equals("b"));
+            assertTrue(str.equals("b"));
             u1.seek(1);
-            TEST(u1.get_float() >= 1.99f);
+            assertTrue(u1.get_float() >= 1.99f);
             d2.destroy();
 
             d1.destroy();
 
             testOps(orb, factory, type, true);
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -2490,22 +2494,22 @@
             type = TestShortSeqHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             s1 = DynSequenceHelper.narrow(d1);
-            TEST(s1.get_length() == 0);
-            TEST(s1.component_count() == 0);
+            assertTrue(s1.get_length() == 0);
+            assertTrue(s1.component_count() == 0);
 
             //
             // Test: set_length() - increase length - position should be 0
             //
             s1.set_length(5);
-            TEST(s1.get_length() == 5);
-            TEST(s1.component_count() == 5);
+            assertTrue(s1.get_length() == 5);
+            assertTrue(s1.component_count() == 5);
             for (i = 0; i < 5; i++) {
                 s1.insert_short((short) i);
                 s1.next();
             }
             s1.rewind();
             for (i = 0; i < 5; i++) {
-                TEST(s1.get_short() == (short) i);
+                assertTrue(s1.get_short() == (short) i);
                 s1.next();
             }
 
@@ -2514,12 +2518,12 @@
             //
             s1.seek(1);
             s1.set_length(3);
-            TEST(s1.get_short() == (short) 1);
-            TEST(s1.get_length() == 3);
-            TEST(s1.component_count() == 3);
+            assertTrue(s1.get_short() == (short) 1);
+            assertTrue(s1.get_length() == 3);
+            assertTrue(s1.component_count() == 3);
             s1.rewind();
             for (i = 0; i < 3; i++) {
-                TEST(s1.get_short() == (short) i);
+                assertTrue(s1.get_short() == (short) i);
                 s1.next();
             }
 
@@ -2528,15 +2532,15 @@
             //
             av = s1.to_any();
             pseq = TestShortSeqHelper.extract(av);
-            TEST(pseq.length == 3);
+            assertTrue(pseq.length == 3);
             for (i = 0; i < 3; i++)
-                TEST(pseq[i] == (short) i);
+				assertTrue(pseq[i] == (short) i);
 
             //
             // Test: copy
             //
             copy = s1.copy();
-            TEST(s1.equal(copy));
+            assertTrue(s1.equal(copy));
             copy.destroy();
 
             //
@@ -2545,7 +2549,7 @@
             copy = s1.copy();
             copy.seek(1);
             copy.insert_short((short) -33);
-            TEST(!s1.equal(copy));
+            assertTrue(!s1.equal(copy));
             copy.destroy();
 
             //
@@ -2558,7 +2562,7 @@
             s1.from_any(any);
             s1.rewind();
             for (i = 0; i < 8; i++) {
-                TEST(s1.get_short() == (short) (8 - i));
+                assertTrue(s1.get_short() == (short) (8 - i));
                 s1.next();
             }
 
@@ -2569,9 +2573,9 @@
             s1.rewind();
             for (i = 0; i < 8; i++) {
                 comp = s1.current_component();
-                TEST(comp.get_short() == (short) (8 - i));
+                assertTrue(comp.get_short() == (short) (8 - i));
                 comp.insert_short((short) i);
-                TEST(s1.get_short() == (short) i);
+                assertTrue(s1.get_short() == (short) i);
                 s1.next();
             }
 
@@ -2579,10 +2583,10 @@
             // Test: get_elements()
             //
             Any[] anySeq = s1.get_elements();
-            TEST(anySeq.length == 8);
+            assertTrue(anySeq.length == 8);
             for (i = 0; i < 8; i++) {
                 short n = anySeq[i].extract_short();
-                TEST(n == (short) i);
+                assertTrue(n == (short) i);
             }
 
             //
@@ -2596,7 +2600,7 @@
             s1.set_elements(anySeq);
             s1.rewind();
             for (i = 0; i < 3; i++) {
-                TEST(s1.get_short() == (short) (i + 10));
+                assertTrue(s1.get_short() == (short) (i + 10));
                 s1.next();
             }
 
@@ -2604,9 +2608,9 @@
             // Test: get_elements_as_dyn_any()
             //
             DynAny[] dynAnySeq = s1.get_elements_as_dyn_any();
-            TEST(dynAnySeq.length == 3);
+            assertTrue(dynAnySeq.length == 3);
             for (i = 0; i < 3; i++)
-                TEST(dynAnySeq[i].get_short() == (short) (i + 10));
+				assertTrue(dynAnySeq[i].get_short() == (short) (i + 10));
 
             //
             // Test: set_elements_as_dyn_any
@@ -2619,7 +2623,7 @@
             s1.set_elements_as_dyn_any(dynAnySeq);
             s1.rewind();
             for (i = 0; i < 4; i++) {
-                TEST(s1.get_short() == (short) (i + 100));
+                assertTrue(s1.get_short() == (short) (i + 100));
                 s1.next();
             }
             for (i = 0; i < 4; i++)
@@ -2635,13 +2639,13 @@
             d2 = factory.create_dyn_any(any);
             s2 = DynSequenceHelper.narrow(d2);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(s1.get_length() == 10);
-            TEST(s1.component_count() == 10);
+            assertTrue(s1.get_length() == 10);
+            assertTrue(s1.component_count() == 10);
             s1.rewind();
             for (i = 0; i < 10; i++) {
-                TEST(s1.get_short() == (short) (i * 10));
+                assertTrue(s1.get_short() == (short) (i * 10));
                 s1.next();
             }
 
@@ -2649,25 +2653,25 @@
             // Test: seek
             //
             int count = d1.component_count();
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(count) == false);
-            TEST(d1.seek(count - 1) == true);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(count) == false);
+            assertTrue(d1.seek(count - 1) == true);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(count - 1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -2680,15 +2684,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -2710,18 +2714,18 @@
             type = TestBoundedString10SeqHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             s1 = DynSequenceHelper.narrow(d1);
-            TEST(s1.get_length() == 0);
-            TEST(s1.component_count() == 0);
+            assertTrue(s1.get_length() == 0);
+            assertTrue(s1.component_count() == 0);
 
             //
             // Test: set_length() - increase length - position should be 0
             //
             s1.set_length(5);
-            TEST(s1.get_length() == 5);
-            TEST(s1.component_count() == 5);
+            assertTrue(s1.get_length() == 5);
+            assertTrue(s1.component_count() == 5);
             for (i = 0; i < 5; i++) {
                 str = s1.get_string();
-                TEST(str.length() == 0);
+                assertTrue(str.length() == 0);
                 str += "str ";
                 str += i;
                 s1.insert_string(str);
@@ -2731,7 +2735,7 @@
             for (i = 0; i < 5; i++) {
                 str = s1.get_string();
                 String s = "str " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s1.next();
             }
 
@@ -2742,26 +2746,26 @@
             s1.seek(1);
             s1.set_length(3);
             str = s1.get_string();
-            TEST(str.equals("str 1"));
-            TEST(s1.get_length() == 3);
-            TEST(s1.component_count() == 3);
+            assertTrue(str.equals("str 1"));
+            assertTrue(s1.get_length() == 3);
+            assertTrue(s1.component_count() == 3);
 
             //
             // Test: to_any
             //
             av = s1.to_any();
             pseq = TestBoundedString10SeqHelper.extract(av);
-            TEST(pseq.length == 3);
+            assertTrue(pseq.length == 3);
             for (i = 0; i < 3; i++) {
                 String s = "str " + i;
-                TEST(pseq[i].equals(s));
+                assertTrue(pseq[i].equals(s));
             }
 
             //
             // Test: copy
             //
             copy = s1.copy();
-            TEST(s1.equal(copy));
+            assertTrue(s1.equal(copy));
             copy.destroy();
 
             //
@@ -2770,7 +2774,7 @@
             copy = s1.copy();
             copy.seek(1);
             copy.insert_string("hi there");
-            TEST(!s1.equal(copy));
+            assertTrue(!s1.equal(copy));
             copy.destroy();
 
             //
@@ -2785,7 +2789,7 @@
             for (i = 0; i < 8; i++) {
                 str = s1.get_string();
                 String s = "STR " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s1.next();
             }
 
@@ -2798,11 +2802,11 @@
                 comp = s1.current_component();
                 str = comp.get_string();
                 String s = "STR " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s = "string " + i;
                 comp.insert_string(s);
                 str = s1.get_string();
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s1.next();
             }
 
@@ -2810,11 +2814,11 @@
             // Test: get_elements()
             //
             Any[] anySeq = s1.get_elements();
-            TEST(anySeq.length == 8);
+            assertTrue(anySeq.length == 8);
             for (i = 0; i < 8; i++) {
                 String cp = anySeq[i].extract_string();
                 String s = "string " + i;
-                TEST(cp.equals(s));
+                assertTrue(cp.equals(s));
             }
 
             //
@@ -2831,7 +2835,7 @@
             for (i = 0; i < 3; i++) {
                 str = s1.get_string();
                 String s = "String " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s1.next();
             }
 
@@ -2839,11 +2843,11 @@
             // Test: get_elements_as_dyn_any()
             //
             DynAny[] dynAnySeq = s1.get_elements_as_dyn_any();
-            TEST(dynAnySeq.length == 3);
+            assertTrue(dynAnySeq.length == 3);
             for (i = 0; i < 3; i++) {
                 str = dynAnySeq[i].get_string();
                 String s = "String " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
             }
 
             //
@@ -2860,7 +2864,7 @@
             for (i = 0; i < 4; i++) {
                 str = s1.get_string();
                 String s = "STRING " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s1.next();
             }
             for (i = 0; i < 4; i++)
@@ -2876,15 +2880,15 @@
             d2 = factory.create_dyn_any(any);
             s2 = DynSequenceHelper.narrow(d2);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(s1.get_length() == 10);
-            TEST(s1.component_count() == 10);
+            assertTrue(s1.get_length() == 10);
+            assertTrue(s1.component_count() == 10);
             s1.rewind();
             for (i = 0; i < 10; i++) {
                 str = s1.get_string();
                 String s = "Str " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s1.next();
             }
 
@@ -2894,11 +2898,11 @@
             i = s1.component_count();
             try {
                 s1.set_length(11);
-                TEST("set_length() should not have succeeded" == null);
+                assertTrue("set_length() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
-            TEST(s1.component_count() == i);
+            assertTrue(s1.component_count() == i);
 
             //
             // Test: set_elements() TypeMismatch exception
@@ -2911,7 +2915,7 @@
             }
             try {
                 s1.set_elements(anySeq);
-                TEST("set_elements() should not have succeeded" == null);
+                assertTrue("set_elements() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -2920,25 +2924,25 @@
             // Test: seek
             //
             int count = d1.component_count();
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(count) == false);
-            TEST(d1.seek(count - 1) == true);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(count) == false);
+            assertTrue(d1.seek(count - 1) == true);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(count - 1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -2951,15 +2955,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -2982,15 +2986,15 @@
             type = TestAnySeqHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             s1 = DynSequenceHelper.narrow(d1);
-            TEST(s1.get_length() == 0);
-            TEST(s1.component_count() == 0);
+            assertTrue(s1.get_length() == 0);
+            assertTrue(s1.component_count() == 0);
 
             //
             // Test: set_length() - increase length - position should be 0
             //
             s1.set_length(5);
-            TEST(s1.get_length() == 5);
-            TEST(s1.component_count() == 5);
+            assertTrue(s1.get_length() == 5);
+            assertTrue(s1.component_count() == 5);
             for (i = 0; i < 5; i++) {
                 any.insert_short((short) i);
                 s1.insert_any(any);
@@ -3000,7 +3004,7 @@
             for (i = 0; i < 5; i++) {
                 av = s1.get_any();
                 s = av.extract_short();
-                TEST(s == (short) i);
+                assertTrue(s == (short) i);
                 s1.next();
             }
 
@@ -3012,14 +3016,14 @@
             s1.set_length(3);
             av = s1.get_any();
             s = av.extract_short();
-            TEST(s == (short) 1);
-            TEST(s1.get_length() == 3);
-            TEST(s1.component_count() == 3);
+            assertTrue(s == (short) 1);
+            assertTrue(s1.get_length() == 3);
+            assertTrue(s1.component_count() == 3);
             s1.rewind();
             for (i = 0; i < 3; i++) {
                 av = s1.get_any();
                 s = av.extract_short();
-                TEST(s == (short) i);
+                assertTrue(s == (short) i);
                 s1.next();
             }
 
@@ -3028,17 +3032,17 @@
             //
             av = s1.to_any();
             pseq = TestAnySeqHelper.extract(av);
-            TEST(pseq.length == 3);
+            assertTrue(pseq.length == 3);
             for (i = 0; i < 3; i++) {
                 s = pseq[i].extract_short();
-                TEST(s == (short) i);
+                assertTrue(s == (short) i);
             }
 
             //
             // Test: copy
             //
             copy = s1.copy();
-            TEST(s1.equal(copy));
+            assertTrue(s1.equal(copy));
             copy.destroy();
 
             //
@@ -3048,7 +3052,7 @@
             copy.seek(1);
             any.insert_short((short) -33);
             copy.insert_any(any);
-            TEST(!s1.equal(copy));
+            assertTrue(!s1.equal(copy));
             copy.destroy();
 
             //
@@ -3065,7 +3069,7 @@
             for (i = 0; i < 8; i++) {
                 av = s1.get_any();
                 s = av.extract_short();
-                TEST(s == (short) (8 - i));
+                assertTrue(s == (short) (8 - i));
                 s1.next();
             }
 
@@ -3078,12 +3082,12 @@
                 comp = s1.current_component();
                 av = comp.get_any();
                 s = av.extract_short();
-                TEST(s == (short) (8 - i));
+                assertTrue(s == (short) (8 - i));
                 any.insert_short((short) i);
                 comp.insert_any(any);
                 av = s1.get_any();
                 s = av.extract_short();
-                TEST(s == (short) i);
+                assertTrue(s == (short) i);
                 s1.next();
             }
 
@@ -3091,11 +3095,11 @@
             // Test: get_elements()
             //
             Any[] anySeq = s1.get_elements();
-            TEST(anySeq.length == 8);
+            assertTrue(anySeq.length == 8);
             for (i = 0; i < 8; i++) {
                 Any p = anySeq[i].extract_any();
                 s = p.extract_short();
-                TEST(s == (short) i);
+                assertTrue(s == (short) i);
             }
 
             //
@@ -3113,7 +3117,7 @@
             for (i = 0; i < 3; i++) {
                 av = s1.get_any();
                 s = av.extract_short();
-                TEST(s == (short) (i + 10));
+                assertTrue(s == (short) (i + 10));
                 s1.next();
             }
 
@@ -3121,11 +3125,11 @@
             // Test: get_elements_as_dyn_any()
             //
             DynAny[] dynAnySeq = s1.get_elements_as_dyn_any();
-            TEST(dynAnySeq.length == 3);
+            assertTrue(dynAnySeq.length == 3);
             for (i = 0; i < 3; i++) {
                 av = dynAnySeq[i].get_any();
                 s = av.extract_short();
-                TEST(s == (short) (i + 10));
+                assertTrue(s == (short) (i + 10));
             }
 
             //
@@ -3143,7 +3147,7 @@
             for (i = 0; i < 4; i++) {
                 av = s1.get_any();
                 s = av.extract_short();
-                TEST(s == (short) (i + 100));
+                assertTrue(s == (short) (i + 100));
                 s1.next();
             }
             for (i = 0; i < 4; i++)
@@ -3161,15 +3165,15 @@
             d2 = factory.create_dyn_any(any);
             s2 = DynSequenceHelper.narrow(d2);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(s1.get_length() == 10);
-            TEST(s1.component_count() == 10);
+            assertTrue(s1.get_length() == 10);
+            assertTrue(s1.component_count() == 10);
             s1.rewind();
             for (i = 0; i < 10; i++) {
                 av = s1.get_any();
                 s = av.extract_short();
-                TEST(s == (short) (i * 10));
+                assertTrue(s == (short) (i * 10));
                 s1.next();
             }
 
@@ -3177,25 +3181,25 @@
             // Test: seek
             //
             int count = d1.component_count();
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(count) == false);
-            TEST(d1.seek(count - 1) == true);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(count) == false);
+            assertTrue(d1.seek(count - 1) == true);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(count - 1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -3208,15 +3212,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -3237,10 +3241,10 @@
             type = TestStringArrayHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             a1 = DynArrayHelper.narrow(d1);
-            TEST(a1.component_count() == 10);
+            assertTrue(a1.component_count() == 10);
             for (i = 0; i < 10; i++) {
                 str = a1.get_string();
-                TEST(str.length() == 0);
+                assertTrue(str.length() == 0);
                 String s = "str " + i;
                 a1.insert_string(s);
                 a1.next();
@@ -3253,14 +3257,14 @@
             arr = TestStringArrayHelper.extract(av);
             for (i = 0; i < 10; i++) {
                 String s = "str " + i;
-                TEST(arr[i].equals(s));
+                assertTrue(arr[i].equals(s));
             }
 
             //
             // Test: copy
             //
             copy = a1.copy();
-            TEST(a1.equal(copy));
+            assertTrue(a1.equal(copy));
             copy.destroy();
 
             //
@@ -3269,7 +3273,7 @@
             copy = a1.copy();
             copy.seek(1);
             copy.insert_string("hi there");
-            TEST(!a1.equal(copy));
+            assertTrue(!a1.equal(copy));
             copy.destroy();
 
             //
@@ -3283,7 +3287,7 @@
             for (i = 0; i < 10; i++) {
                 str = a1.get_string();
                 String s = "STR " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 a1.next();
             }
 
@@ -3296,11 +3300,11 @@
                 comp = a1.current_component();
                 str = comp.get_string();
                 String s = "STR " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 s = "string " + i;
                 comp.insert_string(s);
                 str = a1.get_string();
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 a1.next();
             }
 
@@ -3308,11 +3312,11 @@
             // Test: get_elements()
             //
             Any[] anySeq = a1.get_elements();
-            TEST(anySeq.length == 10);
+            assertTrue(anySeq.length == 10);
             for (i = 0; i < 10; i++) {
                 String cp = anySeq[i].extract_string();
                 String s = "string " + i;
-                TEST(cp.equals(s));
+                assertTrue(cp.equals(s));
             }
 
             //
@@ -3327,7 +3331,7 @@
             for (i = 0; i < 10; i++) {
                 str = a1.get_string();
                 String s = "String " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 a1.next();
             }
 
@@ -3335,11 +3339,11 @@
             // Test: get_elements_as_dyn_any()
             //
             DynAny[] dynAnySeq = a1.get_elements_as_dyn_any();
-            TEST(dynAnySeq.length == 10);
+            assertTrue(dynAnySeq.length == 10);
             for (i = 0; i < 10; i++) {
                 str = dynAnySeq[i].get_string();
                 String s = "String " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
             }
 
             //
@@ -3356,7 +3360,7 @@
             for (i = 0; i < 10; i++) {
                 str = a1.get_string();
                 String s = "STRING " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 a1.next();
             }
             for (i = 0; i < 10; i++)
@@ -3371,14 +3375,14 @@
             d2 = factory.create_dyn_any(any);
             a2 = DynArrayHelper.narrow(d2);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(a1.component_count() == 10);
+            assertTrue(a1.component_count() == 10);
             a1.rewind();
             for (i = 0; i < 10; i++) {
                 str = a1.get_string();
                 String s = "Str " + i;
-                TEST(str.equals(s));
+                assertTrue(str.equals(s));
                 a1.next();
             }
 
@@ -3393,35 +3397,35 @@
                     anySeq[i].insert_string(s);
                 }
                 a1.set_elements(anySeq);
-                TEST("set_elements() should not have succeeded" == null);
+                assertTrue("set_elements() should not have succeeded" == null);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
-            TEST(a1.component_count() == 10);
+            assertTrue(a1.component_count() == 10);
 
             //
             // Test: seek
             //
             int count = d1.component_count();
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(count) == false);
-            TEST(d1.seek(count - 1) == true);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(count) == false);
+            assertTrue(d1.seek(count - 1) == true);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(count - 1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -3434,15 +3438,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -3464,22 +3468,22 @@
             type = TestStructBoxHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             v1 = DynValueBoxHelper.narrow(d1);
-            TEST(v1.is_null());
-            TEST(v1.component_count() == 0);
-            TEST(v1.current_component() == null);
+            assertTrue(v1.is_null());
+            assertTrue(v1.component_count() == 0);
+            assertTrue(v1.current_component() == null);
 
             //
             // Test: to_any (null)
             //
             av = d1.to_any();
             pts = TestStructBoxHelper.extract(av);
-            TEST(pts == null);
+            assertTrue(pts == null);
 
             //
             // Test: copy (null)
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             copy.destroy();
 
             //
@@ -3487,7 +3491,7 @@
             //
             TestStructBoxHelper.insert(any, null);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
 
             //
@@ -3496,16 +3500,16 @@
             TestStructBoxHelper.insert(any, null);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
 
             //
             // Test: get_boxed_value (null)
             //
             try {
                 v1.get_boxed_value();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -3515,7 +3519,7 @@
             //
             try {
                 v1.get_boxed_value_as_dyn_any();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -3526,7 +3530,7 @@
             try {
                 any.insert_string("hi");
                 v1.set_boxed_value(any);
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -3537,7 +3541,7 @@
             try {
                 any.type(TestStructHelper.type());
                 v1.set_boxed_value(any);
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -3549,7 +3553,7 @@
                 any.insert_long(123);
                 d2 = factory.create_dyn_any(any);
                 v1.set_boxed_value_as_dyn_any(d2);
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 d2.destroy();
@@ -3558,10 +3562,10 @@
             //
             // Test: set_to_value
             //
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_to_value();
-            TEST(!v1.is_null());
-            TEST(v1.component_count() == 1);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.component_count() == 1);
 
             //
             // Test: component
@@ -3583,7 +3587,7 @@
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             copy.destroy();
 
             //
@@ -3593,7 +3597,7 @@
             loadStruct(orb, tsbv);
             TestStructBoxHelper.insert(any, tsbv);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
 
             //
@@ -3610,7 +3614,7 @@
             TestStructHelper.insert(any, ts);
             copy = v1.copy();
             v1.set_boxed_value(any);
-            TEST(!v1.equal(copy));
+            assertTrue(!v1.equal(copy));
             copy.destroy();
 
             //
@@ -3635,54 +3639,54 @@
             d2 = factory.create_dyn_any(any);
             v2 = DynValueBoxHelper.narrow(d2);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(v1.component_count() == 1);
+            assertTrue(v1.component_count() == 1);
 
             //
             // Test: set_boxed_value (from null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             ts.shortVal = (short) -99;
             TestStructHelper.insert(any, ts);
             v1.set_boxed_value(any);
-            TEST(!v1.is_null());
-            TEST(v1.current_component() != null);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.current_component() != null);
 
             //
             // Test: set_boxed_value_as_dyn_any (from null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             TestStructHelper.insert(any, ts);
             d2 = factory.create_dyn_any(any);
             v1.set_boxed_value_as_dyn_any(d2);
             d2.destroy();
-            TEST(!v1.is_null());
-            TEST(v1.current_component() != null);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.current_component() != null);
 
             //
             // Test: seek
             //
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(1) == false);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(1) == false);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(0);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -3695,15 +3699,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -3724,22 +3728,22 @@
             type = TestStringBoxHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             v1 = DynValueBoxHelper.narrow(d1);
-            TEST(v1.is_null());
-            TEST(v1.component_count() == 0);
-            TEST(v1.current_component() == null);
+            assertTrue(v1.is_null());
+            assertTrue(v1.component_count() == 0);
+            assertTrue(v1.current_component() == null);
 
             //
             // Test: to_any (null)
             //
             av = d1.to_any();
             str = TestStringBoxHelper.extract(av);
-            TEST(str == null);
+            assertTrue(str == null);
 
             //
             // Test: copy (null)
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             copy.destroy();
 
             //
@@ -3747,7 +3751,7 @@
             //
             TestStringBoxHelper.insert(any, null);
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
 
             //
@@ -3756,16 +3760,16 @@
             TestStringBoxHelper.insert(any, null);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
 
             //
             // Test: get_boxed_value (null)
             //
             try {
                 v1.get_boxed_value();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -3775,7 +3779,7 @@
             //
             try {
                 v1.get_boxed_value_as_dyn_any();
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -3786,7 +3790,7 @@
             try {
                 any.insert_boolean(false);
                 v1.set_boxed_value(any);
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
             }
@@ -3797,7 +3801,7 @@
             try {
                 any.type(orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_string));
                 v1.set_boxed_value(any);
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
                 // expected
             }
@@ -3809,7 +3813,7 @@
                 any.insert_long(123);
                 d2 = factory.create_dyn_any(any);
                 v1.set_boxed_value_as_dyn_any(d2);
-                TEST(false);
+                assertTrue(false);
             } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
                 // expected
                 d2.destroy();
@@ -3818,17 +3822,17 @@
             //
             // Test: set_to_value
             //
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_to_value();
-            TEST(!v1.is_null());
-            TEST(v1.component_count() == 1);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.component_count() == 1);
 
             //
             // Test: component
             //
             comp = v1.current_component();
             str = comp.get_string();
-            TEST(str.length() == 0);
+            assertTrue(str.length() == 0);
             any.insert_string("hi");
             comp.from_any(any);
 
@@ -3837,13 +3841,13 @@
             //
             av = d1.to_any();
             str = TestStringBoxHelper.extract(av);
-            TEST(str.equals("hi"));
+            assertTrue(str.equals("hi"));
 
             //
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             copy.destroy();
 
             //
@@ -3851,14 +3855,14 @@
             //
             TestStringBoxHelper.insert(any, "hi");
             d2 = factory.create_dyn_any(any);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
 
             //
             // Test: get_boxed_value
             //
             av = v1.get_boxed_value();
-            TEST(av.extract_string().equals("hi"));
+            assertTrue(av.extract_string().equals("hi"));
 
             //
             // Test: set_boxed_value
@@ -3866,14 +3870,14 @@
             any.insert_string("bye");
             copy = v1.copy();
             v1.set_boxed_value(any);
-            TEST(!v1.equal(copy));
+            assertTrue(!v1.equal(copy));
             copy.destroy();
 
             //
             // Test: get_boxed_value_as_dyn_any
             //
             d2 = v1.get_boxed_value_as_dyn_any();
-            TEST(d2.get_string().equals("bye"));
+            assertTrue(d2.get_string().equals("bye"));
 
             //
             // Test: set_boxed_value_as_dyn_any
@@ -3890,53 +3894,53 @@
             d2 = factory.create_dyn_any(any);
             v2 = DynValueBoxHelper.narrow(d2);
             d1.assign(d2);
-            TEST(d1.equal(d2));
+            assertTrue(d1.equal(d2));
             d2.destroy();
-            TEST(v1.component_count() == 1);
+            assertTrue(v1.component_count() == 1);
 
             //
             // Test: set_boxed_value (from null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             any.insert_string("foo");
             v1.set_boxed_value(any);
-            TEST(!v1.is_null());
-            TEST(v1.current_component() != null);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.current_component() != null);
 
             //
             // Test: set_boxed_value_as_dyn_any (from null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             any.insert_string("bar");
             d2 = factory.create_dyn_any(any);
             v1.set_boxed_value_as_dyn_any(d2);
             d2.destroy();
-            TEST(!v1.is_null());
-            TEST(v1.current_component() != null);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.current_component() != null);
 
             //
             // Test: seek
             //
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(1) == false);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(1) == false);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(0);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -3949,15 +3953,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -3977,21 +3981,21 @@
             type = TestValue1Helper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             v1 = DynValueHelper.narrow(d1);
-            TEST(v1.is_null());
-            TEST(v1.component_count() == 0);
+            assertTrue(v1.is_null());
+            assertTrue(v1.component_count() == 0);
 
             //
             // Test: to_any (null)
             //
             av = d1.to_any();
             ptv1 = TestValue1Helper.extract(av);
-            TEST(ptv1 == null);
+            assertTrue(ptv1 == null);
 
             //
             // Test: copy (null)
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4000,7 +4004,7 @@
             //
             TestValue1Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
@@ -4009,17 +4013,17 @@
             TestValue1Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
 
             //
             // Test: set_to_value
             //
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_to_value();
-            TEST(!v1.is_null());
-            TEST(v1.component_count() == 0);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.component_count() == 0);
 
             //
             // Test: current_component TypeMismatch exception
@@ -4035,13 +4039,13 @@
             //
             av = d1.to_any();
             ptv1 = TestValue1Helper.extract(av);
-            TEST(ptv1 != null);
+            assertTrue(ptv1 != null);
 
             //
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4052,14 +4056,14 @@
             TestValue1Helper.insert(any, tv1v);
             d2 = factory.create_dyn_any(any);
             v2 = DynValueHelper.narrow(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
             // Test: get_members
             //
             NameValuePair[] nvpSeq = v1.get_members();
-            TEST(nvpSeq.length == 0);
+            assertTrue(nvpSeq.length == 0);
 
             //
             // Test: set_members
@@ -4070,15 +4074,15 @@
             // Test: set_members (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members(nvpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: get_members_as_dyn_any
             //
             NameDynAnyPair[] ndpSeq = v1.get_members_as_dyn_any();
-            TEST(ndpSeq.length == 0);
+            assertTrue(ndpSeq.length == 0);
 
             //
             // Test: set_elements_as_dyn_any
@@ -4090,9 +4094,9 @@
             // Test: set_elements_as_dyn_any (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members_as_dyn_any(ndpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: assign
@@ -4102,29 +4106,29 @@
             d2 = factory.create_dyn_any(any);
             v2 = DynValueHelper.narrow(d2);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.component_count() == 0);
+            assertTrue(v1.component_count() == 0);
 
             //
             // Test: seek
             //
-            TEST(d1.seek(0) == false);
-            TEST(d1.seek(-1) == false);
+            assertTrue(d1.seek(0) == false);
+            assertTrue(d1.seek(-1) == false);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -4147,21 +4151,21 @@
             type = TestValue2Helper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             v1 = DynValueHelper.narrow(d1);
-            TEST(v1.is_null());
-            TEST(v1.component_count() == 0);
+            assertTrue(v1.is_null());
+            assertTrue(v1.component_count() == 0);
 
             //
             // Test: to_any (null)
             //
             av = d1.to_any();
             ptv2 = TestValue2Helper.extract(av);
-            TEST(ptv2 == null);
+            assertTrue(ptv2 == null);
 
             //
             // Test: copy (null)
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4170,7 +4174,7 @@
             //
             TestValue2Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
@@ -4179,17 +4183,17 @@
             TestValue2Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
 
             //
             // Test: set_to_value
             //
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_to_value();
-            TEST(!v1.is_null());
-            TEST(v1.component_count() == 3);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.component_count() == 3);
 
             //
             // Test: components
@@ -4205,15 +4209,15 @@
             //
             av = d1.to_any();
             ptv2 = TestValue2Helper.extract(av);
-            TEST(ptv2.shortVal == (short) -55);
-            TEST(ptv2.longVal == 333);
-            TEST(ptv2.stringVal.equals("hi there"));
+            assertTrue(ptv2.shortVal == (short) -55);
+            assertTrue(ptv2.longVal == 333);
+            assertTrue(ptv2.stringVal.equals("hi there"));
 
             //
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4226,20 +4230,20 @@
             tv2v.stringVal = "hi there";
             TestValue2Helper.insert(any, tv2v);
             d2 = factory.create_dyn_any(any);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
             // Test: get_members
             //
             NameValuePair[] nvpSeq = v1.get_members();
-            TEST(nvpSeq.length == 3);
+            assertTrue(nvpSeq.length == 3);
             shortVal = nvpSeq[0].value.extract_short();
-            TEST(shortVal == (short) -55);
+            assertTrue(shortVal == (short) -55);
             longVal = nvpSeq[1].value.extract_long();
-            TEST(longVal == 333);
+            assertTrue(longVal == 333);
             cp = nvpSeq[2].value.extract_string();
-            TEST(cp.equals("hi there"));
+            assertTrue(cp.equals("hi there"));
 
             //
             // Test: set_members
@@ -4253,19 +4257,19 @@
             // Test: set_members (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members(nvpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: get_members_as_dyn_any
             //
             NameDynAnyPair[] ndpSeq = v1.get_members_as_dyn_any();
-            TEST(ndpSeq.length == 3);
-            TEST(ndpSeq[0].value.get_short() == (short) 237);
-            TEST(ndpSeq[1].value.get_long() == 680580);
+            assertTrue(ndpSeq.length == 3);
+            assertTrue(ndpSeq[0].value.get_short() == (short) 237);
+            assertTrue(ndpSeq[1].value.get_long() == 680580);
             str = ndpSeq[2].value.get_string();
-            TEST(str.equals("ho there"));
+            assertTrue(str.equals("ho there"));
 
             //
             // Test: set_elements_as_dyn_any
@@ -4289,9 +4293,9 @@
             // Test: set_elements_as_dyn_any (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members_as_dyn_any(ndpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: assign
@@ -4303,36 +4307,36 @@
             TestValue2Helper.insert(any, tv2v);
             d2 = factory.create_dyn_any(any);
             v2 = DynValueHelper.narrow(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.insert_short((short) 980);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.component_count() == 3);
+            assertTrue(v1.component_count() == 3);
 
             //
             // Test: seek
             //
             int count = d1.component_count();
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(count) == false);
-            TEST(d1.seek(count - 1) == true);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(count) == false);
+            assertTrue(d1.seek(count - 1) == true);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(count - 1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -4345,15 +4349,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -4379,21 +4383,21 @@
             type = TestValue3Helper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             v1 = DynValueHelper.narrow(d1);
-            TEST(v1.is_null());
-            TEST(v1.component_count() == 0);
+            assertTrue(v1.is_null());
+            assertTrue(v1.component_count() == 0);
 
             //
             // Test: to_any (null)
             //
             av = d1.to_any();
             ptv3 = TestValue3Helper.extract(av);
-            TEST(ptv3 == null);
+            assertTrue(ptv3 == null);
 
             //
             // Test: copy (null)
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4402,7 +4406,7 @@
             //
             TestValue3Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
@@ -4411,16 +4415,16 @@
             TestValue3Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
 
             //
             // Test: set_to_value
             //
             v1.set_to_value();
-            TEST(!v1.is_null());
-            TEST(v1.component_count() == 4);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.component_count() == 4);
 
             //
             // Test: components
@@ -4442,17 +4446,17 @@
             //
             av = d1.to_any();
             ptv3 = TestValue3Helper.extract(av);
-            TEST(ptv3.shortVal == (short) -55);
-            TEST(ptv3.longVal == 333);
-            TEST(ptv3.stringVal.equals("hi there"));
-            TEST(ptv3.unionVal.discriminator() == (short) 0);
-            TEST(ptv3.unionVal.a() == 333);
+            assertTrue(ptv3.shortVal == (short) -55);
+            assertTrue(ptv3.longVal == 333);
+            assertTrue(ptv3.stringVal.equals("hi there"));
+            assertTrue(ptv3.unionVal.discriminator() == (short) 0);
+            assertTrue(ptv3.unionVal.a() == 333);
 
             //
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4467,23 +4471,23 @@
             tv3v.unionVal.a((short) 0, 333);
             TestValue3Helper.insert(any, tv3v);
             d2 = factory.create_dyn_any(any);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
             // Test: get_members
             //
             NameValuePair[] nvpSeq = v1.get_members();
-            TEST(nvpSeq.length == 4);
+            assertTrue(nvpSeq.length == 4);
             shortVal = nvpSeq[0].value.extract_short();
-            TEST(shortVal == (short) -55);
+            assertTrue(shortVal == (short) -55);
             longVal = nvpSeq[1].value.extract_long();
-            TEST(longVal == 333);
+            assertTrue(longVal == 333);
             cp = nvpSeq[2].value.extract_string();
-            TEST(cp.equals("hi there"));
+            assertTrue(cp.equals("hi there"));
             ptu4 = test.types.DynAnyTypes.TestUnion4Helper
                     .extract(nvpSeq[3].value);
-            TEST(ptu4.a() == 333);
+            assertTrue(ptu4.a() == 333);
 
             //
             // Test: set_members
@@ -4500,21 +4504,21 @@
             // Test: set_members (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members(nvpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: get_members_as_dyn_any
             //
             NameDynAnyPair[] ndpSeq = v1.get_members_as_dyn_any();
-            TEST(ndpSeq.length == 4);
-            TEST(ndpSeq[0].value.get_short() == (short) 237);
-            TEST(ndpSeq[1].value.get_long() == 680580);
+            assertTrue(ndpSeq.length == 4);
+            assertTrue(ndpSeq[0].value.get_short() == (short) 237);
+            assertTrue(ndpSeq[1].value.get_long() == 680580);
             str = ndpSeq[2].value.get_string();
-            TEST(str.equals("ho there"));
+            assertTrue(str.equals("ho there"));
             ndpSeq[3].value.seek(1);
-            TEST(ndpSeq[3].value.get_float() < 2.0f);
+            assertTrue(ndpSeq[3].value.get_float() < 2.0f);
 
             //
             // Test: set_elements_as_dyn_any
@@ -4543,9 +4547,9 @@
             // Test: set_elements_as_dyn_any (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members_as_dyn_any(ndpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: assign
@@ -4559,36 +4563,36 @@
             TestValue3Helper.insert(any, tv3v);
             d2 = factory.create_dyn_any(any);
             v2 = DynValueHelper.narrow(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.insert_short((short) 980);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.component_count() == 4);
+            assertTrue(v1.component_count() == 4);
 
             //
             // Test: seek
             //
             int count = d1.component_count();
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(count) == false);
-            TEST(d1.seek(count - 1) == true);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(count) == false);
+            assertTrue(d1.seek(count - 1) == true);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(count - 1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -4601,15 +4605,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -4634,21 +4638,21 @@
             type = TestValue4Helper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
             v1 = DynValueHelper.narrow(d1);
-            TEST(v1.is_null());
-            TEST(v1.component_count() == 0);
+            assertTrue(v1.is_null());
+            assertTrue(v1.component_count() == 0);
 
             //
             // Test: to_any (null)
             //
             av = d1.to_any();
             ptv4 = TestValue4Helper.extract(av);
-            TEST(ptv4 == null);
+            assertTrue(ptv4 == null);
 
             //
             // Test: copy (null)
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4657,7 +4661,7 @@
             //
             TestValue4Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
@@ -4666,16 +4670,16 @@
             TestValue4Helper.insert(any, null);
             d2 = factory.create_dyn_any(any);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
 
             //
             // Test: set_to_value
             //
             v1.set_to_value();
-            TEST(!v1.is_null());
-            TEST(v1.component_count() == 5);
+            assertTrue(!v1.is_null());
+            assertTrue(v1.component_count() == 5);
 
             //
             // Test: components
@@ -4695,17 +4699,17 @@
             //
             av = d1.to_any();
             ptv4 = TestValue4Helper.extract(av);
-            TEST(ptv4.shortVal == (short) -55);
-            TEST(ptv4.longVal == 333);
-            TEST(ptv4.stringVal.equals("hi there"));
-            TEST(ptv4.charVal == 'A');
-            TEST(ptv4.longlongVal == 7890123L);
+            assertTrue(ptv4.shortVal == (short) -55);
+            assertTrue(ptv4.longVal == 333);
+            assertTrue(ptv4.stringVal.equals("hi there"));
+            assertTrue(ptv4.charVal == 'A');
+            assertTrue(ptv4.longlongVal == 7890123L);
 
             //
             // Test: copy
             //
             copy = d1.copy();
-            TEST(d1.equal(copy));
+            assertTrue(d1.equal(copy));
             // destroying copy would also destroy d1
             // copy.destroy();
 
@@ -4720,24 +4724,24 @@
             tv4v.longlongVal = 7890123L;
             TestValue4Helper.insert(any, tv4v);
             d2 = factory.create_dyn_any(any);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
 
             //
             // Test: get_members
             //
             NameValuePair[] nvpSeq = v1.get_members();
-            TEST(nvpSeq.length == 5);
+            assertTrue(nvpSeq.length == 5);
             shortVal = nvpSeq[0].value.extract_short();
-            TEST(shortVal == (short) -55);
+            assertTrue(shortVal == (short) -55);
             longVal = nvpSeq[1].value.extract_long();
-            TEST(longVal == 333);
+            assertTrue(longVal == 333);
             cp = nvpSeq[2].value.extract_string();
-            TEST(cp.equals("hi there"));
+            assertTrue(cp.equals("hi there"));
             charVal = nvpSeq[3].value.extract_char();
-            TEST(charVal == 'A');
+            assertTrue(charVal == 'A');
             longlongVal = nvpSeq[4].value.extract_longlong();
-            TEST(longlongVal == 7890123L);
+            assertTrue(longlongVal == 7890123L);
 
             //
             // Test: set_members
@@ -4753,21 +4757,21 @@
             // Test: set_members (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members(nvpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: get_members_as_dyn_any
             //
             NameDynAnyPair[] ndpSeq = v1.get_members_as_dyn_any();
-            TEST(ndpSeq.length == 5);
-            TEST(ndpSeq[0].value.get_short() == (short) 237);
-            TEST(ndpSeq[1].value.get_long() == 680580);
+            assertTrue(ndpSeq.length == 5);
+            assertTrue(ndpSeq[0].value.get_short() == (short) 237);
+            assertTrue(ndpSeq[1].value.get_long() == 680580);
             str = ndpSeq[2].value.get_string();
-            TEST(str.equals("ho there"));
-            TEST(ndpSeq[3].value.get_char() == 'Z');
-            TEST(ndpSeq[4].value.get_longlong() == 1237890L);
+            assertTrue(str.equals("ho there"));
+            assertTrue(ndpSeq[3].value.get_char() == 'Z');
+            assertTrue(ndpSeq[4].value.get_longlong() == 1237890L);
 
             //
             // Test: set_elements_as_dyn_any
@@ -4799,9 +4803,9 @@
             // Test: set_elements_as_dyn_any (null)
             //
             v1.set_to_null();
-            TEST(v1.is_null());
+            assertTrue(v1.is_null());
             v1.set_members_as_dyn_any(ndpSeq);
-            TEST(!v1.is_null());
+            assertTrue(!v1.is_null());
 
             //
             // Test: assign
@@ -4815,36 +4819,36 @@
             TestValue4Helper.insert(any, tv4v);
             d2 = factory.create_dyn_any(any);
             v2 = DynValueHelper.narrow(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.insert_short((short) 980);
             d1.assign(d2);
-            TEST(!d1.equal(d2));
+            assertTrue(!d1.equal(d2));
             d2.destroy();
-            TEST(v1.component_count() == 5);
+            assertTrue(v1.component_count() == 5);
 
             //
             // Test: seek
             //
             int count = d1.component_count();
-            TEST(d1.seek(0) == true);
-            TEST(d1.seek(-1) == false);
-            TEST(d1.seek(count) == false);
-            TEST(d1.seek(count - 1) == true);
+            assertTrue(d1.seek(0) == true);
+            assertTrue(d1.seek(-1) == false);
+            assertTrue(d1.seek(count) == false);
+            assertTrue(d1.seek(count - 1) == true);
 
             //
             // Test: next
             //
             d1.seek(-1);
-            TEST(d1.next() == true);
+            assertTrue(d1.next() == true);
             d1.seek(count - 1);
-            TEST(d1.next() == false);
+            assertTrue(d1.next() == false);
 
             //
             // Test: current_component
             //
             d1.rewind();
             d2 = d1.current_component();
-            TEST(d2 != null);
+            assertTrue(d2 != null);
 
             //
             // Test: destroy
@@ -4857,15 +4861,15 @@
             //
             d1.seek(-9);
             d2 = d1.current_component();
-            TEST(d2 == null);
+            assertTrue(d2 == null);
 
             d1.destroy();
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -4883,7 +4887,7 @@
             //
             type = TestValueStructHelper.type();
             d1 = factory.create_dyn_any_from_type_code(type);
-            TEST(d1.component_count() == 2);
+            assertTrue(d1.component_count() == 2);
 
             //
             // Test: components
@@ -4892,7 +4896,7 @@
             d1.next();
             comp = d1.current_component();
             dv = DynValueHelper.narrow(comp);
-            TEST(dv.is_null());
+            assertTrue(dv.is_null());
             dv.set_to_value();
             comp.insert_short((short) -55);
             comp.next();
@@ -4908,11 +4912,11 @@
             try {
                 ptv2 = (TestValue2) vb;
             } catch (ClassCastException ex) {
-                TEST(false);
+                assertTrue(false);
             }
-            TEST(ptv2.shortVal == (short) -55);
-            TEST(ptv2.longVal == 333);
-            TEST(ptv2.stringVal.equals("hi there"));
+            assertTrue(ptv2.shortVal == (short) -55);
+            assertTrue(ptv2.longVal == 333);
+            assertTrue(ptv2.stringVal.equals("hi there"));
 
             //
             // Test: insert_val()
@@ -4930,33 +4934,33 @@
             // truncated to TestValue2
             //
             comp = d1.current_component();
-            TEST(comp.component_count() == 3);
+            assertTrue(comp.component_count() == 3);
             comp.rewind();
-            TEST(comp.get_short() == (short) -77);
+            assertTrue(comp.get_short() == (short) -77);
             comp.next();
-            TEST(comp.get_long() == 555);
+            assertTrue(comp.get_long() == 555);
             comp.next();
             str = comp.get_string();
-            TEST(str.equals("ho there"));
+            assertTrue(str.equals("ho there"));
             vb = d1.get_val();
             try {
                 ptv2 = (TestValue2) vb;
             } catch (ClassCastException ex) {
-                TEST(false);
+                assertTrue(false);
             }
 
             try {
                 TestValue4 ptv4 = (TestValue4) vb;
-                TEST(false);
+                assertTrue(false);
             } catch (ClassCastException ex) {
                 // expected
             }
         } catch (org.omg.DynamicAny.DynAnyFactoryPackage.InconsistentTypeCode ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.TypeMismatch ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.DynamicAny.DynAnyPackage.InvalidValue ex) {
-            TEST(false);
+            assertTrue(false);
         }
     }
 
@@ -4965,9 +4969,9 @@
 
         try {
             obj = orb.resolve_initial_references("DynAnyFactory");
-            TEST(obj != null);
+            assertTrue(obj != null);
         } catch (org.omg.CORBA.ORBPackage.InvalidName ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
diff --git a/yoko-core/src/test/java/test/types/TestPortableTypes.java b/yoko-core/src/test/java/test/types/TestPortableTypes.java
index 9805f57..5dda928 100644
--- a/yoko-core/src/test/java/test/types/TestPortableTypes.java
+++ b/yoko-core/src/test/java/test/types/TestPortableTypes.java
@@ -17,6 +17,8 @@
 
 package test.types;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
 
 public class TestPortableTypes extends test.common.TestBase {
@@ -52,7 +54,7 @@
             // more than just compare IDs
             //
             tc.id_ = "";
-            TEST(tc.equivalent(types[i]));
+            assertTrue(tc.equivalent(types[i]));
 
             //
             // There's no point in calling equal() because the comparison
@@ -153,7 +155,7 @@
                     test.types.DynAnyTypes.TestEnum.red);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -170,7 +172,7 @@
                     new test.types.DynAnyTypes.TestEmptyException());
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -187,7 +189,7 @@
                     new test.types.DynAnyTypes.TestException("hi", 0));
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -223,7 +225,7 @@
             test.types.DynAnyTypes.TestStructHelper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             /**
@@ -251,7 +253,7 @@
             test.types.TestStruct1Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -269,7 +271,7 @@
             test.types.DynAnyTypes.TestUnion1Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -287,7 +289,7 @@
             test.types.DynAnyTypes.TestUnion1Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -305,7 +307,7 @@
             test.types.DynAnyTypes.TestUnion1Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -323,7 +325,7 @@
             test.types.DynAnyTypes.TestUnion2Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -341,7 +343,7 @@
             test.types.DynAnyTypes.TestUnion2Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             /**
@@ -363,7 +365,7 @@
             test.types.DynAnyTypes.TestUnion3Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -381,7 +383,7 @@
             test.types.DynAnyTypes.TestUnion3Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -399,7 +401,7 @@
             test.types.DynAnyTypes.TestUnion3Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -417,7 +419,7 @@
             test.types.DynAnyTypes.TestUnion4Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -435,7 +437,7 @@
             test.types.DynAnyTypes.TestUnion4Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -453,7 +455,7 @@
             test.types.DynAnyTypes.TestUnion4Helper.insert(any1, val);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -470,7 +472,7 @@
                     .insert(any1, new short[5]);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -512,7 +514,7 @@
             test.types.DynAnyTypes.TestAnySeqHelper.insert(any1, seq);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
@@ -531,7 +533,7 @@
             test.types.DynAnyTypes.TestStringArrayHelper.insert(any1, seq);
             org.omg.DynamicAny.DynAny da = factory.create_dyn_any(any1);
             org.omg.CORBA.Any any2 = da.to_any();
-            TEST(any2.equal(any1));
+            assertTrue(any2.equal(any1));
             da.destroy();
 
             org.omg.CORBA.portable.OutputStream out = orb
diff --git a/yoko-core/src/test/java/test/types/TestTypeCode.java b/yoko-core/src/test/java/test/types/TestTypeCode.java
index 672a06a..6f7a8dc 100644
--- a/yoko-core/src/test/java/test/types/TestTypeCode.java
+++ b/yoko-core/src/test/java/test/types/TestTypeCode.java
@@ -17,9 +17,12 @@
 
 package test.types;
 
+import static org.junit.Assert.assertTrue;
+
 import org.omg.CORBA.*;
 
 public class TestTypeCode extends test.common.TestBase {
+    private static final boolean CHECK_IDL_NAMES = false;
     public TestTypeCode(ORB orb) {
         //
         // Test CompletionStatus
@@ -30,452 +33,452 @@
         //
         try {
             TCKind kind = CompletionStatusHelper.type().kind();
-            TEST(kind == TCKind.tk_enum);
+            assertTrue(kind == TCKind.tk_enum);
 
             String name = CompletionStatusHelper.type().name();
-            TEST(name.equals("completion_status")
-                    || name.equals("CompletionStatus"));
+            assertTrue(name.equals("completion_status")
+			|| name.equals("CompletionStatus"));
 
             String id = CompletionStatusHelper.type().id();
-            TEST(id.equals("IDL:omg.org/CORBA/completion_status:1.0")
-                    || id.equals("IDL:omg.org/CORBA/CompletionStatus:1.0"));
+            assertTrue(id.equals("IDL:omg.org/CORBA/completion_status:1.0")
+			|| id.equals("IDL:omg.org/CORBA/CompletionStatus:1.0"));
 
             int count = CompletionStatusHelper.type().member_count();
-            TEST(count == 3);
+            assertTrue(count == 3);
 
             String name0 = CompletionStatusHelper.type().member_name(0);
-            TEST(name0.equals("COMPLETED_YES"));
+            assertTrue(name0.equals("COMPLETED_YES"));
 
             String name1 = CompletionStatusHelper.type().member_name(1);
-            TEST(name1.equals("COMPLETED_NO"));
+            assertTrue(name1.equals("COMPLETED_NO"));
 
             String name2 = CompletionStatusHelper.type().member_name(2);
-            TEST(name2.equals("COMPLETED_MAYBE"));
+            assertTrue(name2.equals("COMPLETED_MAYBE"));
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TypeCode type = org.omg.CORBA.TypeCodePackage.BoundsHelper.type();
 
             TCKind kind = type.kind();
-            TEST(kind == TCKind.tk_except);
+            assertTrue(kind == TCKind.tk_except);
 
             String name = type.name();
-            TEST(name.equals("Bounds"));
+            assertTrue(name.equals("Bounds"));
 
             String id = type.id();
-            TEST(id.equals("IDL:omg.org/CORBA/TypeCode/Bounds:1.0"));
+            assertTrue(id.equals("IDL:omg.org/CORBA/TypeCode/Bounds:1.0"));
 
             int count = type.member_count();
-            TEST(count == 0);
+            assertTrue(count == 0);
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TypeCode type = org.omg.CORBA.TypeCodePackage.BadKindHelper.type();
 
             TCKind kind = type.kind();
-            TEST(kind == TCKind.tk_except);
+            assertTrue(kind == TCKind.tk_except);
 
             String name = type.name();
-            TEST(name.equals("BadKind"));
+            assertTrue(name.equals("BadKind"));
 
             String id = type.id();
-            TEST(id.equals("IDL:omg.org/CORBA/TypeCode/BadKind:1.0"));
+            assertTrue(id.equals("IDL:omg.org/CORBA/TypeCode/BadKind:1.0"));
 
             int count = type.member_count();
-            TEST(count == 0);
+            assertTrue(count == 0);
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TCKind kind = TestStruct1Helper.type().kind();
-            TEST(kind == TCKind.tk_struct);
+            assertTrue(kind == TCKind.tk_struct);
 
             String name = TestStruct1Helper.type().name();
-            TEST(name.equals("TestStruct1"));
+            assertTrue(name.equals("TestStruct1"));
 
             long count = TestStruct1Helper.type().member_count();
-            TEST(count == 7);
+            assertTrue(count == 7);
 
             String name0 = TestStruct1Helper.type().member_name(0);
-            TEST(name0.equals("s"));
+            assertTrue(name0.equals("s"));
 
             String name1 = TestStruct1Helper.type().member_name(1);
-            TEST(name1.equals("l"));
+            assertTrue(name1.equals("l"));
 
             String name2 = TestStruct1Helper.type().member_name(2);
-            TEST(name2.equals("d"));
+            assertTrue(name2.equals("d"));
 
             String name3 = TestStruct1Helper.type().member_name(3);
-            TEST(name3.equals("b"));
+            assertTrue(name3.equals("b"));
 
             String name4 = TestStruct1Helper.type().member_name(4);
-            TEST(name4.equals("c"));
+            assertTrue(name4.equals("c"));
 
             String name5 = TestStruct1Helper.type().member_name(5);
-            TEST(name5.equals("o"));
+            assertTrue(name5.equals("o"));
 
             String name6 = TestStruct1Helper.type().member_name(6);
-            TEST(name6.equals("str"));
+            assertTrue(name6.equals("str"));
 
             TypeCode type0 = TestStruct1Helper.type().member_type(0);
-            TEST(type0.equal(orb.get_primitive_tc(TCKind.tk_short)));
+            assertTrue(type0.equal(orb.get_primitive_tc(TCKind.tk_short)));
 
             TypeCode type1 = TestStruct1Helper.type().member_type(1);
-            TEST(type1.equal(orb.get_primitive_tc(TCKind.tk_long)));
+            assertTrue(type1.equal(orb.get_primitive_tc(TCKind.tk_long)));
 
             TypeCode type2 = TestStruct1Helper.type().member_type(2);
-            TEST(type2.equal(orb.get_primitive_tc(TCKind.tk_double)));
+            assertTrue(type2.equal(orb.get_primitive_tc(TCKind.tk_double)));
 
             TypeCode type3 = TestStruct1Helper.type().member_type(3);
-            TEST(type3.equal(orb.get_primitive_tc(TCKind.tk_boolean)));
+            assertTrue(type3.equal(orb.get_primitive_tc(TCKind.tk_boolean)));
 
             TypeCode type4 = TestStruct1Helper.type().member_type(4);
-            TEST(type4.equal(orb.get_primitive_tc(TCKind.tk_char)));
+            assertTrue(type4.equal(orb.get_primitive_tc(TCKind.tk_char)));
 
             TypeCode type5 = TestStruct1Helper.type().member_type(5);
-            TEST(type5.equal(orb.get_primitive_tc(TCKind.tk_octet)));
+            assertTrue(type5.equal(orb.get_primitive_tc(TCKind.tk_octet)));
 
             TypeCode type6 = TestStruct1Helper.type().member_type(6);
-            TEST(type6.equal(orb.get_primitive_tc(TCKind.tk_string)));
+            assertTrue(type6.equal(orb.get_primitive_tc(TCKind.tk_string)));
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TCKind kind = TestStruct2Helper.type().kind();
-            TEST(kind == TCKind.tk_struct);
+            assertTrue(kind == TCKind.tk_struct);
 
             String name = TestStruct2Helper.type().name();
-            TEST(name.equals("TestStruct2"));
+            assertTrue(name.equals("TestStruct2"));
 
             long count = TestStruct2Helper.type().member_count();
-            TEST(count == 4);
+            assertTrue(count == 4);
 
             String name0 = TestStruct2Helper.type().member_name(0);
-            TEST(name0.equals("s"));
+            assertTrue(name0.equals("s"));
 
             TypeCode type0 = TestStruct2Helper.type().member_type(0);
-            TEST(type0.equal(TestStruct1Helper.type()));
+            assertTrue(type0.equal(TestStruct1Helper.type()));
 
             String name1 = TestStruct2Helper.type().member_name(1);
-            TEST(name1.equals("a"));
+            assertTrue(name1.equals("a"));
 
             TypeCode type1 = TestStruct2Helper.type().member_type(1);
-            TEST(type1.equal(orb.get_primitive_tc(TCKind.tk_any)));
+            assertTrue(type1.equal(orb.get_primitive_tc(TCKind.tk_any)));
 
             String name2 = TestStruct2Helper.type().member_name(2);
-            TEST(name2.equals("da"));
+            assertTrue(name2.equals("da"));
 
             TypeCode type2 = TestStruct2Helper.type().member_type(2);
-            TEST(type2.equal(DoubleArrayHelper.type()));
+            assertTrue(type2.equal(DoubleArrayHelper.type()));
 
             String name3 = TestStruct2Helper.type().member_name(3);
-            TEST(name3.equals("sa"));
+            assertTrue(name3.equals("sa"));
 
             TypeCode type3 = TestStruct2Helper.type().member_type(3);
-            TEST(type3.equal(orb.create_array_tc(100, orb
-                    .get_primitive_tc(TCKind.tk_string))));
+            assertTrue(type3.equal(orb.create_array_tc(100, orb
+			.get_primitive_tc(TCKind.tk_string))));
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TCKind kind = TestStruct3Helper.type().kind();
-            TEST(kind == TCKind.tk_struct);
+            assertTrue(kind == TCKind.tk_struct);
 
             String name = TestStruct3Helper.type().name();
-            TEST(name.equals("TestStruct3"));
+            assertTrue(name.equals("TestStruct3"));
 
             int count = TestStruct3Helper.type().member_count();
-            TEST(count == 2);
+            assertTrue(count == 2);
 
             String name0 = TestStruct3Helper.type().member_name(0);
-            TEST(name0.equals("l"));
+            assertTrue(name0.equals("l"));
 
             TypeCode type0 = TestStruct3Helper.type().member_type(0);
-            TEST(type0.equal(orb.get_primitive_tc(TCKind.tk_long)));
+            assertTrue(type0.equal(orb.get_primitive_tc(TCKind.tk_long)));
 
             String name1 = TestStruct3Helper.type().member_name(1);
-            TEST(name1.equals("seq"));
+            assertTrue(name1.equals("seq"));
 
             TypeCode type1 = TestStruct3Helper.type().member_type(1);
             TypeCode contentType = type1.content_type();
-            TEST(contentType.equal(TestStruct3Helper.type()));
+            assertTrue(contentType.equal(TestStruct3Helper.type()));
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TCKind kind = TestStruct4Helper.type().kind();
-            TEST(kind == TCKind.tk_struct);
+            assertTrue(kind == TCKind.tk_struct);
 
             String name = TestStruct4Helper.type().name();
-            TEST(name.equals("TestStruct4"));
+            assertTrue(name.equals("TestStruct4"));
 
             int count = TestStruct4Helper.type().member_count();
-            TEST(count == 2);
+            assertTrue(count == 2);
 
             String name0 = TestStruct4Helper.type().member_name(0);
-            TEST(name0.equals("a"));
+            assertTrue(name0.equals("a"));
 
             TypeCode type0 = TestStruct4Helper.type().member_type(0);
-            TEST(type0.equal(TestStruct3Helper.type()));
+            assertTrue(type0.equal(TestStruct3Helper.type()));
 
             String name1 = TestStruct4Helper.type().member_name(1);
-            TEST(name1.equals("b"));
+            assertTrue(name1.equals("b"));
 
             TypeCode type1 = TestStruct4Helper.type().member_type(1);
             TypeCode contentType = type1.content_type();
-            TEST(contentType.equal(TestStruct3Helper.type()));
+            assertTrue(contentType.equal(TestStruct3Helper.type()));
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TCKind kind = TestUnion4Helper.type().kind();
-            TEST(kind == TCKind.tk_union);
+            assertTrue(kind == TCKind.tk_union);
 
             String name = TestUnion4Helper.type().name();
-            TEST(name.equals("TestUnion4"));
+            assertTrue(name.equals("TestUnion4"));
 
             int count = TestUnion4Helper.type().member_count();
-            TEST(count == 2);
+            assertTrue(count == 2);
 
             String name0 = TestUnion4Helper.type().member_name(0);
-            TEST(name0.equals("seq"));
+            assertTrue(name0.equals("seq"));
 
             TypeCode type0 = TestUnion4Helper.type().member_type(0);
             TypeCode contentType = type0.content_type();
-            TEST(contentType.equal(TestUnion4Helper.type()));
+            assertTrue(contentType.equal(TestUnion4Helper.type()));
 
             String name1 = TestUnion4Helper.type().member_name(1);
-            TEST(name1.equals("c"));
+            assertTrue(name1.equals("c"));
 
             TypeCode type1 = TestUnion4Helper.type().member_type(1);
-            TEST(type1.equal(orb.get_primitive_tc(TCKind.tk_char)));
+            assertTrue(type1.equal(orb.get_primitive_tc(TCKind.tk_char)));
 
             Any label = TestUnion4Helper.type().member_label(1);
             TypeCode labelType = label.type();
-            TEST(labelType.equal(org.apache.yoko.orb.OB.TypeCodeFactory
-                    .createPrimitiveTC(org.omg.CORBA_2_4.TCKind
-                            .from_int(org.omg.CORBA.TCKind._tk_short))));
+            assertTrue(labelType.equal(org.apache.yoko.orb.OB.TypeCodeFactory
+			.createPrimitiveTC(org.omg.CORBA_2_4.TCKind
+			        .from_int(org.omg.CORBA.TCKind._tk_short))));
             short labelValue = label.extract_short();
-            TEST(labelValue == 1);
+            assertTrue(labelValue == 1);
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             Any label = TestUnion1Helper.type().member_label(
                     TestUnion1Helper.type().default_index());
             byte defaultValue = label.extract_octet();
-            TEST(defaultValue == 0);
+            assertTrue(defaultValue == 0);
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             Any label = TestUnion2Helper.type().member_label(0);
             TestEnum enumValue = TestEnumHelper.extract(label);
-            TEST(enumValue.value() == TestEnum._A);
+            assertTrue(enumValue.value() == TestEnum._A);
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         } catch (org.omg.CORBA.TypeCodePackage.Bounds ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         try {
             TypeCode p;
 
             p = RepositoryIdHelper.type();
-            TEST(p.name().equals("RepositoryId"));
+            assertTrue(p.name().equals("RepositoryId"));
 
             p = ScopedNameHelper.type();
-            TEST(p.name().equals("ScopedName"));
+            assertTrue(p.name().equals("ScopedName"));
 
             p = IdentifierHelper.type();
-            TEST(p.name().equals("Identifier"));
+            assertTrue(p.name().equals("Identifier"));
 
             p = DefinitionKindHelper.type();
-            TEST(p.name().equals("DefinitionKind"));
+            assertTrue(p.name().equals("DefinitionKind"));
 
             p = IRObjectHelper.type();
-            TEST(p.name().equals("IRObject"));
+            assertTrue(p.name().equals("IRObject"));
 
             p = VersionSpecHelper.type();
-            TEST(p.name().equals("VersionSpec"));
+            assertTrue(p.name().equals("VersionSpec"));
 
             p = ContainedHelper.type();
-            TEST(p.name().equals("Contained"));
+            assertTrue(p.name().equals("Contained"));
 
             p = org.omg.CORBA.ContainedPackage.DescriptionHelper.type();
-            TEST(p.name().equals("Description"));
+            assertTrue(p.name().equals("Description"));
 
             p = InterfaceDefSeqHelper.type();
-            TEST(p.name().equals("InterfaceDefSeq"));
+            assertTrue(p.name().equals("InterfaceDefSeq"));
 
             p = ContainedSeqHelper.type();
-            TEST(p.name().equals("ContainedSeq"));
+            assertTrue(p.name().equals("ContainedSeq"));
 
             p = StructMemberHelper.type();
-            TEST(p.name().equals("StructMember"));
+            assertTrue(p.name().equals("StructMember"));
 
             p = StructMemberSeqHelper.type();
-            TEST(p.name().equals("StructMemberSeq"));
+            assertTrue(p.name().equals("StructMemberSeq"));
 
             p = UnionMemberHelper.type();
-            TEST(p.name().equals("UnionMember"));
+            assertTrue(p.name().equals("UnionMember"));
 
             p = UnionMemberSeqHelper.type();
-            TEST(p.name().equals("UnionMemberSeq"));
+            assertTrue(p.name().equals("UnionMemberSeq"));
 
             p = EnumMemberSeqHelper.type();
-            TEST(p.name().equals("EnumMemberSeq"));
+            assertTrue(p.name().equals("EnumMemberSeq"));
 
             p = ContainerHelper.type();
-            TEST(p.name().equals("Container"));
+            assertTrue(p.name().equals("Container"));
 
             p = org.omg.CORBA.ContainerPackage.DescriptionHelper.type();
-            TEST(p.name().equals("Description"));
+            assertTrue(p.name().equals("Description"));
 
             p = org.omg.CORBA.ContainerPackage.DescriptionSeqHelper.type();
-            TEST(p.name().equals("DescriptionSeq"));
+            assertTrue(p.name().equals("DescriptionSeq"));
 
             p = IDLTypeHelper.type();
-            TEST(p.name().equals("IDLType"));
+            assertTrue(p.name().equals("IDLType"));
 
             p = PrimitiveKindHelper.type();
-            TEST(p.name().equals("PrimitiveKind"));
+            assertTrue(p.name().equals("PrimitiveKind"));
 
             p = RepositoryHelper.type();
-            TEST(p.name().equals("Repository"));
+            assertTrue(p.name().equals("Repository"));
 
             p = ModuleDefHelper.type();
-            TEST(p.name().equals("ModuleDef"));
+            assertTrue(p.name().equals("ModuleDef"));
 
             p = ModuleDescriptionHelper.type();
-            TEST(p.name().equals("ModuleDescription"));
+            assertTrue(p.name().equals("ModuleDescription"));
 
             p = ConstantDefHelper.type();
-            TEST(p.name().equals("ConstantDef"));
+            assertTrue(p.name().equals("ConstantDef"));
 
             p = ConstantDescriptionHelper.type();
-            TEST(p.name().equals("ConstantDescription"));
+            assertTrue(p.name().equals("ConstantDescription"));
 
             p = TypedefDefHelper.type();
-            TEST(p.name().equals("TypedefDef"));
+            assertTrue(p.name().equals("TypedefDef"));
 
             p = TypeDescriptionHelper.type();
-            TEST(p.name().equals("TypeDescription"));
+            assertTrue(p.name().equals("TypeDescription"));
 
             p = StructDefHelper.type();
-            TEST(p.name().equals("StructDef"));
+            assertTrue(p.name().equals("StructDef"));
 
             p = UnionDefHelper.type();
-            TEST(p.name().equals("UnionDef"));
+            assertTrue(p.name().equals("UnionDef"));
 
             p = EnumDefHelper.type();
-            TEST(p.name().equals("EnumDef"));
+            assertTrue(p.name().equals("EnumDef"));
 
             p = AliasDefHelper.type();
-            TEST(p.name().equals("AliasDef"));
+            assertTrue(p.name().equals("AliasDef"));
 
             p = PrimitiveDefHelper.type();
-            TEST(p.name().equals("PrimitiveDef"));
+            assertTrue(p.name().equals("PrimitiveDef"));
 
             p = StringDefHelper.type();
-            TEST(p.name().equals("StringDef"));
+            assertTrue(p.name().equals("StringDef"));
 
             p = SequenceDefHelper.type();
-            TEST(p.name().equals("SequenceDef"));
+            assertTrue(p.name().equals("SequenceDef"));
 
             p = ArrayDefHelper.type();
-            TEST(p.name().equals("ArrayDef"));
+            assertTrue(p.name().equals("ArrayDef"));
 
             p = ExceptionDefHelper.type();
-            TEST(p.name().equals("ExceptionDef"));
+            assertTrue(p.name().equals("ExceptionDef"));
 
             p = ExceptionDescriptionHelper.type();
-            TEST(p.name().equals("ExceptionDescription"));
+            assertTrue(p.name().equals("ExceptionDescription"));
 
             p = AttributeModeHelper.type();
-            TEST(p.name().equals("AttributeMode"));
+            assertTrue(p.name().equals("AttributeMode"));
 
             p = AttributeDefHelper.type();
-            TEST(p.name().equals("AttributeDef"));
+            assertTrue(p.name().equals("AttributeDef"));
 
             p = AttributeDescriptionHelper.type();
-            TEST(p.name().equals("AttributeDescription"));
+            assertTrue(p.name().equals("AttributeDescription"));
 
             p = OperationModeHelper.type();
-            TEST(p.name().equals("OperationMode"));
+            assertTrue(p.name().equals("OperationMode"));
 
             p = ParameterModeHelper.type();
-            TEST(p.name().equals("ParameterMode"));
+            assertTrue(p.name().equals("ParameterMode"));
 
             p = ParameterDescriptionHelper.type();
-            TEST(p.name().equals("ParameterDescription"));
+            assertTrue(p.name().equals("ParameterDescription"));
 
             p = ParDescriptionSeqHelper.type();
-            TEST(p.name().equals("ParDescriptionSeq"));
+            assertTrue(p.name().equals("ParDescriptionSeq"));
 
             p = ContextIdentifierHelper.type();
-            TEST(p.name().equals("ContextIdentifier"));
+            assertTrue(p.name().equals("ContextIdentifier"));
 
             p = ContextIdSeqHelper.type();
-            TEST(p.name().equals("ContextIdSeq"));
+            assertTrue(p.name().equals("ContextIdSeq"));
 
             p = ExceptionDefSeqHelper.type();
-            TEST(p.name().equals("ExceptionDefSeq"));
+            assertTrue(p.name().equals("ExceptionDefSeq"));
 
             p = ExcDescriptionSeqHelper.type();
-            TEST(p.name().equals("ExcDescriptionSeq"));
+            assertTrue(p.name().equals("ExcDescriptionSeq"));
 
             p = OperationDefHelper.type();
-            TEST(p.name().equals("OperationDef"));
+            assertTrue(p.name().equals("OperationDef"));
 
             p = OperationDescriptionHelper.type();
-            TEST(p.name().equals("OperationDescription"));
+            assertTrue(p.name().equals("OperationDescription"));
 
             p = RepositoryIdSeqHelper.type();
-            TEST(p.name().equals("RepositoryIdSeq"));
+            assertTrue(p.name().equals("RepositoryIdSeq"));
 
             p = OpDescriptionSeqHelper.type();
-            TEST(p.name().equals("OpDescriptionSeq"));
+            assertTrue(p.name().equals("OpDescriptionSeq"));
 
             p = AttrDescriptionSeqHelper.type();
-            TEST(p.name().equals("AttrDescriptionSeq"));
+            assertTrue(p.name().equals("AttrDescriptionSeq"));
 
             p = InterfaceDefHelper.type();
-            TEST(p.name().equals("InterfaceDef"));
+            assertTrue(p.name().equals("InterfaceDef"));
 
             p = org.omg.CORBA.InterfaceDefPackage.FullInterfaceDescriptionHelper
                     .type();
-            TEST(p.name().equals("FullInterfaceDescription"));
+            assertTrue(p.name().equals("FullInterfaceDescription"));
 
             p = InterfaceDescriptionHelper.type();
-            TEST(p.name().equals("InterfaceDescription"));
+            assertTrue(p.name().equals("InterfaceDescription"));
         } catch (org.omg.CORBA.TypeCodePackage.BadKind ex) {
-            TEST(false);
+            assertTrue(false);
         }
 
         //
@@ -491,7 +494,7 @@
                     members[0].type = orb
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_struct_tc(bogusIds[i], "foo", members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -507,7 +510,7 @@
                     members[0].label = orb.create_any();
                     members[0].label.insert_short((short) 1);
                     orb.create_union_tc(bogusIds[i], "foo", tcShort, members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -516,7 +519,7 @@
                     org.omg.CORBA.TypeCode tcShort = orb
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_alias_tc(bogusIds[i], "foo", tcShort);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -528,14 +531,14 @@
                     members[0].type = orb
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_exception_tc(bogusIds[i], "foo", members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_interface_tc(bogusIds[i], "foo");
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -544,7 +547,7 @@
                     org.omg.CORBA.ValueMember[] members = new org.omg.CORBA.ValueMember[0];
                     orb.create_value_tc(bogusIds[i], "foo",
                             org.omg.CORBA.VM_NONE.value, null, members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -553,21 +556,21 @@
                     org.omg.CORBA.TypeCode tcShort = orb
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_value_box_tc(bogusIds[i], "foo", tcShort);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_native_tc(bogusIds[i], "foo");
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_abstract_interface_tc(bogusIds[i], "foo");
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -575,7 +578,7 @@
                 try {
                     ((org.omg.CORBA_2_4.ORB) orb).create_local_interface_tc(
                             bogusIds[i], "foo");
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -585,7 +588,7 @@
         //
         // Check IDL name
         //
-        {
+        if (CHECK_IDL_NAMES) {
             String[] bogusNames = { "_foo", "1foo", "f.oo" };
             for (int i = 0; i < bogusNames.length; i++) {
                 try {
@@ -595,7 +598,7 @@
                     members[0].type = orb
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_struct_tc("IDL:foo:1.0", bogusNames[i], members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -612,7 +615,7 @@
                     members[0].label.insert_short((short) 1);
                     orb.create_union_tc("IDL:foo:1.0", bogusNames[i], tcShort,
                             members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -621,7 +624,7 @@
                     org.omg.CORBA.TypeCode tcShort = orb
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_alias_tc("IDL:foo:1.0", bogusNames[i], tcShort);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -634,14 +637,14 @@
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_exception_tc("IDL:foo:1.0", bogusNames[i],
                             members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_interface_tc("IDL:foo:1.0", bogusNames[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -650,7 +653,7 @@
                     org.omg.CORBA.ValueMember[] members = new org.omg.CORBA.ValueMember[0];
                     orb.create_value_tc("IDL:foo:1.0", bogusNames[i],
                             org.omg.CORBA.VM_NONE.value, null, members);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -660,14 +663,14 @@
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_value_box_tc("IDL:foo:1.0", bogusNames[i],
                             tcShort);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_native_tc("IDL:foo:1.0", bogusNames[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -675,7 +678,7 @@
                 try {
                     orb.create_abstract_interface_tc("IDL:foo:1.0",
                             bogusNames[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -683,7 +686,7 @@
                 try {
                     ((org.omg.CORBA_2_4.ORB) orb).create_local_interface_tc(
                             "IDL:foo:1.0", bogusNames[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -710,7 +713,7 @@
                     seq[0].name = "v";
                     seq[0].type = types[i];
                     orb.create_struct_tc("IDL:foo:1.0", "foo", seq);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
@@ -724,7 +727,7 @@
                     seq[0].label = orb.create_any();
                     seq[0].label.insert_short((short) 1);
                     orb.create_union_tc("IDL:foo:1.0", "foo", types[i], seq);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_PARAM ex) {
                     // Expected
                 }
@@ -739,14 +742,14 @@
                     org.omg.CORBA.TypeCode disc = orb
                             .get_primitive_tc(org.omg.CORBA.TCKind.tk_short);
                     orb.create_union_tc("IDL:foo:1.0", "foo", disc, seq);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_alias_tc("IDL:foo:1.0", "foo", types[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
@@ -757,21 +760,21 @@
                     seq[0].name = "v";
                     seq[0].type = types[i];
                     orb.create_exception_tc("IDL:foo:1.0", "foo", seq);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_sequence_tc(0, types[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_array_tc(1, types[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
@@ -784,14 +787,14 @@
                     seq[0].access = org.omg.CORBA.PUBLIC_MEMBER.value;
                     orb.create_value_tc("IDL:foo:1.0", "foo",
                             org.omg.CORBA.VM_NONE.value, null, seq);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
 
                 try {
                     orb.create_value_box_tc("IDL:foo:1.0", "foo", types[i]);
-                    TEST(false);
+                    assertTrue(false);
                 } catch (org.omg.CORBA.BAD_TYPECODE ex) {
                     // Expected
                 }
diff --git a/yoko-core/src/test/java/test/types/TestUnion.java b/yoko-core/src/test/java/test/types/TestUnion.java
index 6e566c1..7364e40 100644
--- a/yoko-core/src/test/java/test/types/TestUnion.java
+++ b/yoko-core/src/test/java/test/types/TestUnion.java
@@ -17,25 +17,28 @@
 
 package test.types;
 
+import static org.junit.Assert.assertTrue;
+
 import java.util.Properties;
+
 import org.omg.CORBA.*;
 
 public class TestUnion extends test.common.TestBase {
     TestUnion(ORB orb) {
         TestUnion1 u = new TestUnion1();
         u.l(123);
-        TEST(u.l() == 123);
-        TEST(u.discriminator() == -1);
+        assertTrue(u.l() == 123);
+        assertTrue(u.discriminator() == -1);
 
         u.tc(-6, TestUnion1Helper.type());
-        TEST(u.discriminator() == -6);
-        TEST(u.tc().equal(TestUnion1Helper.type()));
+        assertTrue(u.discriminator() == -6);
+        assertTrue(u.tc().equal(TestUnion1Helper.type()));
         u.tc(4, TestUnion1Helper.type());
-        TEST(u.discriminator() == 4);
-        TEST(u.tc().equal(TestUnion1Helper.type()));
+        assertTrue(u.discriminator() == 4);
+        assertTrue(u.tc().equal(TestUnion1Helper.type()));
         u.tc(999, TestUnion1Helper.type());
-        TEST(u.discriminator() == 999);
-        TEST(u.tc().equal(TestUnion1Helper.type()));
+        assertTrue(u.discriminator() == 999);
+        assertTrue(u.tc().equal(TestUnion1Helper.type()));
 
         double arr[][][] = new double[10][20][30];
         arr[2][2][2] = 3.14;
@@ -44,14 +47,14 @@
 
         u.a(arr);
         double arr2[][][] = u.a();
-        TEST(arr2[2][2][2] == 3.14);
-        TEST(arr2[0][0][0] == 1234);
-        TEST(arr2[9][19][29] == 1.23E23);
-        TEST(u.discriminator() == -2);
+        assertTrue(arr2[2][2][2] == 3.14);
+        assertTrue(arr2[0][0][0] == 1234);
+        assertTrue(arr2[9][19][29] == 1.23E23);
+        assertTrue(u.discriminator() == -2);
 
         u.s("Hello!");
-        TEST(u.s().equals("Hello!"));
-        TEST(u.discriminator() == -3);
+        assertTrue(u.s().equals("Hello!"));
+        assertTrue(u.discriminator() == -3);
 
         TestStruct2 ts = new TestStruct2();
         ts.s = new TestStruct1();
@@ -72,76 +75,76 @@
             ts.sa[i] = "";
         ts.sa[50] = "Hi!";
         u.str(0, ts);
-        TEST(u.discriminator() == 0);
+        assertTrue(u.discriminator() == 0);
         u.str(1, ts);
-        TEST(u.discriminator() == 1);
+        assertTrue(u.discriminator() == 1);
         u.str(2, ts);
-        TEST(u.discriminator() == 2);
+        assertTrue(u.discriminator() == 2);
         u.str(3, ts);
-        TEST(u.discriminator() == 3);
+        assertTrue(u.discriminator() == 3);
         u.str(-4, ts);
-        TEST(u.discriminator() == -4);
+        assertTrue(u.discriminator() == -4);
         u.str(-5, ts);
-        TEST(u.discriminator() == -5);
-        TEST(u.str().s.s == -32768);
-        TEST(u.str().s.l == 2147483647);
-        TEST(u.str().s.d == 1E200);
-        TEST(u.str().s.b == true);
-        TEST(u.str().s.c == 'x');
-        TEST(u.str().s.o == (byte) 0xff);
-        TEST(u.str().s.str.equals("abc"));
+        assertTrue(u.discriminator() == -5);
+        assertTrue(u.str().s.s == -32768);
+        assertTrue(u.str().s.l == 2147483647);
+        assertTrue(u.str().s.d == 1E200);
+        assertTrue(u.str().s.b == true);
+        assertTrue(u.str().s.c == 'x');
+        assertTrue(u.str().s.o == (byte) 0xff);
+        assertTrue(u.str().s.str.equals("abc"));
         TestUnion1 u2 = TestUnion1Helper.extract(u.str().a);
-        TEST(u2.s().equals("Hello!"));
-        TEST(u2.discriminator() == -3);
-        TEST(u.str().da[0][0][0] == 1.23);
-        TEST(u.str().da[2][3][4] == -1.11);
-        TEST(u.str().sa[50].equals("Hi!"));
+        assertTrue(u2.s().equals("Hello!"));
+        assertTrue(u2.discriminator() == -3);
+        assertTrue(u.str().da[0][0][0] == 1.23);
+        assertTrue(u.str().da[2][3][4] == -1.11);
+        assertTrue(u.str().sa[50].equals("Hi!"));
 
         TestUnion2 u3 = new TestUnion2();
         u3.un(u);
-        TEST(u3.discriminator() == TestEnum.C);
-        TEST(u3.un().discriminator() == -5);
-        TEST(u3.un().str().s.s == -32768);
-        TEST(u3.un().str().s.l == 2147483647);
-        TEST(u3.un().str().s.d == 1E200);
-        TEST(u3.un().str().s.b == true);
-        TEST(u3.un().str().s.c == 'x');
-        TEST(u3.un().str().s.o == (byte) 0xff);
-        TEST(u3.un().str().s.str.equals("abc"));
+        assertTrue(u3.discriminator() == TestEnum.C);
+        assertTrue(u3.un().discriminator() == -5);
+        assertTrue(u3.un().str().s.s == -32768);
+        assertTrue(u3.un().str().s.l == 2147483647);
+        assertTrue(u3.un().str().s.d == 1E200);
+        assertTrue(u3.un().str().s.b == true);
+        assertTrue(u3.un().str().s.c == 'x');
+        assertTrue(u3.un().str().s.o == (byte) 0xff);
+        assertTrue(u3.un().str().s.str.equals("abc"));
         TestUnion1 u4 = TestUnion1Helper.extract(u.str().a);
-        TEST(u4.s().equals("Hello!"));
-        TEST(u4.discriminator() == -3);
-        TEST(u3.un().str().da[0][0][0] == 1.23);
-        TEST(u3.un().str().da[2][3][4] == -1.11);
-        TEST(u3.un().str().sa[50].equals("Hi!"));
+        assertTrue(u4.s().equals("Hello!"));
+        assertTrue(u4.discriminator() == -3);
+        assertTrue(u3.un().str().da[0][0][0] == 1.23);
+        assertTrue(u3.un().str().da[2][3][4] == -1.11);
+        assertTrue(u3.un().str().sa[50].equals("Hi!"));
 
         Any any = orb.create_any();
         TestUnion2Helper.insert(any, u3);
         TestUnion2 u5 = TestUnion2Helper.extract(any);
-        TEST(u5.discriminator() == TestEnum.C);
-        TEST(u5.un().discriminator() == -5);
-        TEST(u5.un().str().s.s == -32768);
-        TEST(u5.un().str().s.l == 2147483647);
-        TEST(u5.un().str().s.d == 1E200);
-        TEST(u5.un().str().s.b == true);
-        TEST(u5.un().str().s.c == 'x');
-        TEST(u5.un().str().s.o == (byte) 0xff);
-        TEST(u5.un().str().s.str.equals("abc"));
+        assertTrue(u5.discriminator() == TestEnum.C);
+        assertTrue(u5.un().discriminator() == -5);
+        assertTrue(u5.un().str().s.s == -32768);
+        assertTrue(u5.un().str().s.l == 2147483647);
+        assertTrue(u5.un().str().s.d == 1E200);
+        assertTrue(u5.un().str().s.b == true);
+        assertTrue(u5.un().str().s.c == 'x');
+        assertTrue(u5.un().str().s.o == (byte) 0xff);
+        assertTrue(u5.un().str().s.str.equals("abc"));
         TestUnion1 u6 = TestUnion1Helper.extract(u.str().a);
-        TEST(u6.s().equals("Hello!"));
-        TEST(u6.discriminator() == -3);
-        TEST(u5.un().str().da[0][0][0] == 1.23);
-        TEST(u5.un().str().da[2][3][4] == -1.11);
-        TEST(u5.un().str().sa[50].equals("Hi!"));
+        assertTrue(u6.s().equals("Hello!"));
+        assertTrue(u6.discriminator() == -3);
+        assertTrue(u5.un().str().da[0][0][0] == 1.23);
+        assertTrue(u5.un().str().da[2][3][4] == -1.11);
+        assertTrue(u5.un().str().sa[50].equals("Hi!"));
 
         TestUnion3 u7 = new TestUnion3();
         u7.__default();
         u7.c('a', '1');
-        TEST(u7.discriminator() == 'a');
-        TEST(u7.c() == '1');
+        assertTrue(u7.discriminator() == 'a');
+        assertTrue(u7.c() == '1');
         u7.c('b', '1');
-        TEST(u7.discriminator() == 'b');
-        TEST(u7.c() == '1');
+        assertTrue(u7.discriminator() == 'b');
+        assertTrue(u7.c() == '1');
     }
 
     public static void main(String args[]) {
diff --git a/yoko-core/src/test/java/test/util/MultiException.java b/yoko-core/src/test/java/test/util/MultiException.java
new file mode 100644
index 0000000..23f9984
--- /dev/null
+++ b/yoko-core/src/test/java/test/util/MultiException.java
@@ -0,0 +1,61 @@
+package test.util;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+public class MultiException extends RuntimeException {
+    private static final String SEP = "--------------------------------------------------------------------------------";
+    private static final String NULL_COUNT_FORMAT = SEP + "%n%d \u2715 null%n" + SEP + "%n";
+    private static final String ENTRY_FORMAT = "%n" + SEP + "%n%d \u2715 %s" + SEP + "%n";
+    private Map<String, Integer> map = new TreeMap<>();
+    private int nullCount;
+
+    public boolean isEmpty() {
+        return map.isEmpty();
+    }
+
+    public Integer add(Throwable t) {
+        if (t == null) return nullCount++;
+        String desc = getDescription(t);
+        Integer count = map.get(desc);
+        return count == null ?
+                map.put(desc, 1) :
+                map.put(desc, ++count);
+    }
+
+    private String getDescription(Throwable t) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        pw.println(t);
+        pw.println(SEP);
+        t.printStackTrace(pw);
+        pw.flush();
+        return sw.getBuffer().toString();
+    }
+
+    public <T extends Throwable, F extends Future<T>> MultiException(Iterable<F> results) {
+        for (F f : results)
+            try {
+                add(f.get());
+            } catch (InterruptedException | ExecutionException e) {
+                add(e);
+            }
+    }
+
+    @Override
+    public void printStackTrace(PrintStream s) {
+        s.printf(NULL_COUNT_FORMAT, nullCount);
+        for (Map.Entry<String, Integer> e : map.entrySet()) s.printf(ENTRY_FORMAT, e.getValue(), e.getKey());
+    }
+
+    @Override
+    public void printStackTrace(PrintWriter s) {
+        s.printf(NULL_COUNT_FORMAT, nullCount);
+        for (Map.Entry<String, Integer> e : map.entrySet()) s.printf(ENTRY_FORMAT, e.getValue(), e.getKey());
+    }
+}
diff --git a/yoko-core/src/test/java/test/util/Skellington.java b/yoko-core/src/test/java/test/util/Skellington.java
new file mode 100644
index 0000000..5e2f0b5
--- /dev/null
+++ b/yoko-core/src/test/java/test/util/Skellington.java
@@ -0,0 +1,127 @@
+package test.util;
+
+import org.apache.yoko.orb.OBPortableServer.POAHelper;
+import org.junit.Assert;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.ORBPackage.InvalidName;
+import org.omg.CORBA.SystemException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.ResponseHandler;
+import org.omg.CORBA.portable.UnknownException;
+import org.omg.PortableServer.POA;
+import org.omg.PortableServer.POAManagerPackage.AdapterInactive;
+import org.omg.PortableServer.POAPackage.ObjectNotActive;
+import org.omg.PortableServer.POAPackage.ServantAlreadyActive;
+import org.omg.PortableServer.POAPackage.ServantNotActive;
+import org.omg.PortableServer.POAPackage.WrongPolicy;
+import org.omg.PortableServer.Servant;
+
+import javax.rmi.CORBA.Tie;
+import javax.rmi.CORBA.Util;
+import javax.rmi.CORBA.ValueHandler;
+import java.lang.reflect.Method;
+import java.rmi.NoSuchObjectException;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.*;
+
+public abstract class Skellington extends Servant implements Tie, Remote {
+    private final Collection<Class<? extends Remote>> interfaceClasses;
+    private final String[] ids;
+
+    public Skellington() {
+        Set<Class<? extends Remote>> ifaces = new HashSet<>();
+        for (Class<?> c = this.getClass(); c != Object.class; c = c.getSuperclass()) {
+            NEXT_CLASS: for (Class<?> iface: c.getInterfaces()) {
+                if (Remote.class.isAssignableFrom(iface)) {
+                    for (Method m : iface.getMethods()) {
+                        if (Arrays.asList(m.getExceptionTypes()).contains(RemoteException.class))
+                            continue;
+                        continue NEXT_CLASS;
+                    }
+                    // there were no non-remote methods, so add the interface
+                    ifaces.add((Class<? extends Remote>)iface);
+                }
+            }
+        }
+        final ValueHandler vh = Util.createValueHandler();
+        this.interfaceClasses = Collections.unmodifiableSet(ifaces);
+        this.ids = new String[interfaceClasses.size()];
+        int index = 0;
+        for (Class<?> c : interfaceClasses)
+            this.ids[index++] = vh.getRMIRepositoryID(c);
+    }
+
+    public Skellington(Class<? extends Remote>... interfaces) {
+        final ValueHandler vh = Util.createValueHandler();
+        ids = new String[interfaces.length];
+        List<Class<? extends Remote>> iflst = new ArrayList<>();
+        for (int i = 0; i < interfaces.length; i++) {
+            Assert.assertTrue(interfaces[i].isInterface());
+            iflst.add(interfaces[i]);
+            ids[i] = vh.getRMIRepositoryID(interfaces[i]);
+        }
+        this.interfaceClasses = Collections.unmodifiableList(iflst);
+    }
+
+    @Override
+    public String[] _all_interfaces(POA poa, byte[] objectId) {
+        return ids.clone();
+    }
+
+    @Override
+    public org.omg.CORBA.Object thisObject() {
+        return _this_object();
+    }
+
+    @Override
+    public void deactivate() throws NoSuchObjectException {
+        try{
+            _poa().deactivate_object(_poa().servant_to_id(this));
+        } catch (WrongPolicy |ObjectNotActive |ServantNotActive ignored){}
+    }
+
+    @Override
+    public ORB orb() {return _orb();}
+
+    @Override
+    public void orb(ORB orb) {
+        try {
+            ((org.omg.CORBA_2_3.ORB)orb).set_delegate(this);
+        } catch(ClassCastException e) {
+            throw new BAD_PARAM("POA Servant requires an instance of org.omg.CORBA_2_3.ORB");
+        }
+    }
+
+    @Override
+    public void setTarget(Remote target) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Remote getTarget() {
+        return this;
+    }
+
+    @Override
+    public OutputStream  _invoke(String method, InputStream _in, ResponseHandler reply) throws SystemException {
+        try {
+            return dispatch(method, (org.omg.CORBA_2_3.portable.InputStream) _in, reply);
+        } catch (SystemException ex) {
+            throw ex;
+        } catch (Throwable ex) {
+            throw new UnknownException(ex);
+        }
+    }
+
+    public String publish(ORB serverORB) throws InvalidName, AdapterInactive, ServantAlreadyActive, WrongPolicy {
+        POA rootPOA = POAHelper.narrow(serverORB.resolve_initial_references("RootPOA"));
+        rootPOA.the_POAManager().activate();
+        rootPOA.activate_object(this);
+        return serverORB.object_to_string(thisObject());
+    }
+
+    protected abstract OutputStream dispatch(String method, org.omg.CORBA_2_3.portable.InputStream in, ResponseHandler reply) throws RemoteException;
+}
diff --git a/yoko-osgi/pom.xml b/yoko-osgi/pom.xml
index 7a9ec0e..8f9468a 100644
--- a/yoko-osgi/pom.xml
+++ b/yoko-osgi/pom.xml
@@ -23,21 +23,42 @@
         <groupId>org.apache.yoko</groupId>
         <version>1.5-SNAPSHOT</version>
     </parent>
+
     <artifactId>yoko-osgi</artifactId>
-    <name>Apache Yoko OSGI Support</name>
+
+    <name>Apache Yoko OSGi Utilities</name>
+
     <packaging>bundle</packaging>
+
     <dependencies>
         <!-- this contains the osgi-relevant classes in the endorsed dir -->
         <dependency>
-            <groupId>org.apache.yoko</groupId>
-            <artifactId>yoko-spec-corba</artifactId>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>5.0.0</version>
             <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.osgi</groupId>
-            <artifactId>org.osgi.core</artifactId>
-            <version>4.3.0</version>
+            <artifactId>org.osgi.compendium</artifactId>
+            <version>5.0.0</version>
             <scope>provided</scope>
         </dependency>
     </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.yoko.osgi
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/yoko-spec-corba/src/main/java/org/apache/yoko/osgi/ProviderLocator.java b/yoko-osgi/src/main/java/org/apache/yoko/osgi/ProviderLocator.java
similarity index 100%
rename from yoko-spec-corba/src/main/java/org/apache/yoko/osgi/ProviderLocator.java
rename to yoko-osgi/src/main/java/org/apache/yoko/osgi/ProviderLocator.java
diff --git a/yoko-spec-corba/src/main/java/org/apache/yoko/osgi/ProviderRegistry.java b/yoko-osgi/src/main/java/org/apache/yoko/osgi/ProviderRegistry.java
similarity index 100%
rename from yoko-spec-corba/src/main/java/org/apache/yoko/osgi/ProviderRegistry.java
rename to yoko-osgi/src/main/java/org/apache/yoko/osgi/ProviderRegistry.java
diff --git a/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderBean.java b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderBean.java
index 688ff61..8a8d452 100644
--- a/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderBean.java
+++ b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderBean.java
@@ -20,6 +20,7 @@
 
 package org.apache.yoko.osgi.locator;
 
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.osgi.framework.Bundle;
@@ -47,7 +48,8 @@
                         Register providerRegistry,
                         Integer priority) {
         bundleProviderLoader = new BundleProviderLoader(key, className, bundle, priority == null? -1: priority);
-        log.finer("ProviderBean: " + bundleProviderLoader);
+        if (log.isLoggable(Level.FINER))
+            log.finer("ProviderBean: " + bundleProviderLoader);
         this.providerRegistry = providerRegistry;
     }
 
diff --git a/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderRegistryImpl.java b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderRegistryImpl.java
index 5b57e50..28fa885 100644
--- a/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderRegistryImpl.java
+++ b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ProviderRegistryImpl.java
@@ -25,12 +25,13 @@
 import java.util.logging.Logger;
 
 import org.apache.yoko.osgi.ProviderLocator;
+import org.apache.yoko.osgi.ProviderRegistry;
 
 /**
  * The implementation of the provider registry used to store
  * the bundle registrations.
  */
-public class ProviderRegistryImpl implements org.apache.yoko.osgi.ProviderRegistry, Register {
+public class ProviderRegistryImpl implements ProviderRegistry, Register {
 
     private static final Logger log = Logger.getLogger(ProviderRegistryImpl.class.getName());
     // our mapping between a provider id and the implementation information.  There
@@ -54,7 +55,8 @@
      * @param provider The loader used to resolve the provider class.
      */
     public void registerProvider(BundleProviderLoader provider) {
-        log(Level.FINE, "registering provider " + provider);
+        if (log.isLoggable(Level.FINE))
+            log.log(Level.FINE, "registering provider " + provider);
         providers.register(provider);
     }
 
@@ -64,7 +66,8 @@
      * @param provider The provider registration instance
      */
     public void unregisterProvider(BundleProviderLoader provider) {
-        log(Level.FINE, "unregistering provider " + provider);
+        if (log.isLoggable(Level.FINE))
+            log.log(Level.FINE, "unregistering provider " + provider);
         providers.unregister(provider);
     }
 
@@ -75,7 +78,8 @@
      * @param provider The loader used to resolve the provider class.
      */
     public void registerService(BundleProviderLoader provider) {
-        log(Level.FINE, "registering service " + provider);
+        if (log.isLoggable(Level.FINE))
+            log.log(Level.FINE, "registering service " + provider);
         serviceProviders.register(provider);
     }
 
@@ -85,7 +89,8 @@
      * @param provider The provider registration instance
      */
     public void unregisterService(BundleProviderLoader provider) {
-        log(Level.FINE, "unregistering service " + provider);
+        if (log.isLoggable(Level.FINE))
+            log.log(Level.FINE, "unregistering service " + provider);
         serviceProviders.unregister(provider);
     }
 
@@ -241,10 +246,6 @@
         return null;
     }
 
-    private void log(Level level, String message) {
-        log.log(level, message);
-    }
-
     /**
      * Holder class for information about a given collection of
      * id to provider mappings.  Used for both the providers and
@@ -297,7 +298,8 @@
         private synchronized BundleProviderLoader getLoader(String id) {
             // synchronize on the registry instance
             if (registry != null) {
-                log.fine("registry: " + registry);
+                if (log.isLoggable(Level.FINE))
+                    log.fine("registry: " + registry);
                 // return the first match, if any
                 List<BundleProviderLoader> list = registry.get(id);
                 if (list != null && !list.isEmpty()) {
diff --git a/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ServiceBean.java b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ServiceBean.java
index 7876495..b42f3fe 100644
--- a/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ServiceBean.java
+++ b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/ServiceBean.java
@@ -20,6 +20,7 @@
 
 package org.apache.yoko.osgi.locator;
 
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import org.osgi.framework.Bundle;
@@ -47,7 +48,8 @@
                        Register providerRegistry,
                        Integer priority) {
         bundleProviderLoader = new BundleProviderLoader(key, className, bundle, priority == null? -1: priority);
-        log.finer("ServiceBean: " + bundleProviderLoader);
+        if (log.isLoggable(Level.FINER))
+            log.finer("ServiceBean: " + bundleProviderLoader);
         this.providerRegistry = providerRegistry;
     }
 
diff --git a/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/activator/AbstractBundleActivator.java b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/activator/AbstractBundleActivator.java
new file mode 100644
index 0000000..c21cf42
--- /dev/null
+++ b/yoko-osgi/src/main/java/org/apache/yoko/osgi/locator/activator/AbstractBundleActivator.java
@@ -0,0 +1,107 @@
+package org.apache.yoko.osgi.locator.activator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.yoko.osgi.locator.BundleProviderLoader;
+import org.apache.yoko.osgi.locator.Register;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+
+public abstract class AbstractBundleActivator implements BundleActivator {
+
+	public static class Info {
+	    final String id;
+	    final String className;
+        final int priority;
+        
+		public Info(String id, String className, int priority) {
+			super();
+			this.id = id;
+			this.className = className;
+			this.priority = priority;
+		}
+		
+	}
+	private final Info[] providerInfo;
+    private final Info[] serviceInfo;
+	private ServiceTracker<Register, Register> tracker;
+	private BundleContext context;
+	private boolean registered;
+	private final List<BundleProviderLoader> providerLoaders = new ArrayList<BundleProviderLoader>();
+	private final List<BundleProviderLoader> serviceLoaders = new ArrayList<BundleProviderLoader>();
+	
+	public AbstractBundleActivator(Info[] providerInfo, Info[] serviceInfo) {
+		this.providerInfo = providerInfo;
+		this.serviceInfo = serviceInfo;
+	}
+
+	public void start(final BundleContext context) throws Exception {
+		this.context = context;
+		tracker = new ServiceTracker<Register, Register>(context, Register.class, new ServiceTrackerCustomizer<Register, Register>() {
+
+			public Register addingService(ServiceReference<Register> reference) {
+				Register register = context.getService(reference);
+				register(register);
+				return register;
+			}
+
+			public void modifiedService(ServiceReference<Register> reference,
+					Register service) {
+				// TODO Auto-generated method stub
+				
+			}
+
+			public void removedService(ServiceReference<Register> reference,
+					Register service) {
+				// TODO Auto-generated method stub
+				
+			}
+			
+		});
+		tracker.open();
+		Register register = tracker.getService();
+		if (register != null) {
+			register(register);
+		}
+
+	}
+
+	private synchronized void register(Register register) {
+		if (!registered) {
+			registered = true;
+			Bundle bundle = context.getBundle();
+			for (Info classInfo: providerInfo) {
+				BundleProviderLoader loader = new BundleProviderLoader(classInfo.id, classInfo.className, bundle, classInfo.priority);
+				providerLoaders.add(loader);
+				register.registerProvider(loader);
+			}
+			for (Info classInfo: serviceInfo) {
+				BundleProviderLoader loader = new BundleProviderLoader(classInfo.id, classInfo.className, bundle, classInfo.priority);
+				serviceLoaders.add(loader);
+				register.registerService(loader);
+			}
+		}
+	}
+
+	public void stop(BundleContext context) throws Exception {
+		Register register = tracker.getService();
+		tracker.close();
+		synchronized (this) {
+			if (register != null && registered) {
+				for (BundleProviderLoader loader: providerLoaders) {
+					register.unregisterProvider(loader);
+				}
+				for (BundleProviderLoader loader: serviceLoaders) {
+					register.unregisterService(loader);
+				}
+			}
+		}
+
+	}
+
+}
diff --git a/yoko-rmi-impl/pom.xml b/yoko-rmi-impl/pom.xml
index b5d3045..7b8d098 100755
--- a/yoko-rmi-impl/pom.xml
+++ b/yoko-rmi-impl/pom.xml
@@ -32,6 +32,11 @@
     an endorsed standard -->
         <dependency>
             <groupId>org.apache.yoko</groupId>
+            <artifactId>yoko-osgi</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.yoko</groupId>
             <artifactId>yoko-spec-corba</artifactId>
             <scope>provided</scope>
         </dependency>
@@ -42,13 +47,20 @@
         </dependency>
         <dependency>
             <groupId>org.apache.yoko</groupId>
-            <artifactId>yoko-osgi</artifactId>
+            <artifactId>yoko-util</artifactId>
+            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.servicemix.bundles</groupId>
             <artifactId>org.apache.servicemix.bundles.bcel</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>5.0.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
@@ -62,14 +74,18 @@
                 <artifactId>maven-bundle-plugin</artifactId>
                 <configuration>
                     <instructions>
+                        <Bundle-Activator>org.apache.yoko.rmi.osgi.activator.Activator</Bundle-Activator>
                         <Export-Package>
-                            org.apache.yoko.osgi.locator,
                             org.apache.yoko.rmi.impl,
                             org.apache.yoko.rmi.api,
                             org.apache.yoko.rmi.util,
                             org.apache.yoko.rmi.util.corba,
-                            org.apache.yoko.rmi.util.stub
+                            org.apache.yoko.rmi.util.stub,
                         </Export-Package>
+                        <Import-Package>
+                            !sun.*,
+                            *
+                        </Import-Package>
                     </instructions>
                 </configuration>
             </plugin>
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/api/PortableRemoteObjectExt.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/api/PortableRemoteObjectExt.java
index 1a009e0..6d0e16e 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/api/PortableRemoteObjectExt.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/api/PortableRemoteObjectExt.java
@@ -20,8 +20,8 @@
 
 import java.security.AccessController;
 
-import org.apache.yoko.osgi.ProviderLocator;
 import org.apache.yoko.rmi.util.GetSystemPropertyAction;
+import org.apache.yoko.osgi.ProviderLocator;
 
 public class PortableRemoteObjectExt {
 
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..9c81bce 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,64 +18,57 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class AbstractObjectDescriptor extends ValueDescriptor {
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+
+import java.io.PrintWriter;
+
+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", type.getName().replace('.', '/'));
     }
 
     /** Read an instance of this value from a CDR stream */
-    public Object read(org.omg.CORBA.portable.InputStream in) {
+    @Override
+    public Object read(InputStream in) {
         org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
 
         return _in.read_abstract_interface();
     }
 
     /** Write an instance of this value to a CDR stream */
-    public void write(org.omg.CORBA.portable.OutputStream out, Object value) {
+    @Override
+    public void write(OutputStream out, Object value) {
         org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;
 
         _out.write_abstract_interface(value);
     }
 
-    /*
-     * public java.io.Serializable writeReplace (java.io.Serializable val) {
-     * return null; }
-     * 
-     * public void writeValue(org.omg.CORBA.portable.OutputStream out,
-     * java.io.Serializable value) { // skip // }
-     * 
-     * public java.io.Serializable readValue (org.omg.CORBA.portable.InputStream
-     * in, java.util.Map offsetMap) { return null; }
-     */
-
-    org.omg.CORBA.TypeCode getTypeCode() {
-        if (_type_code == null) {
-            org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
-            _type_code = orb.create_abstract_interface_tc(getRepositoryID(),
-                    getJavaClass().getName());
-        }
-
-        return _type_code;
+    @Override
+    protected TypeCode genTypeCode() {
+        ORB orb = ORB.init();
+        return orb.create_abstract_interface_tc(getRepositoryID(), type.getName());
     }
 
+    @Override
     public long computeHashCode() {
         return 0L;
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         throw new IllegalStateException("not serializable " + value.getClass().getName());
     }
 
-    void writeMarshalValue(java.io.PrintWriter pw, String outName,
-            String paramName) {
+    @Override
+    void writeMarshalValue(PrintWriter pw, String outName, String paramName) {
         pw.print("javax.rmi.CORBA.Util.writeAbstractObject(");
         pw.print(outName);
         pw.print(',');
@@ -83,9 +76,9 @@
         pw.print(')');
     }
 
-    void writeUnmarshalValue(java.io.PrintWriter pw, String inName) {
+    @Override
+    void writeUnmarshalValue(PrintWriter pw, String inName) {
         pw.print(inName);
         pw.print(".read_abstract_interface()");
     }
-
 }
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..aad6973 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,40 +18,49 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class AnyDescriptor extends TypeDescriptor {
+import java.io.PrintWriter;
+
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.TCKind;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+
+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", type.getName().replace('.', '/'));
     }
 
     /** Read an instance of this value from a CDR stream */
-    public Object read(org.omg.CORBA.portable.InputStream in) {
+    @Override
+    public Object read(InputStream in) {
         return javax.rmi.CORBA.Util.readAny(in);
     }
 
     /** Write an instance of this value to a CDR stream */
-    public void write(org.omg.CORBA.portable.OutputStream out, Object val) {
+    @Override
+    public void write(OutputStream out, Object val) {
         javax.rmi.CORBA.Util.writeAny(out, val);
     }
 
-    org.omg.CORBA.TypeCode getTypeCode() {
-        org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
-        return orb.get_primitive_tc(org.omg.CORBA.TCKind.tk_any);
+    @Override
+    protected TypeCode genTypeCode() {
+        ORB orb = ORB.init();
+        return orb.get_primitive_tc(TCKind.tk_any);
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         throw new InternalError("cannot copy org.omg.CORBA.Any");
     }
 
-    void writeMarshalValue(java.io.PrintWriter pw, String outName,
-            String paramName) {
+    @Override
+    void writeMarshalValue(PrintWriter pw, String outName, String paramName) {
         pw.print("javax.rmi.CORBA.Util.writeAny(");
         pw.print(outName);
         pw.print(',');
@@ -59,10 +68,10 @@
         pw.print(')');
     }
 
-    void writeUnmarshalValue(java.io.PrintWriter pw, String inName) {
+    @Override
+    void writeUnmarshalValue(PrintWriter pw, String inName) {
         pw.print("javax.rmi.CORBA.Util.readAny(");
         pw.print(inName);
         pw.print(")");
     }
-
 }
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 4f34759..ca4e0b1 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ArrayDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ArrayDescriptor.java
@@ -18,84 +18,78 @@
 
 package org.apache.yoko.rmi.impl;
 
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Serializable;
 import java.lang.reflect.Array;
-import java.util.Vector;
+import java.rmi.Remote;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Map;
+import java.util.Set;
 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.IndirectionException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
 
-public 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;
-
-    public String getRepositoryID() {
-        if (_repid != null)
-            return _repid;
-
-        if (elementType.isPrimitive() || elementType == Object.class) {
-            _repid = "RMI:" + getJavaClass().getName() + ":0000000000000000";
-        } else {
-            TypeDescriptor desc = getTypeRepository()
-                    .getDescriptor(elementType);
-            String elemRep = desc.getRepositoryIDForArray();
-            String hash = elemRep.substring(elemRep.indexOf(':', 4));
-            _repid = "RMI:" + getJavaClass().getName() + hash;
-        }
-
-        // System.out.println ("REPID "+getJavaClass()+" >> "+_repid);
-
-        return _repid;
-    }
-
-
-    public String getElementRepositoryID() {
-        if (_elementRepid != null) {
-            return _elementRepid;
-        }
-
-        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.getRepositoryIDForArray();
-        }
-
-        // System.out.println ("Element REPID "+getJavaClass()+" >> "+_elementRepid);
-
-        return _elementRepid;
-    }
+abstract class ArrayDescriptor extends ValueDescriptor {
+    final Class elementType;
+    final Class basicType;
+    private final int order;
 
     protected ArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
         super(type, rep);
-        logger.fine("Creating an array descriptor for type " + type.getName() + " holding elements of " + elemType.getName()); 
+        logger.fine("Creating an array descriptor for type " + type.getName() + " holding elements of " + elemType.getName());
         this.elementType = elemType;
 
-        order = 1;
-        basicType = elemType;
+        int order = 1;
+        Class basicType = elemType;
         while (basicType.isArray()) {
             basicType = basicType.getComponentType();
-            order += 1;
+            order++;
         }
+        this.basicType = basicType;
+        this.order = order;
     }
 
-    public String getIDLName() {
+    @Override
+    protected String genRepId() {
+        if (elementType.isPrimitive() || elementType == Object.class)
+            return String.format("RMI:%s:%016X", type.getName(), 0);
+
+        TypeDescriptor desc = repo.getDescriptor(elementType);
+        String elemRep = desc.getRepositoryID();
+        String hash = elemRep.substring(elemRep.indexOf(':', 4));
+        return String.format("RMI:%s:%s", type.getName(), hash);
+    }
+
+    // repository ID for the contained elements
+    private volatile String _elementRepid = null;
+    private final String genElemRepId() {
+        if (elementType.isPrimitive() || elementType == Object.class) {
+            // use the descriptor type past the array type marker
+            return String.format("RMI:%s:%016X", type.getName().substring(1), 0);
+        }
+        return repo.getDescriptor(elementType).getRepositoryID();
+    }
+
+    public String getElementRepositoryID() {
+        if (_elementRepid == null) _elementRepid = genElemRepId();
+        return _elementRepid;
+    }
+
+    @Override
+    protected final String genIDLName() {
         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 
@@ -129,7 +123,7 @@
     }
 
     static ArrayDescriptor get(final Class type, TypeRepository rep) {
-        logger.fine("retrieving an array descriptor for class " + type.getName()); 
+        logger.fine("retrieving an array descriptor for class " + type.getName());
         if (!type.isArray()) {
             throw new IllegalArgumentException("type is not an array");
         }
@@ -137,7 +131,6 @@
         Class elemType = type.getComponentType();
 
         if (elemType.isPrimitive()) {
-
             if (elemType == Boolean.TYPE) {
                 return new BooleanArrayDescriptor(type, elemType, rep);
             } else if (elemType == Byte.TYPE) {
@@ -158,76 +151,73 @@
                 throw new RuntimeException("unknown array type " + type);
             }
         }
-
-        if (java.io.Serializable.class.isAssignableFrom(elemType)) {
-            return new ValueArrayDescriptor(type, elemType, rep);
-
-        } else if (java.rmi.Remote.class.isAssignableFrom(elemType)) {
-            return new RemoteArrayDescriptor(type, elemType, rep);
-
-        } else if (Object.class.equals(elemType)) {
+        if (Serializable.class.equals(elemType) ||
+                Externalizable.class.equals(elemType) || Object.class.equals(elemType)) {
             return new ObjectArrayDescriptor(type, elemType, rep);
-
+        } else if (Remote.class.isAssignableFrom(elemType)) {
+            return new RemoteArrayDescriptor(type, elemType, rep);
+        } else if (Serializable.class.isAssignableFrom(elemType)) {
+            return new ValueArrayDescriptor(type, elemType, rep);
         } else {
             return new AbstractObjectArrayDescriptor(type, elemType, rep);
         }
-
     }
 
     /**
      * Read an instance of this value from a CDR stream. Overridden to provide a
      * specific type
      */
-    public Object read(org.omg.CORBA.portable.InputStream in) {
+    @Override
+    public Object read(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()); 
-        
-        // 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);
-        }
+        logger.fine("Reading an array value with repository id " + getRepositoryID() + " java class is " + type);
+
+        // if we have a resolved class, read using that, otherwise fall back on the
+        // repository id.
+        return ((null == type) ? _in.read_value(getRepositoryID()) : _in.read_value(type));
     }
 
     /** Write an instance of this value to a CDR stream */
-    public void write(org.omg.CORBA.portable.OutputStream out, Object value) {
+    @Override
+    public void write(OutputStream out, Object value) {
         org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;
 
-        _out.write_value((java.io.Serializable)value, getRepositoryID());
+        _out.write_value((Serializable)value, getRepositoryID());
     }
 
-    org.omg.CORBA.ValueMember[] getValueMembers() {
+    @Override
+    protected final ValueMember[] genValueMembers() {
+        final ValueMember[] members = new ValueMember[1];
+        final TypeDescriptor elemDesc = repo.getDescriptor(elementType);
+        final String elemRepID = elemDesc.getRepositoryID();
 
-        if (_value_members == null) {
+        final ORB orb = ORB.init();
+        TypeCode memberTC = orb.create_sequence_tc(0, elemDesc.getTypeCode());
 
-            _value_members = new org.omg.CORBA.ValueMember[1];
-
-            TypeDescriptor elemDesc = getTypeRepository().getDescriptor(
-                    elementType);
-
-            String elemRepID = elemDesc.getRepositoryID();
-
-            ORB orb = org.omg.CORBA.ORB.init();
-            TypeCode memberTC = orb.create_sequence_tc(0, elemDesc
-                    .getTypeCode());
-
-            _value_members[0] = new ValueMember("", // member has no name!
+        members[0] = new ValueMember("", // member has no name!
                     elemRepID, this.getRepositoryID(), "1.0", memberTC, null,
                     (short) 1);
-            // public
+
+        return members;
+    }
+
+    @Override
+    void addDependencies(Set classes) {
+        repo.getDescriptor(basicType).addDependencies(classes);
+    }
+
+    final CorbaObjectReader makeCorbaObjectReader(final InputStream in, final Map offsetMap, final Serializable obj)
+            throws IOException {
+        try {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<CorbaObjectReader>() {
+                public CorbaObjectReader run() throws IOException {
+                    return new CorbaObjectReader(in, offsetMap, obj);
+                }
+            });
+        } catch (PrivilegedActionException e) {
+            throw (IOException)e.getException();
         }
-
-        return _value_members;
     }
-
-    void addDependencies(java.util.Set classes) {
-        getTypeRepository().getDescriptor(basicType).addDependencies(classes);
-    }
-
 }
 
 class ObjectArrayDescriptor extends ArrayDescriptor {
@@ -237,15 +227,15 @@
         super(type, elemType, rep);
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out, Serializable value) {
         // System.out.println ("ObjectArrayDescriptor::writeValue
         // "+getRepositoryID ());
 
         Object[] arr = (Object[]) value;
         out.write_long(arr.length);
 
-        logger.finer("writing " + getJavaClass().getName() + " size="
+        logger.finer("writing " + type.getName() + " size="
                 + arr.length);
 
         for (int i = 0; i < arr.length; i++) {
@@ -253,8 +243,9 @@
         }
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         try {
             ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);
@@ -264,7 +255,7 @@
 
             offsetMap.put(key, arr);
 
-            logger.fine("reading " + getJavaClass().getName() + " size="
+            logger.fine("reading " + type.getName() + " size="
                     + arr.length);
 
             for (int i = 0; i < length; i++) {
@@ -276,19 +267,20 @@
                     else {
                         logger.finer("Array item " + i + " is null"); 
                     }
-                } catch (org.omg.CORBA.portable.IndirectionException ex) {
+                } catch (IndirectionException ex) {
                     arr[i] = offsetMap.get(new Integer(ex.offset));
                     // reader.addValueBox (ex.offset, new ArrayBox (i, arr));
                 }
             }
-            return (java.io.Serializable) arr;
+            return arr;
 
-        } catch (java.io.IOException ex) {
+        } catch (IOException ex) {
             throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
 
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         final Object[] orig = (Object[]) value;
         final Object[] result = new Object[orig.length];
@@ -311,9 +303,10 @@
         return result;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, 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) {
@@ -330,11 +323,9 @@
         super(type, elemType, rep);
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
-        // System.out.println ("RemoteArrayDescriptor::writeValue
-        // "+getRepositoryID ());
-
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         Object[] arr = (Object[]) value;
         out.write_long(arr.length);
         for (int i = 0; i < arr.length; i++) {
@@ -342,8 +333,9 @@
         }
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         try {
             ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);
@@ -355,20 +347,21 @@
             for (int i = 0; i < length; i++) {
                 try {
                     arr[i] = reader.readRemoteObject(elementType);
-                } catch (org.omg.CORBA.portable.IndirectionException ex) {
+                } catch (IndirectionException ex) {
                     arr[i] = offsetMap.get(new Integer(ex.offset));
                     // reader.addValueBox (ex.offset, new ArrayBox (i, arr));
                 }
             }
 
-            return (java.io.Serializable) arr;
+            return arr;
 
-        } catch (java.io.IOException ex) {
+        } catch (IOException ex) {
             throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
 
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         final Object[] orig = (Object[]) value;
         final Object[] result = (Object[]) Array.newInstance(elementType,
@@ -392,9 +385,10 @@
         return result;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, 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) {
@@ -411,42 +405,37 @@
         super(type, elemType, rep);
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
-        // System.out.println ("ValueArrayDescriptor::writeValue
-        // "+getRepositoryID ());
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         Object[] arr = (Object[]) value;
         out.write_long(arr.length);
-        java.io.Serializable[] sarr = (java.io.Serializable[]) arr;
+        Serializable[] sarr = (Serializable[]) arr;
         org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;
         for (int i = 0; i < sarr.length; i++) {
             _out.write_value(sarr[i], getElementRepositoryID());
         }
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
-            Integer key) {
-        try {
-            ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);
+    @Override
+    public Serializable readValue(InputStream in, Map offsetMap, Integer key) {
+        final int length = in.read_long();
+        Object[] arr = (Object[]) Array.newInstance(elementType, length);
+        offsetMap.put(key, arr);
 
-            int length = reader.readInt();
-            Object[] arr = (Object[]) Array.newInstance(elementType, length);
-            offsetMap.put(key, arr);
-            // System.out.println ("ValueArrayDescriptor::readValue
-            // len="+length+"; type="+elementType);
-
-            for (int i = 0; i < length; i++) {
-                arr[i] = reader.readValueObject(elementType);
+        final org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
+        for (int i = 0; i < length; i++) {
+            try {
+                arr[i] = _in.read_value(elementType);
+            } catch (IndirectionException ex) {
+                arr[i] = offsetMap.get(new Integer(ex.offset));
             }
-
-            return (java.io.Serializable) arr;
-        } catch (java.io.IOException ex) {
-            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
 
+        return arr;
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         Object[] orig = (Object[]) value;
         final Object[] result = (Object[]) Array.newInstance(value.getClass()
@@ -470,9 +459,10 @@
         return result;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, 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) {
@@ -489,10 +479,9 @@
         super(type, elemType, rep);
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
-        // System.out.println ("AbstractObjectArrayDescriptor::writeValue
-        // "+getRepositoryID ());
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
 
         Object[] arr = (Object[]) value;
         out.write_long(arr.length);
@@ -501,8 +490,9 @@
         }
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         try {
             ObjectReader reader = makeCorbaObjectReader(in, offsetMap, null);
@@ -515,19 +505,20 @@
             for (int i = 0; i < length; i++) {
                 try {
                     arr[i] = reader.readAbstractObject();
-                } catch (org.omg.CORBA.portable.IndirectionException ex) {
+                } catch (IndirectionException ex) {
                     arr[i] = offsetMap.get(new Integer(ex.offset));
                     // reader.addValueBox (ex.offset, new ArrayBox (i, arr));
                 }
             }
 
-            return (java.io.Serializable) arr;
+            return arr;
 
-        } catch (java.io.IOException ex) {
+        } catch (IOException ex) {
             throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         final Object[] orig = (Object[]) value;
         final Object[] result = (Object[]) Array.newInstance(elementType,
@@ -551,9 +542,10 @@
         return result;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, 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) {
@@ -570,19 +562,21 @@
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         boolean[] arr = new boolean[in.read_long()];
         offsetMap.put(key, arr);
         for (int i = 0; i < arr.length; i++) {
             arr[i] = in.read_boolean();
         }
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         boolean[] arr = (boolean[]) value;
         out.write_long(arr.length);
         for (int i = 0; i < arr.length; i++) {
@@ -590,6 +584,7 @@
         }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((boolean[]) value).length == 0)
             return value;
@@ -599,7 +594,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         boolean[] arr = (boolean[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
@@ -613,34 +609,32 @@
 }
 
 class ByteArrayDescriptor extends ArrayDescriptor {
-
     ByteArrayDescriptor(Class type, Class elemType, TypeRepository rep) {
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         byte[] arr = new byte[in.read_long()];
         offsetMap.put(key, arr);
         for (int i = 0; i < arr.length; i++) {
             arr[i] = in.read_octet();
         }
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         byte[] arr = (byte[]) value;
         out.write_long(arr.length);
 
         out.write_octet_array(arr, 0, arr.length);
-
-        // for (int i = 0; i < arr.length; i++) {
-        // out.write_octet(arr[i]);
-        // }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((byte[]) value).length == 0)
             return value;
@@ -650,7 +644,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         byte[] arr = (byte[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
@@ -667,23 +662,26 @@
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         int len = in.read_long();
         char[] arr = new char[len];
         offsetMap.put(key, arr);
         in.read_wchar_array(arr, 0, len);
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         char[] arr = (char[]) value;
         out.write_long(arr.length);
         out.write_wchar_array(arr, 0, arr.length);
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((char[]) value).length == 0)
             return value;
@@ -693,7 +691,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         char[] arr = (char[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
@@ -710,19 +709,21 @@
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         short[] arr = new short[in.read_long()];
         offsetMap.put(key, arr);
         for (int i = 0; i < arr.length; i++) {
             arr[i] = in.read_short();
         }
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         short[] arr = (short[]) value;
         out.write_long(arr.length);
         for (int i = 0; i < arr.length; i++) {
@@ -730,6 +731,7 @@
         }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((short[]) value).length == 0)
             return value;
@@ -739,7 +741,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         short[] arr = (short[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
@@ -756,19 +759,21 @@
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         int[] arr = new int[in.read_long()];
         offsetMap.put(key, arr);
         for (int i = 0; i < arr.length; i++) {
             arr[i] = in.read_long();
         }
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         int[] arr = (int[]) value;
         out.write_long(arr.length);
         for (int i = 0; i < arr.length; i++) {
@@ -776,6 +781,7 @@
         }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((int[]) value).length == 0)
             return value;
@@ -785,7 +791,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         int[] arr = (int[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
@@ -802,19 +809,21 @@
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         long[] arr = new long[in.read_long()];
         offsetMap.put(key, arr);
         for (int i = 0; i < arr.length; i++) {
             arr[i] = in.read_longlong();
         }
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         long[] arr = (long[]) value;
         out.write_long(arr.length);
         for (int i = 0; i < arr.length; i++) {
@@ -822,6 +831,7 @@
         }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((long[]) value).length == 0)
             return value;
@@ -831,7 +841,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         long[] arr = (long[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
@@ -849,19 +860,21 @@
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         float[] arr = new float[in.read_long()];
         offsetMap.put(key, arr);
         for (int i = 0; i < arr.length; i++) {
             arr[i] = in.read_float();
         }
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         float[] arr = (float[]) value;
         out.write_long(arr.length);
         for (int i = 0; i < arr.length; i++) {
@@ -869,6 +882,7 @@
         }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((float[]) value).length == 0)
             return value;
@@ -878,7 +892,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         float[] arr = (float[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
@@ -895,19 +910,21 @@
         super(type, elemType, rep);
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.util.Map offsetMap,
+    @Override
+    public Serializable readValue(
+            InputStream in, Map offsetMap,
             Integer key) {
         double[] arr = new double[in.read_long()];
         offsetMap.put(key, arr);
         for (int i = 0; i < arr.length; i++) {
             arr[i] = in.read_double();
         }
-        return (java.io.Serializable) arr;
+        return arr;
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
+    @Override
+    public void writeValue(OutputStream out,
+            Serializable value) {
         double[] arr = (double[]) value;
         out.write_long(arr.length);
         for (int i = 0; i < arr.length; i++) {
@@ -915,6 +932,7 @@
         }
     }
 
+    @Override
     Object copyObject(Object value, CopyState state) {
         if (((double[]) value).length == 0)
             return value;
@@ -924,7 +942,8 @@
         return copy;
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    @Override
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         double[] arr = (double[]) val;
         pw.print("length=" + arr.length + "; ");
         for (int i = 0; i < arr.length; i++) {
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/ClassBaseDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassBaseDescriptor.java
new file mode 100644
index 0000000..708faea
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassBaseDescriptor.java
@@ -0,0 +1,47 @@
+package org.apache.yoko.rmi.impl;
+
+import org.omg.CORBA.MARSHAL;
+
+import javax.rmi.CORBA.ClassDesc;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+abstract class ClassBaseDescriptor extends ValueDescriptor {
+
+    ClassBaseDescriptor(Class type, TypeRepository repository) {
+        super(type, repository);
+    }
+
+    private volatile Field repidField = null;
+    private Field genRepIdField() {
+        return findField("repid");
+    }
+    final Field getRepidField() {
+        if (null == repidField) repidField = genRepIdField();
+        return repidField;
+    }
+
+    private volatile Field cobebaseField = null;
+    private Field genCodebaseField() {
+        return findField("codebase");
+    }
+    final Field getCobebaseField() {
+        if (null == cobebaseField) cobebaseField = genCodebaseField();
+        return cobebaseField;
+    }
+
+    private Field findField(final String fieldName) {
+        return AccessController.doPrivileged(new PrivilegedAction<Field>() {
+            public Field run() {
+                try {
+                    Field f = ClassDesc.class.getDeclaredField(fieldName);
+                    f.setAccessible(true);
+                    return f;
+                } catch (NoSuchFieldException e) {
+                    throw (MARSHAL)new MARSHAL("no such field: " + e).initCause(e);
+                }
+            }
+        });
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescDescriptor.java
new file mode 100644
index 0000000..8106755
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescDescriptor.java
@@ -0,0 +1,51 @@
+package org.apache.yoko.rmi.impl;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.rmi.CORBA.ClassDesc;
+import javax.rmi.CORBA.Util;
+
+import org.apache.yoko.util.cmsf.RepIds;
+import org.omg.CORBA.MARSHAL;
+
+class ClassDescDescriptor extends ClassBaseDescriptor {
+    private static final Logger logger = Logger.getLogger(ClassDescDescriptor.class.getName());
+
+    ClassDescDescriptor(TypeRepository repository) {
+        super(ClassDesc.class, repository);
+    }
+
+    /** Read an instance of this value from a CDR stream */
+    @Override
+    public Serializable readResolve(final Serializable value) {
+        final ClassDesc desc = (ClassDesc) value;
+
+        Class<?> result = AccessController.doPrivileged(new PrivilegedAction<Class<?>>() {
+            public Class<?> run() {
+                String className = "<unknown>";
+                try {
+                    String repid = (String) getRepidField().get(desc);
+                    String codebase = (String) getCobebaseField().get(desc);
+
+                    Class<?> result = RepIds.query(repid).codebase(codebase).toClass();
+                    if (null != result) return result;
+
+                    throw new MARSHAL(String.format("Cannot load class \"%s\"", className));
+                } catch (IllegalAccessException ex) {
+                    throw (MARSHAL)new MARSHAL("no such field: " + ex).initCause(ex);
+                }
+            }
+        });
+
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("readResolve %s => %s", value, result));
+
+        return result;
+    }
+
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java
index 37d2202..6389139 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClassDescriptor.java
@@ -18,115 +18,61 @@
 
 package org.apache.yoko.rmi.impl;
 
+import java.io.Serializable;
+import java.lang.reflect.Field;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
-public class ClassDescriptor extends ValueDescriptor {
-    static Logger logger = Logger.getLogger(ClassDescriptor.class.getName());
+import javax.rmi.CORBA.ClassDesc;
+import javax.rmi.CORBA.Util;
+import javax.rmi.CORBA.ValueHandler;
+
+import org.omg.CORBA.MARSHAL;
+
+class ClassDescriptor extends ClassBaseDescriptor {
+    private static final Logger logger = Logger.getLogger(ClassDescriptor.class.getName());
 
     ClassDescriptor(TypeRepository repository) {
-        super(javax.rmi.CORBA.ClassDesc.class, repository);
+        super(Class.class, repository);
     }
 
-    java.lang.reflect.Field repid_field;
-
-    java.lang.reflect.Field codebase_field;
-
-    String _repid_arr;
-
-    public void init() {
-        super.init();
-
-        Class clz = javax.rmi.CORBA.ClassDesc.class;
-        try {
-            repid_field = clz.getDeclaredField("repid");
-            repid_field.setAccessible(true);
-            codebase_field = clz.getDeclaredField("codebase");
-            codebase_field.setAccessible(true);
-        } catch (java.lang.NoSuchFieldException ex) {
-            throw new org.omg.CORBA.MARSHAL("no such field: " + ex);
-        }
-
-        ValueDescriptor class_desc = new ValueDescriptor(Class.class,
-                getTypeRepository());
-        class_desc.init();
-        _repid_arr = class_desc.getRepositoryID();
-    }
-
-    public String getRepositoryIDForArray() {
-        return _repid_arr;
-    }
-
+    @Override
     Object copyObject(Object orig, CopyState state) {
         state.put(orig, orig);
         return orig;
     }
 
-    /** Read an instance of this value from a CDR stream */
-    public java.io.Serializable readResolve(final java.io.Serializable value) {
-        final javax.rmi.CORBA.ClassDesc desc = (javax.rmi.CORBA.ClassDesc) value;
-
-        java.io.Serializable result = (java.io.Serializable) AccessController
-                .doPrivileged(new PrivilegedAction() {
-                    public Object run() {
-                        String className = "<unknown>";
-                        try {
-                            String repid = (String) repid_field.get(desc);
-                            String codebase = (String) codebase_field.get(desc);
-
-                            int beg = repid.indexOf(':');
-                            int end = repid.indexOf(':', beg + 1);
-
-                            className = repid.substring(beg + 1, end);
-                            ClassLoader loader = Thread.currentThread()
-                                    .getContextClassLoader();
-
-                            return javax.rmi.CORBA.Util.loadClass(className,
-                                    codebase, loader);
-                        } catch (java.lang.ClassNotFoundException ex) {
-                            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(
-                                    "cannot load class " + className).initCause(ex);
-                        } catch (java.lang.IllegalAccessException ex) {
-                            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(
-                                    "no such field: " + ex).initCause(ex);
-                        }
-                    }
-                });
-
-        logger.fine("readResolve " + value + " => " + result);
-
-        return result;
-    }
-
     /** Write an instance of this value to a CDR stream */
-    public java.io.Serializable writeReplace(final java.io.Serializable value) {
-        final Class type = (Class) value;
+    @Override
+    public Serializable writeReplace(final Serializable value) {
+        final Class<?> type = (Class<?>) value;
 
-        final javax.rmi.CORBA.ClassDesc desc = new javax.rmi.CORBA.ClassDesc();
-
-        return (java.io.Serializable) AccessController
-                .doPrivileged(new PrivilegedAction() {
-                    public Object run() {
+        final ClassDesc result = AccessController
+                .doPrivileged(new PrivilegedAction<ClassDesc>() {
+                    public ClassDesc run() {
                         try {
+                            final ClassDesc desc = new ClassDesc();
 
-                            javax.rmi.CORBA.ValueHandler handler = javax.rmi.CORBA.Util
-                                    .createValueHandler();
+                            ValueHandler handler = Util.createValueHandler();
                             String repId = handler.getRMIRepositoryID(type);
-                            repid_field.set(desc, repId);
+                            getRepidField().set(desc, repId);
 
-                            String codebase = javax.rmi.CORBA.Util
-                                    .getCodebase(type);
-                            codebase_field.set(desc, codebase);
+                            String codebase = Util.getCodebase(type);
+                            getCobebaseField().set(desc, codebase);
 
                             return desc;
 
-                        } catch (java.lang.IllegalAccessException ex) {
-                            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(
-                                    "no such field: " + ex).initCause(ex);
+                        } catch (IllegalAccessException ex) {
+                            throw (MARSHAL)new MARSHAL("no such field: " + ex).initCause(ex);
                         }
                     }
                 });
-    }
 
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("writeReplace %s => %s", value, result));
+
+        return result;
+    }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClosedObjectReader.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClosedObjectReader.java
new file mode 100644
index 0000000..d4485d1
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ClosedObjectReader.java
@@ -0,0 +1,161 @@
+package org.apache.yoko.rmi.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputValidation;
+import java.rmi.Remote;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.logging.Logger;
+
+import org.omg.CORBA.portable.IndirectionException;
+
+class ClosedObjectReader extends ObjectReader {
+    private static final Logger LOGGER = Logger.getLogger(ClosedObjectReader.class.getName());
+    public static final ClosedObjectReader INSTANCE = AccessController.doPrivileged(new PrivilegedAction<ClosedObjectReader>() {
+        @Override
+        public ClosedObjectReader run() {
+            try {
+                return new ClosedObjectReader();
+            } catch (IOException e) {
+                LOGGER.severe("Unable to create ClosedObjectInputStream singleton instance: " + e);
+                return null;
+            }
+        }
+    });
+
+    private ClosedObjectReader() throws IOException {
+    }
+
+    private IllegalStateException newException() {
+        return new IllegalStateException("Stream already closed");
+    }
+
+    public void close() {
+    }
+
+    //////////////////////////////////////
+    // ONLY DELEGATE METHODS BELOW HERE //
+    //////////////////////////////////////
+
+    public int read(byte[] b) {
+        throw newException();
+    }
+    public long skip(long n) {
+        throw newException();
+    }
+    public void mark(int readlimit) {
+        throw newException();
+    }
+    public void reset() {
+        throw newException();
+    }
+    public boolean markSupported() {
+        throw newException();
+    }
+    public Object readUnshared() {
+        throw newException();
+    }
+    public void defaultReadObject() {
+        throw newException();
+    }
+    public GetField readFields() {
+        throw newException();
+    }
+    public void registerValidation(ObjectInputValidation obj, int prio) {
+        throw newException();
+    }
+    public int read() {
+        throw newException();
+    }
+    public int read(byte[] buf, int off, int len) {
+        throw newException();
+    }
+    public int available() {
+        throw newException();
+    }
+    public boolean readBoolean() {
+        throw newException();
+    }
+    public byte readByte() {
+        throw newException();
+    }
+    public int readUnsignedByte() {
+        throw newException();
+    }
+    public char readChar() {
+        throw newException();
+    }
+    public short readShort() {
+        throw newException();
+    }
+    public int readUnsignedShort() {
+        throw newException();
+    }
+    public int readInt() {
+        throw newException();
+    }
+    public long readLong() {
+        throw newException();
+    }
+    public float readFloat() {
+        throw newException();
+    }
+    public double readDouble() {
+        throw newException();
+    }
+    public void readFully(byte[] buf) {
+        throw newException();
+    }
+    public void readFully(byte[] buf, int off, int len) {
+        throw newException();
+    }
+    public int skipBytes(int len) {
+        throw newException();
+    }
+    public String readLine() {
+        throw newException();
+    }
+    public String readUTF() {
+        throw newException();
+    }
+
+    // ObjectReader methods
+
+    void _startValue() {
+        throw newException();
+    }
+    void _endValue() {
+        throw newException();
+    }
+    void setCurrentValueDescriptor(ValueDescriptor desc) {
+        throw newException();
+    }
+    Object readAbstractObject() {
+        throw newException();
+    }
+    Object readAny() {
+        throw newException();
+    }
+    Object readValueObject() {
+        throw newException();
+    }
+    Object readValueObject(Class<?> clz) {
+        throw newException();
+    }
+    org.omg.CORBA.Object readCorbaObject(Class<?> type) {
+        throw newException();
+    }
+    Remote readRemoteObject(Class<?> type) {
+        throw newException();
+    }
+    void readExternal(Externalizable ext) {
+        throw newException();
+    }
+
+    @Override
+    protected final Object readObjectOverride() {
+        throw newException();
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CopyState.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CopyState.java
index de95fce..9c91719 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CopyState.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CopyState.java
@@ -292,7 +292,7 @@
 
     }
 
-    public class Reader extends ObjectReader {
+    public class Reader extends ObjectReaderBase {
 
         int cpos;
 
@@ -330,15 +330,15 @@
             return dequeue();
         }
 
-        public Object readValueObject(Class clz) {
+        public Object readValueObject(Class<?> clz) {
             return dequeue();
         }
         
-        public org.omg.CORBA.Object readCorbaObject(Class type) {
+        public org.omg.CORBA.Object readCorbaObject(Class<?> type) {
             return (org.omg.CORBA.Object) dequeue();
         }
 
-        public java.rmi.Remote readRemoteObject(Class type) {
+        public java.rmi.Remote readRemoteObject(Class<?> type) {
             return (java.rmi.Remote) dequeue();
         }
 
@@ -473,6 +473,14 @@
             return (String) dequeue();
         }
 
+        @Override
+        protected void _startValue() {
+        }
+
+        @Override
+        protected void _endValue() {
+        }
+
     }
 
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CorbaObjectReader.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CorbaObjectReader.java
index cc9f496..cbf95e4 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CorbaObjectReader.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CorbaObjectReader.java
@@ -1,100 +1,108 @@
 /**
-*
-* 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.
-*/ 
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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;
 
 
-public class CorbaObjectReader extends ObjectReader {
+import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.portable.IndirectionException;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.ValueInputStream;
+
+import javax.rmi.CORBA.Util;
+import javax.rmi.PortableRemoteObject;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.rmi.Remote;
+import java.util.Map;
+
+public class CorbaObjectReader extends ObjectReaderBase {
     final org.omg.CORBA_2_3.portable.InputStream in;
 
-    final java.util.Map offsetMap;
+    private final Map<Integer, Object> offsetMap;
 
-    CorbaObjectReader(org.omg.CORBA.portable.InputStream in,
-            java.util.Map offsetMap, java.io.Serializable obj)
-            throws java.io.IOException {
+    CorbaObjectReader(InputStream in, Map<Integer, Object> offsetMap, Serializable obj) throws IOException {
         super(obj);
-
         this.in = (org.omg.CORBA_2_3.portable.InputStream) in;
         this.offsetMap = offsetMap;
     }
 
-    public void readFully(byte[] arr, int off, int val)
-            throws java.io.IOException {
+    public void readFully(byte[] arr, int off, int val) throws IOException {
         in.read_octet_array(arr, off, val);
     }
 
-    public int skipBytes(int len) throws java.io.IOException {
-        byte[] data = new byte[len];
+    public int skipBytes(int len) throws IOException {
+        final byte[] data = new byte[len];
         readFully(data, 0, len);
         return len;
     }
 
-    public boolean readBoolean() throws java.io.IOException {
+    public boolean readBoolean() throws IOException {
         return in.read_boolean();
     }
 
-    public byte readByte() throws java.io.IOException {
+    public byte readByte() throws IOException {
         return in.read_octet();
     }
 
-    public int readUnsignedByte() throws java.io.IOException {
-        int val = in.read_octet();
+    public int readUnsignedByte() throws IOException {
+        final int val = in.read_octet();
         return val & 0xff;
     }
 
-    public short readShort() throws java.io.IOException {
+    public short readShort() throws IOException {
         return in.read_short();
     }
 
-    public int readUnsignedShort() throws java.io.IOException {
-        int val = in.read_short();
+    public int readUnsignedShort() throws IOException {
+        final int val = in.read_short();
         return val & 0xffff;
     }
 
-    public char readChar() throws java.io.IOException {
+    public char readChar() throws IOException {
         return in.read_wchar();
     }
 
-    public int readInt() throws java.io.IOException {
+    public int readInt() throws IOException {
         return in.read_long();
     }
 
-    public long readLong() throws java.io.IOException {
+    public long readLong() throws IOException {
         return in.read_longlong();
     }
 
-    public float readFloat() throws java.io.IOException {
+    public float readFloat() throws IOException {
         return in.read_float();
     }
 
-    public double readDouble() throws java.io.IOException {
+    public double readDouble() throws IOException {
         return in.read_double();
     }
 
-    /** @deprecated */
-    public java.lang.String readLine() throws java.io.IOException {
-        StringBuffer buf = new StringBuffer();
+    @Deprecated
+    public String readLine() throws IOException {
+        final StringBuilder buf = new StringBuilder();
 
         char ch;
 
         try {
             ch = (char) readUnsignedByte();
-        } catch (org.omg.CORBA.MARSHAL ex) {
+        } catch (MARSHAL ex) {
             return null;
         }
 
@@ -103,19 +111,20 @@
 
             try {
                 ch = (char) readUnsignedByte();
-            } catch (org.omg.CORBA.MARSHAL ex) {
+            } catch (MARSHAL ex) {
                 // reached EOF
                 return buf.toString();
             }
 
-            if (ch == '\n')
+            if (ch == '\n') {
                 return buf.toString();
+            }
 
             if (ch == '\r') {
-                char ch2;
+                final char ch2;
                 try {
                     ch2 = (char) readUnsignedByte();
-                } catch (org.omg.CORBA.MARSHAL ex) {
+                } catch (MARSHAL ex) {
                     // reached EOF
                     return buf.toString();
                 }
@@ -129,77 +138,81 @@
         } while (true);
     }
 
-    public java.lang.String readUTF() throws java.io.IOException {
+    public String readUTF() throws IOException {
         return in.read_wstring();
     }
 
-    public Object readAbstractObject()
-            throws org.omg.CORBA.portable.IndirectionException {
+    public Object readAbstractObject() throws IndirectionException {
         try {
             return in.read_abstract_interface();
-        } catch (org.omg.CORBA.portable.IndirectionException ex) {
-            return offsetMap.get(new Integer(ex.offset));
+        } catch (IndirectionException ex) {
+            return offsetMap.get(ex.offset);
         }
     }
 
-    public Object readAny() throws org.omg.CORBA.portable.IndirectionException {
+    public Object readAny() throws IndirectionException {
         try {
-            return javax.rmi.CORBA.Util.readAny(in);
-        } catch (org.omg.CORBA.portable.IndirectionException ex) {
-            return offsetMap.get(new Integer(ex.offset));
+            return Util.readAny(in);
+        } catch (IndirectionException ex) {
+            return offsetMap.get(ex.offset);
         }
     }
 
-    public Object readValueObject()
-            throws org.omg.CORBA.portable.IndirectionException {
+    public Object readValueObject() throws IndirectionException {
         try {
             return in.read_value();
-        } catch (org.omg.CORBA.portable.IndirectionException ex) {
-            return offsetMap.get(new Integer(ex.offset));
+        } catch (IndirectionException ex) {
+            return offsetMap.get(ex.offset);
         }
     }
 
-    public Object readValueObject(Class clz)
-            throws org.omg.CORBA.portable.IndirectionException {
+    public Object readValueObject(Class<?> clz)
+            throws IndirectionException {
         try {
             return in.read_value(clz);
-        } catch (org.omg.CORBA.portable.IndirectionException ex) {
-            return offsetMap.get(new Integer(ex.offset));
+        } catch (IndirectionException ex) {
+            return offsetMap.get(ex.offset);
         }
     }
-    
-    public org.omg.CORBA.Object readCorbaObject(Class type) {
-	org.omg.CORBA.Object objref = in.read_Object();
-	//objref = (org.omg.CORBA.Object) PortableRemoteObject.narrow(objref, type);
-	return objref;
+
+    public org.omg.CORBA.Object readCorbaObject(Class<?> type) {
+        return in.read_Object();
     }
 
-    public java.rmi.Remote readRemoteObject(Class type) {
-        org.omg.CORBA.Object objref = in.read_Object();
-        return (java.rmi.Remote) javax.rmi.PortableRemoteObject.narrow(objref,
-                type);
+    public Remote readRemoteObject(Class<?> type) {
+        final org.omg.CORBA.Object objref = in.read_Object();
+        return (Remote) PortableRemoteObject.narrow(objref, type);
     }
 
-    public int read() throws java.io.IOException {
+    public int read() throws IOException {
         return readUnsignedByte();
     }
 
-    public int read(byte[] arr) throws java.io.IOException {
+    public int read(byte[] arr) throws IOException {
         return read(arr, 0, arr.length);
     }
 
-    public int read(byte[] arr, int off, int len) throws java.io.IOException {
+    public int read(byte[] arr, int off, int len) throws IOException {
         readFully(arr, off, len);
         return len;
     }
 
-    public long skip(long len) throws java.io.IOException {
+    public long skip(long len) throws IOException {
         skipBytes((int) len);
         return len;
     }
 
-    public int available() throws java.io.IOException {
+    public int available() throws IOException {
         return in.available();
     }
 
+    @Override
+    protected void _startValue() {
+        ((ValueInputStream)in).start_value();
+    }
+
+    @Override
+    protected void _endValue() {
+        ((ValueInputStream)in).end_value();
+    }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CustomMarshaledObjectReader.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CustomMarshaledObjectReader.java
new file mode 100644
index 0000000..585b60f
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/CustomMarshaledObjectReader.java
@@ -0,0 +1,142 @@
+package org.apache.yoko.rmi.impl;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.omg.CORBA.INTERNAL;
+import org.omg.CORBA.MARSHAL;
+
+public final class CustomMarshaledObjectReader extends DelegatingObjectReader {
+    private enum State {
+        UNINITIALISED, BEFORE_CUSTOM_DATA, IN_CUSTOM_DATA, CLOSED;
+        private static final Map<State, Set<State>> TRANSITIONS;
+        
+        static {
+            EnumMap<State, Set<State>> transition = new EnumMap<>(State.class);
+            allow(transition, from(UNINITIALISED), to(BEFORE_CUSTOM_DATA));
+            allow(transition, from(BEFORE_CUSTOM_DATA), to(IN_CUSTOM_DATA, CLOSED));
+            allow(transition, from(IN_CUSTOM_DATA), to(CLOSED));
+            allow(transition, from(CLOSED),         to(CLOSED));
+            TRANSITIONS = Collections.unmodifiableMap(transition);
+        }
+        
+        private static void allow(Map<State, Set<State>> map, State from, Set<State> to) {
+            map.put(from, to);
+        }
+        
+        private static State from(State state) { return state; }
+        
+        private static Set<State> to(State state, State...states) {
+            return Collections.unmodifiableSet(EnumSet.of(state, states));
+        }
+        
+        void checkStateTransition(State newState) {
+            if (TRANSITIONS.get(this).contains(newState))
+                return;
+            throw new INTERNAL("Unexpected state transition from " + this + " to " + newState);
+        }
+    }
+
+    private final ObjectReader objectReader;
+    private State state = State.UNINITIALISED;
+
+    private State setState(final State newState) throws IOException {
+        state.checkStateTransition(newState);
+        try {
+            return state;
+        } finally {
+            state = newState;
+            switch(newState) {
+                case UNINITIALISED:
+                    throw new IllegalStateException();
+                case BEFORE_CUSTOM_DATA:
+                    delegateTo(new DefaultWriteObjectReader(objectReader));
+                    break;
+                case IN_CUSTOM_DATA:
+                    delegateTo(objectReader);
+                    break;
+                case CLOSED:
+                    delegateTo(ClosedObjectReader.INSTANCE);
+                    break;
+            }
+        }
+    }
+
+    private void readCustomRMIValue() throws IOException {
+        setState(State.IN_CUSTOM_DATA);
+        objectReader._startValue();
+    }
+
+    public CustomMarshaledObjectReader(ObjectReader delegate) throws IOException {
+        this.objectReader = delegate;
+        setState(State.BEFORE_CUSTOM_DATA);
+    }
+
+    public void close() throws IOException {
+        switch (setState(State.CLOSED)) {
+            case UNINITIALISED:
+                throw new IllegalStateException();
+            case BEFORE_CUSTOM_DATA :
+                objectReader.readValueObject();
+                break;
+            case IN_CUSTOM_DATA :
+                objectReader._endValue();
+                break;
+            case CLOSED :
+                // nothing to do here
+                break;
+        }
+    }
+
+    @Override
+    protected final Object readObjectOverride() throws ClassNotFoundException, IOException {
+        return super.readObjectOverride0();
+    }
+
+    /**
+     * This class handles reading the defaultWriteObject() data,
+     * and prepares its outer instance when the custom data is
+     * first read.
+     */
+    private final class DefaultWriteObjectReader extends DelegatingObjectReaderWithBeforeReadHook {
+
+        private boolean allowDefaultRead = true;
+
+        public DefaultWriteObjectReader(ObjectReader delegate) throws IOException {
+            super(delegate);
+        }
+
+        @Override
+        public void defaultReadObject() throws IOException, ClassNotFoundException {
+            if (allowDefaultRead) {
+                allowDefaultRead = false;
+                CustomMarshaledObjectReader.this.objectReader.defaultReadObject();
+            } else {
+                throw new IllegalStateException("defaultReadObject() or readFields() must not be called more than once");
+            }
+        }
+
+        @Override
+        public GetField readFields() throws IOException ,ClassNotFoundException {
+            if (allowDefaultRead) {
+                allowDefaultRead = false;
+                return CustomMarshaledObjectReader.this.objectReader.readFields();
+            } else {
+                throw new IllegalStateException("readFields() or defaultReadObject() must not be called more than once");
+            }
+        };
+
+        @Override
+        void beforeRead() {
+            try {
+                CustomMarshaledObjectReader.this.readCustomRMIValue();
+            } catch (IOException e) {
+                throw (MARSHAL)new MARSHAL(e.toString()).initCause(e);
+            }
+        }
+    }
+}
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..562312e 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) {
@@ -44,5 +43,4 @@
         state.put(orig, result);
         return result;
     }
-
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DelegatingObjectReader.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DelegatingObjectReader.java
new file mode 100644
index 0000000..b11f531
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DelegatingObjectReader.java
@@ -0,0 +1,149 @@
+package org.apache.yoko.rmi.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.NotActiveException;
+import java.io.ObjectInputValidation;
+import java.rmi.Remote;
+
+import org.omg.CORBA.portable.IndirectionException;
+
+abstract class DelegatingObjectReader extends ObjectReader {
+    private ObjectReader delegate;
+
+    public DelegatingObjectReader() throws IOException {}
+
+    void delegateTo(ObjectReader delegate) {
+        this.delegate = delegate;
+    }
+
+    //////////////////////////////////////
+    // ONLY DELEGATE METHODS BELOW HERE //
+    //////////////////////////////////////
+
+    final Object readObjectOverride0() throws ClassNotFoundException, IOException {
+        return delegate.readObjectOverride();
+    }
+
+    public int read(byte[] b) throws IOException {
+        return delegate.read(b);
+    }
+    public long skip(long n) throws IOException {
+        return delegate.skip(n);
+    }
+    public void mark(int readlimit) {
+        delegate.mark(readlimit);
+    }
+    public void reset() throws IOException {
+        delegate.reset();
+    }
+    public boolean markSupported() {
+        return delegate.markSupported();
+    }
+    public Object readUnshared() throws IOException, ClassNotFoundException {
+        return delegate.readUnshared();
+    }
+    public void defaultReadObject() throws IOException, ClassNotFoundException {
+        delegate.defaultReadObject();
+    }
+    public GetField readFields() throws IOException, ClassNotFoundException {
+        return delegate.readFields();
+    }
+    public void registerValidation(ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException {
+        delegate.registerValidation(obj, prio);
+    }
+    public int read() throws IOException {
+        return delegate.read();
+    }
+    public int read(byte[] buf, int off, int len) throws IOException {
+        return delegate.read(buf, off, len);
+    }
+    public int available() throws IOException {
+        return delegate.available();
+    }
+    public void close() throws IOException {
+        delegate.close();
+    }
+    public boolean readBoolean() throws IOException {
+        return delegate.readBoolean();
+    }
+    public byte readByte() throws IOException {
+        return delegate.readByte();
+    }
+    public int readUnsignedByte() throws IOException {
+        return delegate.readUnsignedByte();
+    }
+    public char readChar() throws IOException {
+        return delegate.readChar();
+    }
+    public short readShort() throws IOException {
+        return delegate.readShort();
+    }
+    public int readUnsignedShort() throws IOException {
+        return delegate.readUnsignedShort();
+    }
+    public int readInt() throws IOException {
+        return delegate.readInt();
+    }
+    public long readLong() throws IOException {
+        return delegate.readLong();
+    }
+    public float readFloat() throws IOException {
+        return delegate.readFloat();
+    }
+    public double readDouble() throws IOException {
+        return delegate.readDouble();
+    }
+    public void readFully(byte[] buf) throws IOException {
+        delegate.readFully(buf);
+    }
+    public void readFully(byte[] buf, int off, int len) throws IOException {
+        delegate.readFully(buf, off, len);
+    }
+    public int skipBytes(int len) throws IOException {
+        return delegate.skipBytes(len);
+    }
+    @Deprecated
+    public String readLine() throws IOException {
+        return delegate.readLine();
+    }
+    public String readUTF() throws IOException {
+        return delegate.readUTF();
+    }
+
+    ///////////////////////////////////////
+    // delegate methods for ObjectReader //
+    ///////////////////////////////////////
+
+    void _startValue() {
+        delegate._startValue();
+    }
+    void _endValue() {
+        delegate._endValue();
+    }
+    void setCurrentValueDescriptor(ValueDescriptor desc) {
+        delegate.setCurrentValueDescriptor(desc);
+    }
+    Object readAbstractObject() throws IndirectionException {
+        return delegate.readAbstractObject();
+    }
+    Object readAny() throws IndirectionException {
+        return delegate.readAny();
+    }
+    Object readValueObject() throws IndirectionException {
+        return delegate.readValueObject();
+    }
+    Object readValueObject(Class<?> clz) throws IndirectionException {
+        return delegate.readValueObject(clz);
+    }
+    org.omg.CORBA.Object readCorbaObject(Class<?> type) {
+        return delegate.readCorbaObject(type);
+    }
+    Remote readRemoteObject(Class<?> type) {
+        return delegate.readRemoteObject(type);
+    }
+    void readExternal(Externalizable ext) throws IOException, ClassNotFoundException {
+        delegate.readExternal(ext);
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DelegatingObjectReaderWithHook.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DelegatingObjectReaderWithHook.java
new file mode 100644
index 0000000..ab0489d
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/DelegatingObjectReaderWithHook.java
@@ -0,0 +1,171 @@
+package org.apache.yoko.rmi.impl;
+
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.InvalidObjectException;
+import java.io.NotActiveException;
+import java.io.ObjectInputValidation;
+import java.rmi.Remote;
+
+import org.omg.CORBA.portable.IndirectionException;
+
+abstract class DelegatingObjectReaderWithBeforeReadHook extends DelegatingObjectReader {
+    private final ObjectReader delegate;
+
+    DelegatingObjectReaderWithBeforeReadHook(ObjectReader delegate) throws IOException {
+        super.delegateTo(delegate);
+        this.delegate = delegate;
+    }
+
+    abstract void beforeRead();
+
+    @Override
+    final void delegateTo(ObjectReader delegate) {
+        throw new UnsupportedOperationException();
+    }
+
+    //////////////////////////////////////
+    // ONLY DELEGATE METHODS BELOW HERE //
+    //////////////////////////////////////
+
+    public int read(byte[] b) throws IOException {
+        beforeRead();
+        return delegate.read(b);
+    }
+    public long skip(long n) throws IOException {
+        beforeRead();
+        return delegate.skip(n);
+    }
+    public void mark(int readlimit) {
+        delegate.mark(readlimit);
+    }
+    public void reset() throws IOException {
+        delegate.reset();
+    }
+    public boolean markSupported() {
+        return delegate.markSupported();
+    }
+    public Object readUnshared() throws IOException, ClassNotFoundException {
+        beforeRead();
+        return delegate.readUnshared();
+    }
+
+    public abstract void defaultReadObject() throws IOException, ClassNotFoundException;
+    public abstract GetField readFields() throws IOException, ClassNotFoundException;
+
+    public void registerValidation(ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException {
+        delegate.registerValidation(obj, prio);
+    }
+    public int read() throws IOException {
+        beforeRead();
+        return delegate.read();
+    }
+    public int read(byte[] buf, int off, int len) throws IOException {
+        beforeRead();
+        return delegate.read(buf, off, len);
+    }
+    public int available() throws IOException {
+        return delegate.available();
+    }
+    public void close() throws IOException {
+        delegate.close();
+    }
+    public boolean readBoolean() throws IOException {
+        beforeRead();
+        return delegate.readBoolean();
+    }
+    public byte readByte() throws IOException {
+        beforeRead();
+        return delegate.readByte();
+    }
+    public int readUnsignedByte() throws IOException {
+        beforeRead();
+        return delegate.readUnsignedByte();
+    }
+    public char readChar() throws IOException {
+        beforeRead();
+        return delegate.readChar();
+    }
+    public short readShort() throws IOException {
+        beforeRead();
+        return delegate.readShort();
+    }
+    public int readUnsignedShort() throws IOException {
+        beforeRead();
+        return delegate.readUnsignedShort();
+    }
+    public int readInt() throws IOException {
+        beforeRead();
+        return delegate.readInt();
+    }
+    public long readLong() throws IOException {
+        beforeRead();
+        return delegate.readLong();
+    }
+    public float readFloat() throws IOException {
+        beforeRead();
+        return delegate.readFloat();
+    }
+    public double readDouble() throws IOException {
+        beforeRead();
+        return delegate.readDouble();
+    }
+    public void readFully(byte[] buf) throws IOException {
+        beforeRead();
+        delegate.readFully(buf);
+    }
+    public void readFully(byte[] buf, int off, int len) throws IOException {
+        beforeRead();
+        delegate.readFully(buf, off, len);
+    }
+    public int skipBytes(int len) throws IOException {
+        beforeRead();
+        return delegate.skipBytes(len);
+    }
+    @SuppressWarnings("deprecation")
+    public String readLine() throws IOException {
+        beforeRead();
+        return delegate.readLine();
+    }
+    public String readUTF() throws IOException {
+        beforeRead();
+        return delegate.readUTF();
+    }
+    @Override
+    protected final Object readObjectOverride() throws ClassNotFoundException ,IOException {
+        beforeRead();
+        return delegate.readObjectOverride();
+    };
+
+    ///////////////////////////////////////
+    // delegate methods for ObjectReader //
+    ///////////////////////////////////////
+    Object readAbstractObject() throws IndirectionException {
+        beforeRead();
+        return delegate.readAbstractObject();
+    }
+    Object readAny() throws IndirectionException {
+        beforeRead();
+        return delegate.readAny();
+    }
+    Object readValueObject() throws IndirectionException {
+        beforeRead();
+        return delegate.readValueObject();
+    }
+    Object readValueObject(Class<?> clz) throws IndirectionException {
+        beforeRead();
+        return delegate.readValueObject(clz);
+    }
+    org.omg.CORBA.Object readCorbaObject(Class<?> type) {
+        beforeRead();
+        return delegate.readCorbaObject(type);
+    }
+    Remote readRemoteObject(Class<?> type) {
+        beforeRead();
+        return delegate.readRemoteObject(type);
+    }
+    void readExternal(Externalizable ext) throws IOException, ClassNotFoundException {
+        beforeRead();
+        delegate.readExternal(ext);
+    }
+}
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
new file mode 100644
index 0000000..84478ca
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumDescriptor.java
@@ -0,0 +1,65 @@
+/**
+ *
+ * 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 java.io.IOException;
+import java.io.Serializable;
+
+class EnumDescriptor extends ValueDescriptor {
+    public EnumDescriptor(Class<?> type, TypeRepository repo) {
+        super(type, repo);
+    }
+
+    @Override
+    protected final long getSerialVersionUID() {
+        return 0L;
+    }
+
+    @Override
+    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 {
+        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..9ba2f4b
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/EnumSubclassDescriptor.java
@@ -0,0 +1,98 @@
+/**
+ *
+ * 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.portable.IndirectionException;
+import org.omg.CORBA.portable.InputStream;
+
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Map;
+
+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
+    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..691a566 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();
+    private String genExceptionRepId() {
         String name = type.getName();
-        String encname = null;
+        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('.', '/'));
     }
 
+    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..f6e42dc
--- /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
+    protected TypeCode genTypeCode() {
+        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..5b07d69
--- /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
+    protected final TypeCode genTypeCode() {
+        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 01e7da4..1b353be 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
@@ -17,7 +17,6 @@
 */ 
 package org.apache.yoko.rmi.impl;
 
-import org.omg.CORBA.AttributeDescription;
 import org.omg.CORBA.TypeCode;
 import org.omg.CORBA.ValueDefPackage.FullValueDescription;
 import org.omg.CORBA.ValueMember;
@@ -25,10 +24,9 @@
 /**
  * @author krab
  */
-public class FVDValueDescriptor extends ValueDescriptor {
-    FullValueDescription fvd;
-
-    String repid;
+class FVDValueDescriptor extends ValueDescriptor {
+    final FullValueDescription fvd;
+    final String repid;
 
     FVDValueDescriptor(FullValueDescription fvd, Class clazz,
             TypeRepository rep, String repid, ValueDescriptor super_desc) {
@@ -62,11 +60,11 @@
         _fields = new_fields;
     }
 
-    FieldDescriptor findField(ValueMember valueMember) {
+    private FieldDescriptor findField(ValueMember valueMember) {
         FieldDescriptor result = null;
 
-        for (Class c = getJavaClass(); c != null; c = c.getSuperclass()) {
-            TypeDescriptor td = getTypeRepository().getDescriptor(c);
+        for (Class c = type; c != null; c = c.getSuperclass()) {
+            TypeDescriptor td = repo.getDescriptor(c);
             if (td instanceof ValueDescriptor) {
                 ValueDescriptor vd = (ValueDescriptor) td;
                 FieldDescriptor[] fds = vd._fields;
@@ -86,35 +84,23 @@
         return result;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.yoko.rmi.impl.TypeDescriptor#getRepositoryID()
-     */
-    public String getRepositoryID() {
+    @Override
+    protected String genRepId() {
         return repid;
     }
 
+    @Override
     org.omg.CORBA.ValueDefPackage.FullValueDescription getFullValueDescription() {
         return fvd;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.yoko.rmi.impl.TypeDescriptor#getTypeCode()
-     */
-    public TypeCode getTypeCode() {
+    @Override
+    protected final TypeCode genTypeCode() {
         return fvd.type;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.apache.yoko.rmi.impl.TypeDescriptor#isCustomMarshalled()
-     */
+    @Override
     public boolean isCustomMarshalled() {
         return fvd.is_custom;
     }
-
 }
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 a19d21b..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
@@ -1,20 +1,20 @@
 /**
-*
-* 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.
-*/ 
+ *
+ * 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;
 
@@ -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))
+                    || 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) {
@@ -1167,31 +1177,31 @@
     void read(ObjectReader reader, Object obj) throws IOException {
         Object value = reader.readCorbaObject(null);
         try {
-	    field.set(obj, value);
-	} catch (IllegalAccessException e) {
-	    throw (IOException)new IOException(e.getMessage()).initCause(e);
-	}
+            field.set(obj, value);
+        } catch (IllegalAccessException e) {
+            throw (IOException)new IOException(e.getMessage()).initCause(e);
+        }
     }
 
     void readFieldIntoMap(ObjectReader reader, Map map) throws IOException {
-	Object value = reader.readCorbaObject(null);
-	map.put(getJavaName(), value);
-	
+        Object value = reader.readCorbaObject(null);
+        map.put(java_name, value);
+
     }
 
     void write(ObjectWriter writer, Object obj) throws IOException {
-	try {
-	    writer.writeCorbaObject(field.get(obj));
-	}
-	catch(IllegalAccessException e) {
-	    throw (IOException)new IOException(e.getMessage()).initCause(e);
-	}
+        try {
+            writer.writeCorbaObject(field.get(obj));
+        }
+        catch(IllegalAccessException e) {
+            throw (IOException)new IOException(e.getMessage()).initCause(e);
+        }
     }
 
     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 cf7319d..c7ff610 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
@@ -18,105 +18,83 @@
 
 package org.apache.yoko.rmi.impl;
 
+import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.ObjectImpl;
+import org.omg.CORBA.portable.OutputStream;
+
+import javax.rmi.CORBA.Util;
+import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Map;
 
-import org.omg.CORBA.MARSHAL;
-
-public class IDLEntityDescriptor extends ValueDescriptor {
-    Method _read_method;
-
-    Method _write_method;
-
-    Method _type_method;
-
-    boolean isAbstract = false;
-
-    boolean isCorba = false; 
+class IDLEntityDescriptor extends ValueDescriptor {
+    private final boolean isCorba;
+    private final Class helperType;
 
     IDLEntityDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
 
-        if (org.omg.CORBA.Object.class.isAssignableFrom(type)) {
-            isCorba = true; 
-        }
-    }
-
-    public String getIDLName() {
-        return "org_omg_boxedIDL_" + super.getIDLName();
-    }
-
-    public void initIDL() {
-        super.init();
-
+        isCorba = org.omg.CORBA.Object.class.isAssignableFrom(type);
         try {
-            final Class type = getJavaClass();
             final String helperName = type.getName() + "Helper";
-            final Class helperClass = javax.rmi.CORBA.Util.loadClass(
-                    helperName, null, type.getClassLoader());
-
-            java.security.AccessController
-                    .doPrivileged(new java.security.PrivilegedAction() {
-                        public Object run() {
-
-                            try {
-                                Method _id_method = null;
-                                Method[] methods = helperClass
-                                        .getDeclaredMethods();
-                                for (int i = 0; i < methods.length; i++) {
-                                    String name = methods[i].getName();
-
-                                    if (name.equals("id"))
-                                        _id_method = methods[i];
-
-                                    else if (name.equals("read"))
-                                        _read_method = methods[i];
-
-                                    else if (name.equals("write"))
-                                        _write_method = methods[i];
-
-                                    else if (name.equals("type"))
-                                        _type_method = methods[i];
-                                }
-
-                                // _repid = (String)
-                                _id_method.invoke(null, new Object[0]);
-
-                            } catch (InvocationTargetException ex) {
-                                throw new RuntimeException(
-                                        "cannot initialize: " + ex, ex);
-
-                            } catch (IllegalAccessException ex) {
-                                throw new RuntimeException(
-                                        "cannot initialize: " + ex, ex);
-                            }
-
-                            return null;
-                        }
-                    });
-
+            helperType = Util.loadClass(helperName, null, type.getClassLoader());
         } catch (ClassNotFoundException ex) {
             throw new RuntimeException("cannot load IDL Helper class for "
-                    + getJavaClass(), ex);
+                    + type, ex);
         }
     }
 
-    /*
-     * public String getRepositoryID () { return _repid; }
-     */
+    @Override
+    protected final String genIDLName() {
+        return "org_omg_boxedIDL_" + super.genIDLName();
+    }
+
+    private volatile Method readMethod = null;
+    private Method getReadMethod() {
+        if (null == readMethod) readMethod = genHelperMethod("read");
+        return readMethod;
+    }
+
+    private volatile Method writeMethod = null;
+    private Method getWriteMethod() {
+        if (null == writeMethod) writeMethod = genHelperMethod("write");
+        return writeMethod;
+    }
+
+    private volatile Method typeMethod = null;
+    private Method getTypeMethod() {
+        if (null == typeMethod) typeMethod = genHelperMethod("type");
+        return typeMethod;
+    }
+
+    private Method genHelperMethod(final String name) {
+        return AccessController.doPrivileged(new PrivilegedAction<Method>() {
+            @Override
+            public Method run() {
+                for (Method m: helperType.getDeclaredMethods()) {
+                    if (m.getName().equals(name)) return m;
+                }
+                throw new RuntimeException("Unable to find " + name + " method for " + helperType.getName());
+            }
+        });
+    }
 
     /** Read an instance of this value from a CDR stream */
-    public Object read(org.omg.CORBA.portable.InputStream in) {
+    @Override
+    public Object read(InputStream in) {
         org.omg.CORBA_2_3.portable.InputStream _in = (org.omg.CORBA_2_3.portable.InputStream) in;
         
         // there are two ways we need to deal with IDLEntity classes.  Ones that also implement 
         // 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()); 
-        }
-        else {
-
+            return _in.read_Object(type);
+        } else {
             // we directly call read_value() on the stream here, with the explicitly specified
             // repository ID.  The input stream will handle validating the value tag for us, and eventually
             // will call our readValue() method to deserialize the object.
@@ -124,80 +102,57 @@
         }
     }
 
-    public java.io.Serializable readValue(
-            final org.omg.CORBA.portable.InputStream in,
-            final java.util.Map offsetMap, final java.lang.Integer offset) {
-        final java.io.Serializable value = (java.io.Serializable) readValue(in);
-
-        offsetMap.put(offset, value);
-
-        return value;
-    }
-
-    public Object readValue(org.omg.CORBA.portable.InputStream in) {
-        if (isAbstract) {
-            throw new MARSHAL("IDL Entity " + getJavaClass().getName()
-                    + " is abstract");
-        }
-
+    @Override
+    public Serializable readValue(final InputStream in, final Map offsetMap, final Integer offset) {
         try {
-            return _read_method.invoke(null, new Object[] { in });
+            Serializable value = (Serializable) getReadMethod().invoke(null, new Object[]{in});
+            offsetMap.put(offset, value);
+            return value;
         } catch (InvocationTargetException ex) {
-            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(ex.getMessage()).initCause(ex);
+            throw (MARSHAL)new MARSHAL(""+ex.getCause()).initCause(ex.getCause());
         } catch (IllegalAccessException ex) {
-            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(ex.getMessage()).initCause(ex);
+            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
     }
 
     /** Write an instance of this value to a CDR stream */
-    public void write(org.omg.CORBA.portable.OutputStream out, Object val) {
+    @Override
+    public void write(OutputStream out, Object val) {
         org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;
 
         
         // there are two ways we need to deal with IDLEntity classes.  Ones that also implement 
         // the CORBA Object interface are actual corba objects, and must be handled that way. 
         // Other IDLEntity classes are just transmitted by value. 
-        if (val instanceof org.omg.CORBA.portable.ObjectImpl) {
+        if (val instanceof ObjectImpl) {
             _out.write_Object((org.omg.CORBA.Object)val); 
-        }
-        else {
+        } else {
             // we directly call write_value() on the stream here, with the explicitly specified
             // repository ID.  the output stream will handle writing the value tag for us, and eventually
             // will call our writeValue() method to serialize the object.
-            _out.write_value((java.io.Serializable)val, getRepositoryID());
+            _out.write_value((Serializable)val, getRepositoryID());
         }
-
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out, java.io.Serializable val) {
-        if (isAbstract) {
-            throw new MARSHAL("IDL Entity " + getJavaClass().getName()
-                    + " is abstract");
-        }
-
+    @Override
+    public void writeValue(OutputStream out, Serializable val) {
         try {
-            _write_method.invoke(null, new Object[] { out, val });
+            getWriteMethod().invoke(null, new Object[] { out, val });
         } catch (InvocationTargetException ex) {
-            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(ex.getMessage()).initCause(ex);
+            throw (MARSHAL)new MARSHAL(""+ ex.getCause()).initCause(ex.getCause());
         } catch (IllegalAccessException ex) {
-            throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(ex.getMessage()).initCause(ex);
+            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
     }
 
-    org.omg.CORBA.TypeCode getTypeCode() {
-        if (_type_code == null) {
-
-            try {
-                _type_code = (org.omg.CORBA.TypeCode) _type_method.invoke(null,
-                        new Object[0]);
-            } catch (InvocationTargetException ex) {
-                throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(ex.getMessage()).initCause(ex);
-            } catch (IllegalAccessException ex) {
-                throw (org.omg.CORBA.MARSHAL)new org.omg.CORBA.MARSHAL(ex.getMessage()).initCause(ex);
-            }
+    @Override
+    protected TypeCode genTypeCode() {
+        try {
+            return (TypeCode) getTypeMethod().invoke(null, new Object[0]);
+        } catch (InvocationTargetException ex) {
+            throw (MARSHAL)new MARSHAL(""+ex.getCause()).initCause(ex.getCause());
+        } catch (IllegalAccessException ex) {
+            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
         }
-
-        return _type_code;
     }
-
 }
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..81a049b 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
@@ -33,7 +33,7 @@
     static final Logger logger = Logger.getLogger(MethodDescriptor.class.getName());
 
     /** The refleced method object for this method */
-    java.lang.reflect.Method reflected_method;
+    final java.lang.reflect.Method reflected_method;
 
     java.lang.Object invocation_block_selector;
 
@@ -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].type.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..3f37c7b 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,21 @@
 
 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 
-
-    protected void setIDLName(String name) {
-        idl_name = name;
-    }
-    
-    public String getIDLName() {
-        return idl_name;
+abstract class ModelElement {
+    final TypeRepository repo;
+    final String java_name;    // the java name of the type
+    protected ModelElement(TypeRepository repo, String java_name) {
+        this.repo = repo;
+        this.java_name = java_name;
     }
 
-    protected void setTypeName(String name) {
-        type_name = name;
-    }
-    
-    public String getTypeName() {
-        return type_name;
+    protected void init() {
     }
 
-    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;
+    private volatile String idlName = null;   // fully resolved package name
+    protected abstract String genIDLName();
+    public final String getIDLName() {
+        if (null == idlName) idlName = genIDLName();
+        return idlName;
     }
 }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectReader.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectReader.java
index 970165d..e27018d 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectReader.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/ObjectReader.java
@@ -1,20 +1,20 @@
 /**
-*
-* 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.
-*/ 
+ *
+ * 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;
 
@@ -22,21 +22,42 @@
 import java.io.IOException;
 import java.io.InvalidObjectException;
 import java.io.NotActiveException;
+import java.io.ObjectInputStream;
 import java.io.ObjectInputValidation;
 import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.rmi.Remote;
 import java.util.Map;
 
 import org.apache.yoko.rmi.util.PriorityQueue;
+import org.omg.CORBA.portable.IndirectionException;
 
+abstract class ObjectReader extends ObjectInputStream {
+    ObjectReader() throws IOException {}
 
-public abstract class ObjectReader extends java.io.ObjectInputStream {
+    abstract void _startValue();
+    abstract void _endValue();
+    abstract void setCurrentValueDescriptor(ValueDescriptor desc);
+    abstract Object readAbstractObject() throws IndirectionException;
+    abstract Object readAny() throws IndirectionException;
+    abstract Object readValueObject() throws IndirectionException;
+    abstract Object readValueObject(Class<?> clz) throws IndirectionException;
+    abstract org.omg.CORBA.Object readCorbaObject(Class<?> type);
+    abstract Remote readRemoteObject(Class<?> type);
+    abstract void readExternal(Externalizable ext) throws IOException, ClassNotFoundException;
+    
+    @Override
+    protected abstract Object readObjectOverride() throws IOException, ClassNotFoundException;
+}
+
+abstract class ObjectReaderBase extends ObjectReader {
     int recursionDepth = 0;
 
     final java.io.Serializable object;
 
     PriorityQueue callbacks;
 
-    ObjectReader(java.io.Serializable obj) throws java.io.IOException {
+    ObjectReaderBase(Serializable obj) throws IOException {
         super();
         this.object = obj;
     }
@@ -49,16 +70,14 @@
         this.desc = desc;
     }
 
-    public final void defaultReadObject() throws java.io.IOException,
-            ClassNotFoundException, java.io.NotActiveException {
+    public final void defaultReadObject() throws IOException, ClassNotFoundException, NotActiveException {
         if (desc == null) {
             throw new java.io.NotActiveException();
         }
         desc.defaultReadValue(this, object);
     }
 
-    protected final java.lang.Object readObjectOverride()
-            throws java.lang.ClassNotFoundException, java.io.IOException {
+    protected final Object readObjectOverride() throws ClassNotFoundException, IOException {
         try {
             enterRecursion();
             return readAbstractObject();
@@ -67,11 +86,11 @@
         }
     }
 
-    protected void enterRecursion() {
+    private void enterRecursion() {
         recursionDepth += 1;
     }
 
-    protected void exitRecursion() throws InvalidObjectException {
+    private void exitRecursion() throws InvalidObjectException {
         recursionDepth -= 1;
 
         if (recursionDepth == 0) {
@@ -84,7 +103,7 @@
         }
     }
 
-    private class Validation implements Comparable {
+    private class Validation implements Comparable<Validation> {
         ObjectInputValidation validator;
 
         int pri;
@@ -94,10 +113,8 @@
             this.pri = pri;
         }
 
-        public int compareTo(Object other) {
-            Validation o = (Validation) other;
-
-            return pri - o.pri;
+        public int compareTo(Validation other) {
+            return pri - other.pri;
         }
 
         void validate() throws InvalidObjectException {
@@ -105,15 +122,13 @@
         }
     }
 
-    public synchronized void registerValidation(ObjectInputValidation obj,
-            int prio) throws NotActiveException, InvalidObjectException {
+    public synchronized void registerValidation(ObjectInputValidation obj, int prio) throws NotActiveException, InvalidObjectException {
         if (recursionDepth == 0) {
             throw new NotActiveException("readObject not Active");
         }
 
         if (obj == null) {
-            throw new InvalidObjectException(
-                    "Null is not a valid callback object");
+            throw new InvalidObjectException("Null is not a valid callback object");
         }
 
         Validation val = new Validation(obj, prio);
@@ -125,30 +140,11 @@
         callbacks.enqueue(val);
     }
 
-    public abstract Object readAbstractObject()
-            throws org.omg.CORBA.portable.IndirectionException;
+    public void close() throws java.io.IOException {}
 
-    public abstract Object readAny()
-            throws org.omg.CORBA.portable.IndirectionException;
-
-    public abstract Object readValueObject()
-            throws org.omg.CORBA.portable.IndirectionException;
-
-    public abstract Object readValueObject(Class clz)
-            throws org.omg.CORBA.portable.IndirectionException;
-
-    public abstract org.omg.CORBA.Object readCorbaObject(Class type);
-    
-    public abstract java.rmi.Remote readRemoteObject(Class type);
-    
-    public void close() throws java.io.IOException {
-        // skip //
-    }
-
-    public java.io.ObjectInputStream.GetField readFields()
-            throws java.io.IOException {
+    public java.io.ObjectInputStream.GetField readFields() throws IOException {
         if (desc == null) {
-            throw new java.io.NotActiveException();
+            throw new NotActiveException();
         }
 
         Map fieldMap = desc.readFields(this);
@@ -156,15 +152,15 @@
         return new GetFieldImpl(fieldMap);
     }
 
-    public void readFully(byte[] arr) throws java.io.IOException {
+    public void readFully(byte[] arr) throws IOException {
         readFully(arr, 0, arr.length);
     }
 
-    public int readUnsignedByte() throws java.io.IOException {
+    public int readUnsignedByte() throws IOException {
         return ((int) readByte()) & 0xff;
     }
 
-    public int readUnsignedShort() throws java.io.IOException {
+    public int readUnsignedShort() throws IOException {
         int val = readShort();
         return val & 0xffff;
     }
@@ -173,7 +169,7 @@
 
         Map fieldMap;
 
-        GetFieldImpl(java.util.Map map) {
+        GetFieldImpl(Map map) {
             fieldMap = map;
         }
 
@@ -301,11 +297,7 @@
 
     }
 
-    /**
-     * @param ext
-     */
-    void readExternal(Externalizable ext) throws IOException,
-            ClassNotFoundException {
+    void readExternal(Externalizable ext) throws IOException, ClassNotFoundException {
         byte old = streamFormatVersion;
         try {
             streamFormatVersion = readByte();
@@ -314,5 +306,4 @@
             streamFormatVersion = old;
         }
     }
-
 }
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 9b2e0f1..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
@@ -1,245 +1,167 @@
 /**
-*
-* 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.
-*/ 
+ *
+ * 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.Externalizable;
 import java.io.IOException;
+import java.io.NotActiveException;
 import java.io.ObjectOutput;
+import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
 
-abstract class ObjectWriter extends java.io.ObjectOutputStream {
-    protected final java.io.Serializable object;
+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;
 
     private ValueDescriptor _desc;
 
     private PutFieldImpl _putFields;
 
-    private WriteObjectState state = NOT_IN_WRITE_OBJECT;
+    private WriteObjectState state = WriteObjectState.NOT_IN_WRITE_OBJECT;
 
-    private byte streamFormatVersion = 1;
+    final byte cmsf;
+    final Set<Yasf> yasfSet;
 
-    static class WriteObjectState {
-        void beforeWriteObject(ObjectWriter writer) throws IOException {
+    private enum WriteObjectState {
+        NOT_IN_WRITE_OBJECT {
+            void beforeWriteObject(ObjectWriter writer) {
+                writer.state = IN_WRITE_OBJECT;
+            }
+        },
+        IN_WRITE_OBJECT {
+            void afterWriteObject(ObjectWriter writer) throws IOException {
+                writer.state = NOT_IN_WRITE_OBJECT;
+
+                // there is no custom (nor default) state written
+                writer.writeBoolean(false);
+
+                // 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.cmsf == 2) {
+                    writer._nullValue();
+                }
+            }
+
+            void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
+                writer.state = IN_DEFAULT_WRITE_OBJECT;
+                writer.writeBoolean(true);
+            }
+
+            void beforeWriteData(ObjectWriter writer) throws IOException {
+                writer.state = WROTE_CUSTOM_DATA;
+
+                // writeDefaultObject was not invoked
+                writer.writeBoolean(false);
+
+                if (writer.cmsf == 2) {
+                    writer._startValue(writer._desc.getCustomRepositoryID());
+                }
+            }
+        },
+        IN_DEFAULT_WRITE_OBJECT {
+            void afterDefaultWriteObject(ObjectWriter writer) {
+                writer.state = WROTE_DEFAULT_DATA;
+            }
+        },
+        WROTE_DEFAULT_DATA {
+            void afterWriteObject(ObjectWriter writer) throws IOException {
+                // the boolean identifying that default data was written has already
+                // been emitted in IN_WRITE_OBJECT.beforeWriteDefaultObject
+                writer.state = NOT_IN_WRITE_OBJECT;
+
+                // write a null-marker to identify that there is no custom
+                // state being marshalled...
+                if (writer.cmsf == 2) {
+                    writer._nullValue();
+                }
+            }
+
+            void beforeWriteData(ObjectWriter writer) throws IOException {
+                // the boolean identifying that default data was written has already
+                // been emitted in IN_WRITE_OBJECT.beforeWriteDefaultObject
+                writer.state = WROTE_CUSTOM_DATA;
+
+                if (writer.cmsf == 2) {
+                    writer._startValue(writer._desc.getCustomRepositoryID());
+                }
+            }
+        },
+        WROTE_CUSTOM_DATA {
+            void afterWriteObject(ObjectWriter writer) throws IOException {
+                if (writer.cmsf == 2) {
+                    writer._endValue();
+                }
+
+                writer.state = NOT_IN_WRITE_OBJECT;
+            }
+        }
+        ;
+
+        void beforeWriteObject(ObjectWriter writer) {
+            throw new IllegalStateException();
         }
 
         void afterWriteObject(ObjectWriter writer) throws IOException {
+            throw new IllegalStateException();
         }
 
         void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
+            throw new IllegalStateException();
         }
 
-        void afterDefaultWriteObject(ObjectWriter writer) throws IOException {
+        void afterDefaultWriteObject(ObjectWriter writer) {
+            throw new IllegalStateException();
         }
 
         void beforeWriteData(ObjectWriter writer) throws IOException {
         }
     }
 
-    static WriteObjectState NOT_IN_WRITE_OBJECT = new WriteObjectState() {
-        void beforeWriteObject(ObjectWriter writer) throws IOException {
-            writer.state = IN_WRITE_OBJECT;
-        }
-
-        void afterWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void afterDefaultWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-    };
-
-    static WriteObjectState IN_WRITE_OBJECT = new WriteObjectState() {
-        void beforeWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("already in writeObject");
-        }
-
-        void afterWriteObject(ObjectWriter writer) throws IOException {
-
-            writer.state = NOT_IN_WRITE_OBJECT;
-
-            // there is no custom (nor default) state written
-            writer.writeBoolean(false);
-
-            // If we're in stream format verison 2, we must
-            // put the "null" marker to say that there isn't
-            // any optional data
-            if (writer.getStreamFormatVersion() == 2) {
-                writer._nullValue();
-            }
-
-        }
-
-        void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
-            writer.state = IN_DEFAULT_WRITE_OBJECT;
-            writer.writeBoolean(true);
-        }
-
-        void afterDefaultWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see org.apache.yoko.rmi.impl.ObjectWriter.WriteObjectState#writeData(org.apache.yoko.rmi.impl.ObjectWriter)
-         */
-        void beforeWriteData(ObjectWriter writer) throws IOException {
-            writer.state = WROTE_CUSTOM_DATA;
-
-            // writeDefaultObject was not invoked
-            writer.writeBoolean(false);
-
-            if (writer.getStreamFormatVersion() == 2) {
-                writer._startValue(writer._desc.getRepositoryID());
-            }
-
-        }
-    };
-
-    static WriteObjectState IN_DEFAULT_WRITE_OBJECT = new WriteObjectState() {
-
-        void beforeWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void afterWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void afterDefaultWriteObject(ObjectWriter writer) throws IOException {
-            writer.state = WROTE_DEFAULT_DATA;
-        }
-
-        void beforeWriteData(ObjectWriter writer) throws IOException {
-            // do nothing
-        }
-    };
-
-    static WriteObjectState WROTE_DEFAULT_DATA = new WriteObjectState() {
-
-        void afterWriteObject(ObjectWriter writer) throws IOException {
-
-            // the boolean identifying that default data was written has already
-            // been emitted in IN_WRITE_OBJECT.beforeWriteDefaultObject
-
-            writer.state = NOT_IN_WRITE_OBJECT;
-
-            // write a null-marker to identify that there is no custom
-            // state being marshalled...
-            if (writer.getStreamFormatVersion() == 2) {
-                writer._nullValue();
-            }
-
-        }
-
-        void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void afterDefaultWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void beforeWriteData(ObjectWriter writer) throws IOException {
-
-            // the boolean identifying that default data was written has already
-            // been emitted in IN_WRITE_OBJECT.beforeWriteDefaultObject
-
-            writer.state = WROTE_CUSTOM_DATA;
-
-            if (writer.getStreamFormatVersion() == 2) {
-                writer._startValue(writer._desc.getRepositoryID());
-            }
-
-        }
-    };
-
-    static WriteObjectState WROTE_CUSTOM_DATA = new WriteObjectState() {
-        /*
-         * (non-Javadoc)
-         * 
-         * @see org.apache.yoko.rmi.impl.ObjectWriter.WriteObjectState#afterWriteObject(org.apache.yoko.rmi.impl.ObjectWriter)
-         */
-        void afterWriteObject(ObjectWriter writer) throws IOException {
-            if (writer.getStreamFormatVersion() == 2) {
-                writer._endValue();
-            }
-
-            writer.state = NOT_IN_WRITE_OBJECT;
-        }
-
-        void beforeDefaultWriteObject(ObjectWriter writer) throws IOException {
-            throw new IllegalStateException("");
-        }
-
-        void afterDefaultWriteObject(ObjectWriter writer) {
-            throw new IllegalStateException("");
-        }
-
-        /*
-         * (non-Javadoc)
-         * 
-         * @see org.apache.yoko.rmi.impl.ObjectWriter.WriteObjectState#writeData(org.apache.yoko.rmi.impl.ObjectWriter)
-         */
-        void beforeWriteData(ObjectWriter writer) throws IOException {
-            // do nothing
-        }
-    };
-
     protected void beforeWriteData() throws IOException {
         state.beforeWriteData(this);
     }
 
-    ObjectWriter(java.io.Serializable obj) throws java.io.IOException {
+    ObjectWriter(Serializable obj) throws IOException {
         object = obj;
-    }
-
-    /**
-     * @return
-     */
-    protected byte getStreamFormatVersion() {
-        return streamFormatVersion;
+        cmsf = CmsfThreadLocal.get();
+        yasfSet = YasfThreadLocal.get();
     }
 
     abstract ObjectReader getObjectReader(Object newObject);
 
-    void setCurrentValueDescriptor(ValueDescriptor desc) {
+    private void setCurrentValueDescriptor(ValueDescriptor desc) {
         _desc = desc;
         _putFields = null;
     }
 
-    public final void defaultWriteObject() throws java.io.IOException,
-            java.io.NotActiveException {
+    public final void defaultWriteObject() throws IOException {
         if (_desc == null) {
-            throw new java.io.NotActiveException();
+            throw new NotActiveException();
         }
 
         state.beforeDefaultWriteObject(this);
@@ -250,10 +172,10 @@
         }
     }
 
-    public java.io.ObjectOutputStream.PutField putFields()
-            throws java.io.IOException {
+    public ObjectOutputStream.PutField putFields()
+            throws IOException {
         if (_desc == null) {
-            throw new java.io.NotActiveException();
+            throw new NotActiveException();
         }
 
         _putFields = new PutFieldImpl(_desc);
@@ -263,11 +185,11 @@
 
     public void writeFields() throws IOException {
         if (_putFields == null) {
-            throw new java.io.NotActiveException("no current PutFields");
+            throw new NotActiveException("no current PutFields");
         }
 
         if (_putFields.slice != _desc) {
-            throw new java.io.NotActiveException(
+            throw new NotActiveException(
                     "PutField cannot survive writeObject invocation");
         }
 
@@ -288,109 +210,82 @@
     public abstract void writeValueObject(Object obj) throws IOException;
 
     public abstract void writeRemoteObject(Object obj) throws IOException;
-    
+
     public abstract void writeCorbaObject(Object obj) throws IOException;
 
     public abstract void writeAny(Object obj) throws IOException;
-    
-    static class PutFieldImpl extends PutField {
-        ValueDescriptor slice;
 
-        java.util.Map valueMap = new HashMap();
+    static class PutFieldImpl extends PutField {
+        final ValueDescriptor slice;
+
+        final Map<String, Object> valueMap = new HashMap<>();
 
         PutFieldImpl(ValueDescriptor slice) {
             this.slice = slice;
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, boolean)
-         */
+        @Override
         public void put(String name, boolean val) {
-            valueMap.put(name, new Boolean(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, byte)
-         */
+        @Override
         public void put(String name, byte val) {
-            valueMap.put(name, new Byte(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, char)
-         */
+        @Override
         public void put(String name, char val) {
-            valueMap.put(name, new Character(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, double)
-         */
+        @Override
         public void put(String name, double val) {
-            valueMap.put(name, new Double(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, float)
-         */
+        @Override
         public void put(String name, float val) {
-            valueMap.put(name, new Float(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, int)
-         */
+        @Override
         public void put(String name, int val) {
-            valueMap.put(name, new Integer(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, long)
-         */
+        @Override
         public void put(String name, long val) {
-            valueMap.put(name, new Long(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, Object)
-         */
+        @Override
         public void put(String name, Object val) {
             valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#put(String, short)
-         */
+        @Override
         public void put(String name, short val) {
-            valueMap.put(name, new Short(val));
+            valueMap.put(name, val);
         }
 
-        /**
-         * @see java.io.ObjectOutputStream.PutField#write(ObjectOutput)
-         * @deprecated
-         */
+        @Override
         public void write(ObjectOutput out) throws IOException {
             slice.writeFields((ObjectWriter) out, valueMap);
         }
-
     }
 
-    /**
-     * @param descriptor
-     * @param val
-     * @param _write_object_method
-     */
     void invokeWriteObject(ValueDescriptor descriptor, Serializable val,
-            Method _write_object_method) throws IllegalArgumentException,
+                           Method _write_object_method) throws IllegalArgumentException,
             IllegalAccessException, InvocationTargetException, IOException {
-        ValueDescriptor desc = _desc;
-        WriteObjectState old_state = state;
-        state = NOT_IN_WRITE_OBJECT;
+        final ValueDescriptor desc = _desc;
+        final WriteObjectState old_state = state;
+        state = WriteObjectState.NOT_IN_WRITE_OBJECT;
         try {
             setCurrentValueDescriptor(descriptor);
-            writeByte(getStreamFormatVersion());
+            writeByte(cmsf);
             state.beforeWriteObject(this);
-            _write_object_method.invoke(val, new Object[] { this });
+            _write_object_method.invoke(val, this);
             state.afterWriteObject(this);
         } finally {
             state = old_state;
@@ -404,11 +299,8 @@
 
     protected abstract void _nullValue() throws IOException;
 
-    /**
-     * @param externalizable
-     */
     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/PortableRemoteObjectImpl.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/PortableRemoteObjectImpl.java
index 47badf7..c3815b2 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/PortableRemoteObjectImpl.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/PortableRemoteObjectImpl.java
@@ -24,10 +24,13 @@
 import java.rmi.Remote;
 import java.rmi.RemoteException;
 import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.logging.Logger;
 import java.util.logging.Level;
 
 import javax.rmi.CORBA.PortableRemoteObjectDelegate;
+import javax.rmi.CORBA.Stub;
 import javax.rmi.CORBA.Tie;
 import javax.rmi.CORBA.Util;
 
@@ -38,21 +41,18 @@
 import org.apache.yoko.rmi.util.stub.StubInitializer;
 import org.apache.yoko.rmispec.util.UtilLoader;
 import org.omg.CORBA.BAD_INV_ORDER;
+import org.omg.CORBA.portable.IDLEntity;
 import org.omg.CORBA.portable.ObjectImpl;
 
 
 public class PortableRemoteObjectImpl implements PortableRemoteObjectDelegate {
-    static final Logger logger = Logger
+    static final Logger LOGGER = Logger
             .getLogger(PortableRemoteObjectImpl.class.getName());
 
     static {
-        // Initialize the stub handler factory when first loaded to ensure we have 
-        // class loading visibility to the factory. 
-        getRMIStubInitializer(); 
-    }
-
-    private static TypeRepository getTypeRepository() {
-        return RMIState.current().getTypeRepository();
+        // Initialize the stub handler factory when first loaded to ensure we have
+        // class loading visibility to the factory.
+        getRMIStubInitializer();
     }
 
     static org.omg.CORBA.ORB getORB() {
@@ -80,15 +80,14 @@
 
             try {
                 exportObject(target);
-            } catch (java.rmi.RemoteException ex) {
+            } catch (RemoteException ex) {
                 // ignore "already exported test" //
             }
 
             try {
                 obj = (ObjectImpl) toStub(target);
             } catch (java.rmi.NoSuchObjectException ex) {
-                throw (java.rmi.RemoteException)new 
-                    java.rmi.RemoteException("cannot convert to stub!").initCause(ex);
+                throw (RemoteException)new RemoteException("cannot convert to stub!").initCause(ex);
             }
         }
 
@@ -100,7 +99,77 @@
         }
     }
 
-    public Object narrow(Object narrowFrom, Class narrowTo)
+    private Object narrowRMI(ObjectImpl narrowFrom, Class<?> narrowTo) {
+        if (LOGGER.isLoggable(Level.FINE))
+            LOGGER.fine(String.format("RMI narrowing %s => %s", narrowFrom.getClass().getName(), narrowTo.getName()));
+        ObjectImpl object = narrowFrom;
+
+        final String codebase = getCodebase(narrowFrom);
+
+        RMIState state = RMIState.current();
+
+        javax.rmi.CORBA.Stub stub;
+        try {
+            stub = createStub(state, codebase, narrowTo);
+        } catch (ClassNotFoundException ex) {
+            throw (ClassCastException)new ClassCastException(narrowTo.getName()).initCause(ex);
+        }
+
+        org.omg.CORBA.portable.Delegate delegate;
+        try {
+            // let the stub adopt narrowFrom's identity
+            delegate = object._get_delegate();
+
+        } catch (org.omg.CORBA.BAD_OPERATION ex) {
+            // ignore
+            delegate = null;
+        }
+
+        stub._set_delegate(delegate);
+
+        return stub;
+    }
+
+    private String getCodebase(ObjectImpl narrowFrom) {
+        String codebase;
+        if (narrowFrom instanceof org.omg.CORBA_2_3.portable.ObjectImpl) {
+            org.omg.CORBA_2_3.portable.ObjectImpl object_2_3 = (org.omg.CORBA_2_3.portable.ObjectImpl) narrowFrom;
+
+            try {
+                codebase = object_2_3._get_codebase();
+            } catch (org.omg.CORBA.BAD_OPERATION ex) {
+                codebase = null;
+            }
+        } else {
+            codebase = null;
+        }
+        return codebase;
+    }
+
+    private Object narrowIDL(ObjectImpl narrowFrom, Class<?> narrowTo) {
+        if (LOGGER.isLoggable(Level.FINE))
+            LOGGER.fine(String.format("IDL narrowing %s => %s", narrowFrom.getClass().getName(), narrowTo.getName()));
+        final ClassLoader idlClassLoader = UtilImpl.getClassLoader(narrowTo);
+        final String codebase = getCodebase(narrowFrom);
+        final String helperClassName = narrowTo.getName() + "Helper";
+
+        try {
+            final Class<?> helperClass = Util.loadClass(helperClassName, codebase, idlClassLoader);
+            final Method helperNarrow = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
+                @Override
+                public Method run() throws Exception {
+                    return helperClass.getMethod("narrow", org.omg.CORBA.Object.class);
+                }
+            });
+            return helperNarrow.invoke(null, narrowFrom);
+        } catch (PrivilegedActionException e) {
+            throw (ClassCastException)new ClassCastException(narrowTo.getName()).initCause(e.getCause());
+        } catch (Exception e) {
+            throw (ClassCastException)new ClassCastException(narrowTo.getName()).initCause(e);
+        }
+    }
+
+    public Object narrow(Object narrowFrom, @SuppressWarnings("rawtypes") Class narrowTo)
             throws ClassCastException {
         if (narrowFrom == null)
             return null;
@@ -108,124 +177,37 @@
         if (narrowTo.isInstance(narrowFrom))
             return narrowFrom;
 
-        logger.finer("narrow " + narrowFrom.getClass().getName() + " => " + narrowTo.getName());
+        final String fromClassName = narrowFrom.getClass().getName();
+        final String toClassName = narrowTo.getName();
+        if (LOGGER.isLoggable(Level.FINE))
+            LOGGER.finer(String.format("narrow %s => %s", fromClassName, toClassName));
 
-        if (narrowFrom instanceof org.omg.CORBA.portable.ObjectImpl
-                && narrowTo.isInterface()
-                && java.rmi.Remote.class.isAssignableFrom(narrowTo)) {
-            org.omg.CORBA.portable.ObjectImpl object = (org.omg.CORBA.portable.ObjectImpl) narrowFrom;
+        if (!(narrowFrom instanceof org.omg.CORBA.portable.ObjectImpl))
+            throw new ClassCastException(String.format(
+                    "object to narrow (runtime type %s) is not an instance of %s",
+                    fromClassName, ObjectImpl.class.getName()));
+        if (!narrowTo.isInterface())
+            throw new ClassCastException(String.format("%s is not an interface", toClassName));
 
-            String id = getTypeRepository().getDescriptor(narrowTo)
-                    .getRepositoryID();
+        final boolean isRemote = Remote.class.isAssignableFrom(narrowTo);
+        final boolean isIDLEntity = IDLEntity.class.isAssignableFrom(narrowTo);
 
-            //
-            // actually call _is_a to verify runtime type
-            //
-            /*
-             * if (! object._is_a (id)) { throw new ClassCastException (id); }
-             */
-            //
-            // Get the codebase for this object, if possible...
-            //
-            String codebase = null;
-            if (narrowFrom instanceof org.omg.CORBA_2_3.portable.ObjectImpl) {
-                org.omg.CORBA_2_3.portable.ObjectImpl object_2_3 = (org.omg.CORBA_2_3.portable.ObjectImpl) narrowFrom;
+        if (isRemote && isIDLEntity)
+            throw new ClassCastException(String.format(
+                    "%s invalidly extends both %s and %s",
+                    toClassName, Remote.class.getName(), IDLEntity.class.getName()));
+        if (isRemote)
+            return narrowRMI((ObjectImpl) narrowFrom, narrowTo);
+        if (isIDLEntity)
+            return narrowIDL((ObjectImpl) narrowFrom, narrowTo);
 
-                try {
-                    codebase = object_2_3._get_codebase();
-                } catch (org.omg.CORBA.BAD_OPERATION ex) {
-                    codebase = null;
-                }
-            }
-
-            if (false) {
-                //
-                // use most specific class possible, so as to allow
-                // introspection
-                // of the available methods...
-                //
-                try {
-
-                    //
-                    // write object reference and read just the repository id
-                    //
-                    org.omg.CORBA.portable.OutputStream out = RMIState
-                            .current().getORB().create_output_stream();
-                    out.write_Object(object);
-                    org.omg.CORBA.portable.InputStream in = out
-                            .create_input_stream();
-                    String object_id = in.read_string();
-
-                    if (!object_id.equals(id) && object_id.startsWith("RMI:")) {
-
-                        String name = object_id.substring(4, object_id.indexOf(
-                                ':', 4));
-
-                        String baseName = RemoteDescriptor
-                                .classNameFromStub(name);
-                        if (baseName == null)
-                            baseName = name;
-
-                        //
-                        // Try loading the found type...
-                        //
-                        Class newNarrowTo = javax.rmi.CORBA.Util.loadClass(
-                                baseName, codebase, Thread.currentThread()
-                                        .getContextClassLoader());
-
-                        //
-                        // if the new narrow to is more specific, use it!
-                        //
-                        if (narrowTo.isAssignableFrom(newNarrowTo)) {
-                            narrowTo = newNarrowTo;
-
-                            logger.finer("NARROW " + object_id + " TO "
-                                    + narrowTo.getName());
-                        }
-                    }
-                } catch (ClassNotFoundException ex) {
-                    // ignore ..
-                } catch (org.omg.CORBA.SystemException ex) {
-                    // ignore
-                }
-            }
-
-            RMIState state = null;
-            if (narrowFrom instanceof RMIServant) {
-                state = ((RMIServant) narrowFrom).getRMIState();
-            } else {
-                state = RMIState.current();
-            }
-
-            javax.rmi.CORBA.Stub stub;
-            try {
-                stub = createStub(state, codebase, narrowTo);
-            } catch (ClassNotFoundException ex) {
-                throw (ClassCastException)new ClassCastException(narrowTo.getName()).initCause(ex);
-            }
-
-            org.omg.CORBA.portable.Delegate delegate;
-            try {
-                // let the stub adopt narrowFrom's identity
-                delegate = object._get_delegate();
-
-            } catch (org.omg.CORBA.BAD_OPERATION ex) {
-                // ignore
-                delegate = null;
-            }
-
-            stub._set_delegate(delegate);
-
-            return stub;
-        }
-
-        throw new ClassCastException(narrowTo.getName());
+        throw new ClassCastException(String.format(
+                    "%s extends neither %s nor %s",
+                    toClassName, Remote.class.getName(), IDLEntity.class.getName()));
     }
 
-    static java.rmi.Remote narrow1(RMIState state,
-            org.omg.CORBA.portable.ObjectImpl object, Class narrowTo)
-            throws ClassCastException {
-        javax.rmi.CORBA.Stub stub;
+    static java.rmi.Remote narrow1(RMIState state, ObjectImpl object, Class<?> narrowTo) throws ClassCastException {
+        Stub stub;
 
         try {
             stub = createStub(state, null, narrowTo);
@@ -248,14 +230,13 @@
         return (java.rmi.Remote) stub;
     }
 
-    static private javax.rmi.CORBA.Stub createStub(RMIState state,
-            String codebase, Class type) throws ClassNotFoundException {
-        if (java.rmi.Remote.class == type) {
+    static private Stub createStub(RMIState state, String codebase, Class<?> type) throws ClassNotFoundException {
+        if (Remote.class == type) {
             return new RMIRemoteStub();
         }
 
         if (ClientUtil.isRunningAsClientContainer()) {
-            javax.rmi.CORBA.Stub stub = state.getStaticStub(codebase, type);
+            Stub stub = state.getStaticStub(codebase, type);
             if (stub != null) {
                 return stub;
             }
@@ -266,25 +247,24 @@
 
     static Object[] NO_ARG = new Object[0];
 
-    static javax.rmi.CORBA.Stub createRMIStub(RMIState state, Class type)
-            throws ClassNotFoundException {
+    static Stub createRMIStub(RMIState state, Class<?> type) throws ClassNotFoundException {
         if (!type.isInterface()) {
             throw new RuntimeException("non-interfaces not supported");
         }
-        
-        logger.fine("Creating RMI stub for class " + type.getName()); 
 
-        Constructor cons = getRMIStubClassConstructor(state, type);
+        LOGGER.fine("Creating RMI stub for class " + type.getName());
+
+        Constructor<? extends Stub> cons = getRMIStubClassConstructor(state, type);
 
         try {
-            javax.rmi.CORBA.Stub result = (javax.rmi.CORBA.Stub) cons.newInstance(NO_ARG);
+            Stub result = cons.newInstance(NO_ARG);
             return result;
         } catch (InstantiationException ex) {
             throw new RuntimeException(
                     "internal problem: cannot instantiate stub", ex);
         } catch (InvocationTargetException ex) {
             throw new RuntimeException(
-                    "internal problem: cannot instantiate stub", ex);
+                    "internal problem: cannot instantiate stub", ex.getCause());
         } catch (IllegalAccessException ex) {
             throw new RuntimeException(
                     "internal problem: cannot instantiate stub", ex);
@@ -299,50 +279,49 @@
                     "writeReplace", new Class[0]);
 
         } catch (Throwable ex) {
-            logger.log(Level.WARNING, "cannot initialize: \n" + ex.getMessage(), ex);
+            LOGGER.log(Level.WARNING, "cannot initialize: \n" + ex.getMessage(), ex);
             throw new Error("cannot initialize", ex);
         }
     }
 
-    static synchronized Class getRMIStubClass(RMIState state, Class type)
-            throws ClassNotFoundException {
+    static synchronized Class<?> getRMIStubClass(RMIState state, Class<?> type) throws ClassNotFoundException {
         return getRMIStubClassConstructor(state, type).getDeclaringClass();
     }
 
-    static Constructor getRMIStubClassConstructor(RMIState state, Class type)
-            throws ClassNotFoundException {
-        logger.fine("Requesting stub constructor of class " + type.getName()); 
-        Constructor cons = (Constructor) state.stub_map.get(type);
+    static Constructor<? extends Stub> getRMIStubClassConstructor(RMIState state, Class<?> type) throws ClassNotFoundException {
+        LOGGER.fine("Requesting stub constructor of class " + type.getName());
+        @SuppressWarnings("unchecked")
+        Constructor<? extends Stub> cons = (Constructor<? extends Stub>) state.stub_map.get(type);
 
         if (cons != null) {
-            logger.fine("Returning cached constructor of class " + cons.getDeclaringClass().getName()); 
+            LOGGER.fine("Returning cached constructor of class " + cons.getDeclaringClass().getName());
             return cons;
         }
 
-        TypeRepository repository = state.getTypeRepository();
-        RemoteDescriptor desc = (RemoteDescriptor) repository.getRemoteDescriptor(type);
+        TypeRepository repository = state.repo;
+        RemoteDescriptor desc = (RemoteDescriptor) repository.getRemoteInterface(type);
 
         MethodDescriptor[] mdesc = desc.getMethods();
         MethodDescriptor[] descriptors = new MethodDescriptor[mdesc.length + 1];
         for (int i = 0; i < mdesc.length; i++) {
             descriptors[i] = mdesc[i];
         }
-        
-        logger.finer("TYPE ----> " + type);
-        logger.finer("LOADER --> " + UtilImpl.getClassLoader(type));
-        logger.finer("CONTEXT -> " + getClassLoader());
+
+        LOGGER.finer("TYPE ----> " + type);
+        LOGGER.finer("LOADER --> " + UtilImpl.getClassLoader(type));
+        LOGGER.finer("CONTEXT -> " + getClassLoader());
 
         MethodRef[] methods = new MethodRef[descriptors.length];
 
         for (int i = 0; i < mdesc.length; i++) {
             Method m = descriptors[i].getReflectedMethod();
-            logger.finer("Method ----> " + m);
+            LOGGER.finer("Method ----> " + m);
             methods[i] = new MethodRef(m);
         }
         methods[mdesc.length] = new MethodRef(stub_write_replace);
 
 
-        Class clazz = null;
+        Class<?> clazz = null;
 
         try {
             /* Construct class! */
@@ -405,10 +384,10 @@
 
         if (clazz != null) {
             try {
-                cons = clazz.getConstructor(new Class[0]);
+                cons = (Constructor<? extends Stub>) clazz.getConstructor();
                 state.stub_map.put(type, cons);
             } catch (NoSuchMethodException e) {
-                logger.log(Level.FINER, "constructed stub has no default constructor", e);
+                LOGGER.log(Level.FINER, "constructed stub has no default constructor", e);
             }
         }
 
@@ -446,45 +425,6 @@
         return poa_stub_invoke_method;
 
     }
-    
-
-    /*
-     * private ClassLoader last_loader = null; private Class last_remote_type =
-     * null; private String last_codebase = null; private Class last_stubclass =
-     * null;
-     *
-     * static javax.rmi.CORBA.Stub createStaticStub (RMIState state, String
-     * codebase, Class type) { String key = (codebase == null ? "null" :
-     * codebase) + "#" + type.getName();
-     *
-     * if (state.negative_stub_set.contains (key)) return null;
-     *
-     * ClassLoader loader = getClassLoader ();
-     *
-     * synchronized (this) { if (type == last_remote_type && codebase ==
-     * last_codebase && last_loader == loader) { try { return
-     * (javax.rmi.CORBA.Stub)last_stubclass.newInstance (); } catch
-     * (InstantiationException ex) { // ignore } catch (IllegalAccessException
-     * ex) { // ignore } } }
-     *
-     * String stubName = RemoteDescriptor.stubClassName (type);
-     *
-     * try { Class stub_class = javax.rmi.CORBA.Util.loadClass (stubName,
-     * codebase, loader);
-     *
-     * last_loader = loader; last_remote_type = type; last_codebase = codebase;
-     * last_stubclass = stub_class;
-     *
-     * return (javax.rmi.CORBA.Stub)stub_class.newInstance (); } catch
-     * (ClassNotFoundException ex) {
-     *  } catch (InstantiationException ex) { // ignore } catch
-     * (IllegalAccessException ex) { // ignore } catch (ClassCastException ex) { //
-     * ignore }
-     *
-     * state.negative_stub_set.add (key);
-     *
-     * return null; }
-     */
 
     public java.rmi.Remote toStub(java.rmi.Remote value)
             throws java.rmi.NoSuchObjectException {
@@ -493,14 +433,6 @@
 
         javax.rmi.CORBA.Tie tie = javax.rmi.CORBA.Util.getTie(value);
         if (tie == null) {
-
-            // Throwable trace =
-            // org.apache.yoko.rmi.api.PortableRemoteObjectExt.getStateTrace ();
-
-            // log.info("Instance of "+value.getClass()+" is not exported in
-            // "+RMIState.current().getName()+" tie="+tie+";
-            // "+(trace==null?"trace is null":""), trace);
-
             throw new java.rmi.NoSuchObjectException("object not exported");
         }
 
@@ -534,7 +466,7 @@
         RMIServant servant = new RMIServant(state);
         javax.rmi.CORBA.Util.registerTarget(servant, obj);
 
-        logger.finer("exporting instance of " + obj.getClass().getName()
+        LOGGER.finer("exporting instance of " + obj.getClass().getName()
                 + " in " + state.getName());
 
         try {
@@ -550,17 +482,17 @@
             throws java.rmi.NoSuchObjectException {
         javax.rmi.CORBA.Util.unexportObject(obj);
     }
-    
+
     // the factory object used for creating stub initializers
     static private StubInitializer initializer = null;
-    // the default stub handler, which is ours without overrides. 
-    private static final String defaultInitializer = "org.apache.yoko.rmi.impl.RMIStubInitializer"; 
-    
+    // the default stub handler, which is ours without overrides.
+    private static final String defaultInitializer = "org.apache.yoko.rmi.impl.RMIStubInitializer";
+
     /**
-     * Get the RMI stub handler initializer to use for RMI invocation 
-     * stubs.  The Class in question must implement the StubInitializer method. 
-     * 
-     * @return The class used to create StubHandler instances. 
+     * Get the RMI stub handler initializer to use for RMI invocation
+     * stubs.  The Class in question must implement the StubInitializer method.
+     *
+     * @return The class used to create StubHandler instances.
      */
     private static StubInitializer getRMIStubInitializer() {
         if (initializer == null) {
@@ -572,6 +504,6 @@
                     "Can not create RMIStubInitializer: " + factory).initCause(e);
             }
         }
-        return initializer; 
+        return initializer;
     }
 }
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 1518273..e18b395 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.type;
     }
 
     RMIState getRMIState() {
@@ -127,7 +127,7 @@
             try {
                 return m.invoke(_target, args);
             } catch (java.lang.reflect.InvocationTargetException ex) {
-                logger.log(Level.FINER, "Error invoking local method", ex);
+                logger.log(Level.FINER, "Error invoking local method", ex.getCause());
                 throw ex.getTargetException();
             }
         } else {
@@ -178,7 +178,7 @@
             throw new IllegalArgumentException();
         }
 
-        _descriptor = _state.getTypeRepository().getRemoteDescriptor(target.getClass()).getRemoteInterface();
+        _descriptor = _state.repo.getRemoteInterface(target.getClass()).getRemoteInterface();
 
         if (_descriptor == null) {
             throw new RuntimeException("remote classes not supported");
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIState.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIState.java
index 6238213..e6f2282 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIState.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIState.java
@@ -51,7 +51,7 @@
 
     private String _name;
 
-    private TypeRepository _typerepository;
+    final TypeRepository repo = TypeRepository.get();
     
     private POA poa;
     
@@ -59,13 +59,6 @@
 	return poa;
     }
 
-    TypeRepository getTypeRepository() {
-        if (_typerepository == null)
-            _typerepository = new TypeRepository(_orb);
-
-        return _typerepository;
-    }
-
     RMIState(org.omg.CORBA.ORB orb, String name) {
         if (orb == null) {
             throw new NullPointerException("ORB is null");
@@ -133,18 +126,6 @@
         return ref._get_delegate();
     }
 
-    ValueHandler valueHandler;
-
-    public ValueHandler createValueHandler() {
-        checkShutDown();
-
-        if (valueHandler == null) {
-            valueHandler = new ValueHandlerImpl(getTypeRepository());
-        }
-
-        return valueHandler;
-    }
-
     static RMIState current() {
         return (RMIState) PortableRemoteObjectExt.getState();
     }
@@ -190,8 +171,6 @@
     }
 
     void clearState() {
-        _typerepository = null;
-        valueHandler = null;
         stub_map = null;
         tie_map = null;
 
@@ -266,7 +245,7 @@
                     + ex.getMessage(), ex);
         } catch (InvocationTargetException ex) {
             logger.log(Level.FINE, "cannot instantiate stub class for " + type + " :: "
-                    + ex.getMessage(), ex);
+                    + ex.getCause(), ex.getCause());
         }
 
         return null;
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStub.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStub.java
index 2262332..98f61a0 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStub.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/RMIStub.java
@@ -19,6 +19,7 @@
 package org.apache.yoko.rmi.impl;
 
 import org.apache.yoko.rmi.api.PortableRemoteObjectExt;
+import org.omg.CORBA.SystemException;
 import org.omg.CORBA.portable.Delegate;
 import org.omg.CORBA.portable.ServantObject;
 
@@ -38,7 +39,7 @@
         Class remote_interface = getClass().getInterfaces()[0];
 
         RMIState state = (RMIState) PortableRemoteObjectExt.getState();
-        Object o = state.getTypeRepository().getRemoteDescriptor(
+        Object o = state.repo.getRemoteInterface(
                 remote_interface);
 
         _descriptor = (RemoteDescriptor) o;
@@ -62,7 +63,11 @@
 
     // apparently this implementation is expected!
     public String toString() {
-        return _orb().object_to_string(this);
+        try {
+            return _orb().object_to_string(this);
+        } catch (SystemException e) {
+            return super.toString() + " (unconnected)";
+        }
     }
 
     /**
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..231981c 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,24 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class RMIStubDescriptor extends ValueDescriptor {
+import java.io.IOException;
+
+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 = type.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)));
     }
 
     //
@@ -61,14 +43,15 @@
     // state is written. This ensures that fields in the proxy are
     // not included on the wire.
     //
+    @Override
     protected void writeValue(ObjectWriter writer, java.io.Serializable val)
-            throws java.io.IOException {
+            throws IOException {
         _super_descriptor.writeValue(writer, val);
     }
 
+    @Override
     protected void readValue(ObjectReader reader, java.io.Serializable value)
-            throws java.io.IOException {
+            throws IOException {
         _super_descriptor.readValue(reader, value);
     }
-
 }
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..07bb558 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.type;
     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..4eb3ea3 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,26 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class RemoteClassDescriptor extends RemoteDescriptor {
+final 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", type.getName().replace('.', '/'));
     }
 
     RemoteClassDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
 
-    public void init() {
-        super.init();
+    @Override
+    protected RemoteInterfaceDescriptor genRemoteInterface() {
+        Class[] remotes = collect_remote_interfaces(type);
+        if (remotes.length == 0) {
+            throw new RuntimeException(type.getName()
+                    + " has no remote interfaces");
+        }
+        Class most_specific_interface = remotes[0];
+
+        return repo.getDescriptor(most_specific_interface).getRemoteInterface();
     }
 }
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..1c8b726 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
@@ -18,9 +18,19 @@
 
 package org.apache.yoko.rmi.impl;
 
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+
+import java.io.IOException;
+import java.io.PrintWriter;
 import java.lang.reflect.Method;
+import java.rmi.Remote;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -34,7 +44,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;
@@ -45,32 +55,10 @@
 
     protected List super_descriptors;
 
-    public RemoteInterfaceDescriptor getRemoteInterface() {
-        RemoteInterfaceDescriptor result = super.getRemoteInterface();
-        if (result != null) { 
-            return result;
-        }
+    @Override
+    protected abstract RemoteInterfaceDescriptor genRemoteInterface();
 
-        if (this instanceof RemoteInterfaceDescriptor) {
-            result = (RemoteInterfaceDescriptor) this;
-        } else {
-            Class[] remotes = collect_remote_interfaces(getJavaClass());
-            if (remotes.length == 0) {
-                throw new RuntimeException(getJavaClass().getName()
-                        + " has no remote interfaces");
-            }
-            Class most_specific_interface = remotes[0];
-
-            result = (RemoteInterfaceDescriptor) repository
-                    .getDescriptor(most_specific_interface);
-        }
-
-        setRemoteInterface(result);
-
-        return result;
-    }
-
-    static final Class REMOTE_CLASS = java.rmi.Remote.class;
+    static final Class REMOTE_CLASS = Remote.class;
 
     static final Class OBJECT_CLASS = java.lang.Object.class;
 
@@ -80,11 +68,11 @@
 
     public String[] all_interfaces() {
         if (_ids == null) {
-            Class[] ifaces = collect_remote_interfaces(getJavaClass());
+            Class[] ifaces = collect_remote_interfaces(type);
             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();
             }
 
@@ -100,7 +88,7 @@
         }
 
         if (method_map == null) {
-            method_map = new java.util.HashMap();
+            method_map = new HashMap();
             for (int i = 0; i < operations.length; i++) {
                 method_map.put(operations[i].getIDLName(), operations[i]);
             }
@@ -111,7 +99,7 @@
 
     void debugMethodMap() {
         if (logger.isLoggable(Level.FINER)) {
-            logger.finer("METHOD MAP FOR " + getJavaClass().getName());
+            logger.finer("METHOD MAP FOR " + type.getName());
 
             Iterator it = method_map.keySet().iterator();
             while (it.hasNext()) {
@@ -128,7 +116,7 @@
         }
 
         if (refl_method_map == null) {
-            refl_method_map = new java.util.HashMap();
+            refl_method_map = new HashMap();
             for (int i = 0; i < operations.length; i++) {
                 refl_method_map.put(operations[i].getReflectedMethod(), operations[i]);
             }
@@ -141,9 +129,6 @@
         super(type, repository);
     }
 
-    public void init() {
-    }
-
     public MethodDescriptor[] getMethods() {
         if (operations == null) {
             init_methods();
@@ -169,7 +154,7 @@
         ArrayList method_list = new ArrayList();
 
         // first step is to build the helpers for any super classes
-        Class[] supers = getJavaClass().getInterfaces();
+        Class[] supers = type.getInterfaces();
         super_descriptors = new ArrayList();
 
         Map all_methods = new HashMap();
@@ -180,8 +165,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 +201,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());
@@ -239,10 +223,10 @@
         }
 
         // init method map...
-        method_map = new java.util.HashMap();
+        method_map = new 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 +255,7 @@
     Method[] getLocalMethods() {
         ArrayList result = new ArrayList();
 
-        addNonRemoteInterfaceMethods(getJavaClass(), result);
+        addNonRemoteInterfaceMethods(type, result);
 
         Method[] out = new Method[result.size()];
         result.toArray(out);
@@ -396,27 +380,26 @@
     }
 
     /** 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());
+    @Override
+    public Object read(InputStream in) {
+        return PortableRemoteObject.narrow(in.read_Object(),
+                type);
     }
 
     /** Write an instance of this value to a CDR stream */
-    public void write(org.omg.CORBA.portable.OutputStream out, Object val) {
+    @Override
+    public void write(OutputStream out, Object val) {
         javax.rmi.CORBA.Util.writeRemoteObject(out, val);
     }
 
-    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()
-                    .getName());
-        }
-
-        return _type_code;
+    @Override
+    protected final TypeCode genTypeCode() {
+        ORB orb = ORB.init();
+        return orb.create_interface_tc(getRepositoryID(), type.getName());
     }
 
-    void writeMarshalValue(java.io.PrintWriter pw, String outName,
+    @Override
+    void writeMarshalValue(PrintWriter pw, String outName,
             String paramName) {
         pw.print("javax.rmi.CORBA.Util.writeRemoteObject(");
         pw.print(outName);
@@ -425,16 +408,17 @@
         pw.print(')');
     }
 
-    void writeUnmarshalValue(java.io.PrintWriter pw, String inName) {
+    @Override
+    void writeUnmarshalValue(PrintWriter pw, String inName) {
         pw.print('(');
-        pw.print(getJavaClass().getName());
+        pw.print(type.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(type.getName());
         pw.print(".class)");
     }
 
@@ -473,9 +457,9 @@
         return pkgname + "._" + cplain + "_Stub";
     }
 
-    void writeStubClass(java.io.PrintWriter pw) {
+    void writeStubClass(PrintWriter pw) {
 
-        Class c = getJavaClass();
+        Class c = type;
         String cname = c.getName();
         String fullname = stubClassName(c);
         //String stubname = fullname.substring(fullname.lastIndexOf('.') + 1);
@@ -520,7 +504,7 @@
     }
 
     String getStubClassName() {
-        Class c = getJavaClass();
+        Class c = type;
         String cname = c.getName();
 
         String pkgname = null;
@@ -536,23 +520,23 @@
         return pkgname + "." + "_" + cplain + "_Stub";
     }
 
+    @Override
     void addDependencies(Set classes) {
-        Class c = getJavaClass();
+        Class c = type;
 
-        if (c == java.rmi.Remote.class || classes.contains(c))
+        if (c == Remote.class || classes.contains(c))
             return;
 
         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);
         }
 
@@ -562,6 +546,7 @@
         }
     }
 
+    @Override
     boolean copyInStub() {
         return false;
     }
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..c75478a 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,13 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class RemoteInterfaceDescriptor extends RemoteDescriptor {
+final class RemoteInterfaceDescriptor extends RemoteDescriptor {
     RemoteInterfaceDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
 
-    public void init() {
-        super.init();
+    @Override
+    protected RemoteInterfaceDescriptor genRemoteInterface() {
+        return this;
     }
-
 }
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..fe3df2c 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,35 +18,51 @@
 
 package org.apache.yoko.rmi.impl;
 
-public abstract class SimpleDescriptor extends TypeDescriptor {
-    SimpleDescriptor(Class type, TypeRepository repository, String idl_name,
-            org.omg.CORBA.TCKind tc) {
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.TCKind;
+import org.omg.CORBA.TypeCode;
+
+abstract class SimpleDescriptor extends TypeDescriptor {
+    private final String idl_name;
+    private final TCKind tc;
+    SimpleDescriptor(Class type, TypeRepository repository, String idl_name, 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("");
-
-        org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
-        _type_code = orb.get_primitive_tc(tc);
+        this.idl_name = idl_name;
+        this.tc = tc;
     }
 
-    org.omg.CORBA.TypeCode getTypeCode() {
-        return _type_code;
+    @Override
+    protected final String genIDLName() {
+        return idl_name;
     }
 
+    @Override
+    protected final String genPackageName() {
+        return "";
+    }
+
+    @Override
+    protected final String genTypeName() {
+        return idl_name;
+    }
+
+    @Override
+    protected final TypeCode genTypeCode() {
+        return ORB.init().get_primitive_tc(tc);
+    }
+
+    @Override
     boolean copyInStub() {
         return false;
     }
 
+    @Override
     public boolean copyBetweenStates() {
         return false;
     }
 
+    @Override
     public boolean copyWithinState() {
         return false;
     }
-
 }
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..f459794 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,47 +18,57 @@
 
 package org.apache.yoko.rmi.impl;
 
-public class StringDescriptor extends ValueDescriptor {
-    public String getIDLName() {
-        return "CORBA_WStringValue";
-    }
-    
+import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.WStringValueHelper;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+
+import java.io.Serializable;
+
+class StringDescriptor extends ValueDescriptor {
     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 final String genIDLName() {
+        return "CORBA_WStringValue";
+    }
+
+    @Override
+    protected String genPackageName() {
+        return "CORBA";
+    }
+
+    @Override
+    protected String genTypeName() {
+        return "WStringValue";
     }
 
     /** Read an instance of this value from a CDR stream */
-    public Object read(org.omg.CORBA.portable.InputStream in) {
-        return org.omg.CORBA.WStringValueHelper.read(in);
+    @Override
+    public Object read(InputStream in) {
+        return WStringValueHelper.read(in);
     }
 
     /** Write an instance of this value to a CDR stream */
-    public void write(org.omg.CORBA.portable.OutputStream out, Object value) {
-        org.omg.CORBA.WStringValueHelper.write(out, (String) value);
+    @Override
+    public void write(OutputStream out, Object value) {
+        WStringValueHelper.write(out, (String) value);
     }
 
-    public void writeValue(org.omg.CORBA.portable.OutputStream out,
-            java.io.Serializable value) {
-        throw new org.omg.CORBA.MARSHAL("internal error");
+    @Override
+    public void writeValue(OutputStream out, Serializable value) {
+        throw new MARSHAL("internal error");
     }
 
-    public java.io.Serializable readValue(
-            org.omg.CORBA.portable.InputStream in, java.io.Serializable value,
-            java.util.Map offsetMap) {
-        throw new org.omg.CORBA.MARSHAL("internal error");
+    @Override
+    protected final TypeCode genTypeCode() {
+        return WStringValueHelper.type();
     }
 
-    org.omg.CORBA.TypeCode getTypeCode() {
-        return org.omg.CORBA.WStringValueHelper.type();
-    }
-
+    @Override
     Object copyObject(Object value, CopyState state) {
         return value;
     }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StubBuilder.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StubBuilder.java
index ad85fcc..8fc509d 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StubBuilder.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/impl/StubBuilder.java
@@ -45,7 +45,7 @@
         Set pending = new HashSet();
         ArrayList result = new ArrayList();
 
-        TypeRepository rep = new TypeRepository(null);
+        TypeRepository rep = TypeRepository.get();
         Iterator it = interfaces.iterator();
         while (it.hasNext()) {
             Class cl = (Class) it.next();
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 6c4126e..aea1298 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
@@ -18,107 +18,148 @@
 
 package org.apache.yoko.rmi.impl;
 
-import java.io.IOException;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
+import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+
+import java.io.PrintWriter;
+import java.rmi.Remote;
 import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
 import java.util.logging.Logger;
 
-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 Class _java_class;
+    final Class type;
 
-    protected String _repid;
+    private volatile String _repid = null;
 
-    protected RemoteInterfaceDescriptor remoteDescriptor;
+    private volatile String packageName = null;    // the package name qualifier (if any)
+    protected String genPackageName() {
+        int idx = java_name.lastIndexOf('.');
+        return ((idx < 0) ? "" : java_name.substring(0, idx));
+    }
+    public final String getPackageName() {
+        if (null == packageName) packageName = genPackageName();
+        return packageName;
+    }
 
-    public Class getJavaClass() {
-        return _java_class;
+    private volatile String typeName = null;       // the simple type name (minus package, if any)
+    protected String genTypeName() {
+        int idx = java_name.lastIndexOf('.');
+        return ((idx < 0) ? java_name : java_name.substring(idx + 1));
+    }
+    public final String getTypeName() {
+        if (null == typeName) typeName = genTypeName();
+        return typeName;
+    }
+
+    private volatile FullKey key = null;
+    private FullKey genKey() {
+        return new FullKey(getRepositoryID(), type);
+    }
+    public final FullKey getKey() {
+        if (null == key) key = genKey();
+        return key;
+    }
+
+    public static class SimpleKey {
+        private final String repid;
+
+        public SimpleKey(String repid) {
+            this.repid = repid;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((repid == null) ? 0 : repid.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null) return false;
+            if (!(obj instanceof SimpleKey)) return false;
+            return Objects.equals(repid, ((SimpleKey)obj).repid);
+        }
+    }
+
+    public static final class FullKey extends SimpleKey {
+        private final Class<?> localType;
+
+        public FullKey(String repid, Class<?> localType) {
+            super(repid);
+            this.localType = localType;
+        }
+
+        @Override
+        public int hashCode() {
+            // must just be the same as SimpleKey's hashCode
+            return super.hashCode();
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) return true;
+            if (obj == null) return false;
+            if (!(obj instanceof SimpleKey)) return false;
+            if (obj instanceof FullKey &&
+                    !!!Objects.equals(localType, ((FullKey)obj).localType)) return false;
+            return super.equals(obj);
+        }
+    }
+
+    @Override
+    public String toString() {
+        return String.format("%s{class=\"%s\",repId=\"%s\"}",
+                this.getClass().getName(), type,
+                getRepositoryID());
     }
 
     protected TypeDescriptor(Class type, TypeRepository repository) {
-        _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); 
-        }
+        super(repository, type.getName());
+        this.type = type;
     }
 
-    public String getRepositoryIDForArray() {
-        return getRepositoryID();
+    @Override
+    protected String genIDLName() {
+        return java_name.replace('.', '_');
     }
 
-    public String getRepositoryID() {
-        if (_repid == null)
-            _repid = "RMI:" + getJavaClass().getName() + ":0000000000000000";
-
+    protected String genRepId() {
+        return String.format("RMI:%s:%016X", type.getName(), 0);
+    }
+    public final String getRepositoryID() {
+        if (_repid == null) _repid = genRepId();
         return _repid;
     }
 
-    RemoteInterfaceDescriptor getRemoteInterface() {
-        return remoteDescriptor;
+    private volatile RemoteInterfaceDescriptor remoteInterface = null;
+    protected RemoteInterfaceDescriptor genRemoteInterface() {
+        throw new UnsupportedOperationException("class " + type + " does not implement " + Remote.class.getName());
+    }
+    final RemoteInterfaceDescriptor getRemoteInterface() {
+        if (null == remoteInterface) remoteInterface = genRemoteInterface();
+        return remoteInterface;
     }
 
-    void setRemoteInterface(RemoteInterfaceDescriptor desc) {
-        remoteDescriptor = desc;
-    }
+
 
     /** Read an instance of this value from a CDR stream */
-    public abstract Object read(org.omg.CORBA.portable.InputStream in);
+    public abstract Object read(InputStream in);
 
     /** Write an instance of this value to a CDR stream */
-    public abstract void write(org.omg.CORBA.portable.OutputStream out,
-            Object val);
-
-    public void init() {
-    }
+    public abstract void write(OutputStream out, Object val);
 
     public boolean isCustomMarshalled() {
         return false;
     }
 
-    static class WrappedIOException extends RuntimeException {
-        IOException wrapped;
-
-        WrappedIOException(IOException ex) {
-            super("wrapped IO exception");
-            this.wrapped = ex;
-        }
-    }
-
-    CorbaObjectReader makeCorbaObjectReader(final InputStream in,
-            final Map offsetMap, final java.io.Serializable obj)
-            throws IOException {
-        try {
-            return (CorbaObjectReader) AccessController
-                    .doPrivileged(new PrivilegedAction() {
-                        public Object run() {
-                            try {
-                                return new CorbaObjectReader(in, offsetMap, obj);
-                            } catch (IOException ex) {
-                                throw new WrappedIOException(ex);
-                            }
-                        }
-                    });
-        } catch (WrappedIOException ex) {
-            throw ex.wrapped;
-        }
-    }
-
     String makeSignature(Class type) {
         if (type.isPrimitive()) {
 
@@ -165,15 +206,30 @@
         return 0L;
     }
 
-    protected org.omg.CORBA.TypeCode _type_code = null;
+    @Override
+    protected void init() {
+        getTypeCode();
+    }
 
-    abstract org.omg.CORBA.TypeCode getTypeCode();
+    private volatile TypeCode typeCode = null;
+    protected abstract TypeCode genTypeCode();
+    final TypeCode getTypeCode() {
+        if (null == typeCode) {
+            synchronized (repo) {
+                if (null == typeCode) typeCode = genTypeCode();
+            }
+        }
+        return typeCode;
+    }
+    protected final void setTypeCode(TypeCode tc) {
+        typeCode = tc;
+    }
 
     Object copyObject(Object value, CopyState state) {
         throw new InternalError("cannot copy " + value.getClass().getName());
     }
 
-    void writeMarshalValue(java.io.PrintWriter pw, String outName,
+    void writeMarshalValue(PrintWriter pw, String outName,
             String paramName) {
         pw.print(outName);
         pw.print('.');
@@ -184,7 +240,7 @@
         pw.print(')');
     }
 
-    void writeUnmarshalValue(java.io.PrintWriter pw, String inName) {
+    void writeUnmarshalValue(PrintWriter pw, String inName) {
         pw.print(inName);
         pw.print('.');
         pw.print("read_");
@@ -193,7 +249,7 @@
         pw.print(')');
     }
 
-    void addDependencies(java.util.Set classes) {
+    void addDependencies(Set<Class<?>> classes) {
         return;
     }
 
@@ -201,7 +257,7 @@
         return true;
     }
 
-    void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    void print(PrintWriter pw, Map<Object,Integer> recurse, Object val) {
         if (val == null) {
             pw.print("null");
         }
@@ -211,15 +267,11 @@
             pw.print("^" + old);
         } else {
             Integer key = new Integer(System.identityHashCode(val));
-            pw.println(getJavaClass().getName() + "@"
+            pw.println(type.getName() + "@"
                     + Integer.toHexString(key.intValue()));
         }
     }
 
-    synchronized TypeDescriptor getSelf() {
-        return this;
-    }
-
     /**
      * Method copyBetweenStates.
      * 
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 0ca87c3..e7fc362 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
@@ -1,30 +1,46 @@
 /**
-*
-* 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.
-*/
+ *
+ * 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.Externalizable;
+import java.io.Serializable;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Method;
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.sql.Date;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.logging.Logger;
+import java.util.concurrent.ConcurrentMap;
 import java.util.logging.Level;
+import java.util.logging.Logger;
 
-import org.apache.yoko.rmi.util.ByteBuffer;
-import org.apache.yoko.rmi.util.ByteString;
+import javax.rmi.CORBA.ClassDesc;
+
+import org.apache.yoko.rmi.util.SearchKey;
+import org.apache.yoko.rmi.util.WeakKey;
 import org.omg.CORBA.MARSHAL;
 import org.omg.CORBA.ValueDefPackage.FullValueDescription;
 import org.omg.CORBA.portable.IDLEntity;
@@ -32,256 +48,247 @@
 import org.omg.SendingContext.CodeBaseHelper;
 import org.omg.SendingContext.RunTime;
 
+import org.apache.yoko.rmi.impl.TypeDescriptor.FullKey;
+import org.apache.yoko.rmi.impl.TypeDescriptor.SimpleKey;
 
 public class TypeRepository {
-    static final Logger logger = Logger.getLogger(TypeRepository.class
-            .getName());
+    static final Logger logger = Logger.getLogger(TypeRepository.class.getName());
 
-    org.omg.CORBA.ORB orb;
+    private static final class TypeDescriptorCache {
+        private final ConcurrentMap<WeakKey<FullKey>, WeakReference<TypeDescriptor>> map =
+                new ConcurrentHashMap<>();
+        private final ReferenceQueue<FullKey> staleKeys = new ReferenceQueue<>();
 
-    java.util.Map<Class, TypeDescriptor> classMap = new ConcurrentHashMap<Class, TypeDescriptor> ();
+        public TypeDescriptor get(String repid) {
+            cleanStaleKeys();
+            WeakReference<TypeDescriptor> ref =
+                    map.get(new SearchKey<SimpleKey>(new SimpleKey(repid)));
+            return (null == ref) ? null : ref.get();
+        }
 
-    java.util.Map<String, TypeDescriptor> repidMap = new ConcurrentHashMap<String, TypeDescriptor>();
+        public TypeDescriptor get(String repid, Class<?> localType) {
+            cleanStaleKeys();
+            WeakReference<TypeDescriptor> ref =
+                    map.get(new SearchKey<FullKey>(new FullKey(repid, localType)));
+            return (null == ref) ? null : ref.get();
+        }
 
-    public TypeRepository(org.omg.CORBA.ORB orb) {
-        this.orb = orb;
-        TypeDescriptor desc;
+        public void put(TypeDescriptor typeDesc) {
+            cleanStaleKeys();
+            final WeakReference<TypeDescriptor> value = new WeakReference<>(typeDesc);
+            map.putIfAbsent(new WeakKey<FullKey>(typeDesc.getKey(), staleKeys), value);
+        }
 
-        desc = new AnyDescriptor(java.lang.Object.class, this);
-        classMap.put(java.lang.Object.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
-
-        desc = new AnyDescriptor(java.lang.Object.class, this);
-        classMap.put(java.lang.Object.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
-
-        desc = new StringDescriptor(this);
-        classMap.put(String.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
-
-        desc = new ClassDescriptor(this);
-        classMap.put(Class.class, desc);
-        classMap.put(javax.rmi.CORBA.ClassDesc.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
-
-        desc = new DateValueDescriptor(this);
-        classMap.put(java.util.Date.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
-
-        desc = new AnyDescriptor(java.io.Externalizable.class, this);
-        classMap.put(java.io.Externalizable.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
-
-        desc = new AnyDescriptor(java.io.Serializable.class, this);
-        classMap.put(java.io.Serializable.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
-
-        desc = new AnyDescriptor(java.rmi.Remote.class, this);
-        classMap.put(java.rmi.Remote.class, desc);
-        desc.init();
-        repidMap.put(desc.getRepositoryID(), desc);
+        private void cleanStaleKeys() {
+            for (Reference<? extends Object> staleKey = staleKeys.poll(); staleKey != null; staleKey = staleKeys.poll()) {
+                map.remove(staleKey);
+            }
+        }
     }
 
-    org.omg.CORBA.ORB getORB() {
-        return orb;
+    private static final class LocalDescriptors extends ClassValue<TypeDescriptor> {
+        private static final class Raw extends ClassValue<TypeDescriptor> {
+            private static final List<Class<?>> staticAnyTypes =
+                    Collections.unmodifiableList(
+                            Arrays.asList(Object.class, Externalizable.class, Serializable.class, Remote.class));
+
+            private final TypeRepository repo;
+
+            Raw(TypeRepository repo) {
+                this.repo = repo;
+            }
+
+            @Override
+            protected TypeDescriptor computeValue(Class<?> type) {
+                if (type.isPrimitive()) {
+                    return primitiveDescriptor(type);
+                } else if (type == String.class) {
+                    return new StringDescriptor(repo);
+                } else if (type == Class.class) {
+                    return new ClassDescriptor(repo);
+                } else if (type == ClassDesc.class) {
+                    return new ClassDescDescriptor(repo);
+                } else if (type == java.util.Date.class) {
+                    return new DateValueDescriptor(repo);
+                } else if (staticAnyTypes.contains(type)) {
+                    return new AnyDescriptor(type, repo);
+                } else if ((IDLEntity.class.isAssignableFrom(type)) && isIDLEntity(type)) {
+                    return new IDLEntityDescriptor(type, repo);
+                } else if (Throwable.class.isAssignableFrom(type)) {
+                    return new ExceptionDescriptor(type, repo);
+                } 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 (Remote.class.isAssignableFrom(type)) {
+                    if (type.isInterface()) {
+                        return new RemoteInterfaceDescriptor(type, repo);
+                    } else {
+                        return new RemoteClassDescriptor(type, repo);
+                    }
+                } else if (!type.isInterface()
+                && Serializable.class.isAssignableFrom(type)) {
+                    return new ValueDescriptor(type, repo);
+                } else if (Object.class.isAssignableFrom(type)) {
+                    if (isAbstractInterface(type)) {
+                        logger.finer("encoding " + type + " as abstract interface");
+                        return new AbstractObjectDescriptor(type, repo);
+                    } else {
+                        logger.finer("encoding " + type + " as a abstract value");
+                        return new ValueDescriptor(type, repo);
+                    }
+                } else {
+                    throw new RuntimeException("cannot handle class " + type.getName());
+                }
+            }
+
+            private TypeDescriptor primitiveDescriptor(Class<?> type) {
+                if (type == Boolean.TYPE) {
+                    return new BooleanDescriptor(repo);
+                } else if (type == Byte.TYPE) {
+                    return new ByteDescriptor(repo);
+                } else if (type == Short.TYPE) {
+                    return new ShortDescriptor(repo);
+                } else if (type == Character.TYPE) {
+                    return new CharDescriptor(repo);
+                } else if (type == Integer.TYPE) {
+                    return new IntegerDescriptor(repo);
+                } else if (type == Long.TYPE) {
+                    return new LongDescriptor(repo);
+                } else if (type == Float.TYPE) {
+                    return new FloatDescriptor(repo);
+                } else if (type == Double.TYPE) {
+                    return new DoubleDescriptor(repo);
+                } else if (type == Void.TYPE) {
+                    return new VoidDescriptor(repo);
+                } else {
+                    throw new RuntimeException("internal error: " + type);
+                }
+            }
+
+            private static boolean isIDLEntity(Class<?> type) {
+                for (Class<?> intf : type.getInterfaces()) {
+                    if (intf.equals(IDLEntity.class))
+                        return true;
+                }
+                return false;
+            }
+
+            private static boolean isAbstractInterface(Class<?> type) {
+                if (!type.isInterface())
+                    return false;
+
+                for (Class<?> intf : type.getInterfaces()) {
+                    if (!isAbstractInterface(intf))
+                        return false;
+                }
+
+                for (Method method : type.getDeclaredMethods()) {
+                    if (!isRemoteMethod(method))
+                        return false;
+                }
+
+                return true;
+            }
+
+            private static boolean isRemoteMethod(java.lang.reflect.Method m) {
+                for (Class<?> exceptionType : m.getExceptionTypes()) {
+                    if (exceptionType.isAssignableFrom(RemoteException.class))
+                        return true;
+                }
+
+                return false;
+            }
+
+        }
+
+        private final Raw rawValues;
+        private final TypeDescriptorCache repIdDescriptors;
+
+        LocalDescriptors(TypeRepository repo, TypeDescriptorCache repIdDescriptors) {
+            rawValues = new Raw(repo);
+            this.repIdDescriptors = repIdDescriptors;
+        }
+        @Override
+        protected TypeDescriptor computeValue(Class<?> type) {
+            final TypeDescriptor desc = rawValues.get(type);
+            desc.init();
+            repIdDescriptors.put(desc);
+            return desc;
+        }
+
     }
 
-    public String getRepositoryID(Class type) {
+    private static final class FvdRepIdDescriptorMaps extends ClassValue<ConcurrentMap<String,ValueDescriptor>> {
+
+        @Override
+        protected ConcurrentMap<String,ValueDescriptor> computeValue(
+                Class<?> type) {
+            return new ConcurrentHashMap<String,ValueDescriptor>(1);
+        }
+    }
+
+    private final TypeDescriptorCache repIdDescriptors;
+    private final LocalDescriptors localDescriptors;
+    private final FvdRepIdDescriptorMaps fvdDescMaps = new FvdRepIdDescriptorMaps();
+    private final ConcurrentMap<String,ValueDescriptor> noTypeDescMap = new ConcurrentHashMap<String,ValueDescriptor>();
+
+    private static final Set<Class<?>> initTypes;
+
+    static {
+        initTypes = createClassSet(Object.class, String.class, ClassDesc.class, Date.class,
+                Externalizable.class, Serializable.class, Remote.class);
+    }
+
+    private static Set<Class<?>> createClassSet(Class<?>...types) {
+        return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(types)));
+    }
+
+    private TypeRepository() {
+        repIdDescriptors = new TypeDescriptorCache();
+        localDescriptors = new LocalDescriptors(this, repIdDescriptors);
+
+        for (Class<?> type: initTypes) {
+            localDescriptors.get(type);
+        }
+    }
+
+    private static enum RepoHolder {
+        ;
+        static final TypeRepository value = new TypeRepository();
+    }
+
+    public static TypeRepository get() {
+        return RepoHolder.value;
+    }
+
+    public String getRepositoryID(Class<?> type) {
         return getDescriptor(type).getRepositoryID();
     }
 
-    public RemoteInterfaceDescriptor getRemoteDescriptor(Class type) {
-        TypeDescriptor td = getDescriptor(type);
-        RemoteInterfaceDescriptor result = td.getRemoteInterface();
-
-        if (result != null) {
-            return result;
-        }
-
-        RemoteDescriptor desc;
-
-        if (java.rmi.Remote.class.isAssignableFrom(type)) {
-            if (type.isInterface()) {
-                desc = new RemoteInterfaceDescriptor(type, this);
-            } else {
-                desc = new RemoteClassDescriptor(type, this);
-            }
-
-            desc.init();
-        } else {
-            throw new IllegalArgumentException("class " + type.toString()
-                    + " does not implement" + " java.rmi.Remote");
-        }
-
-        result = desc.getRemoteInterface();
-        td.setRemoteInterface(result);
-
-        return result;
+    public RemoteInterfaceDescriptor getRemoteInterface(Class<?> type) {
+        return getDescriptor(type).getRemoteInterface();
     }
 
-    public TypeDescriptor getDescriptor(Class type) {
-        logger.fine("Requesting type descriptor for class " + type.getName());
-        TypeDescriptor desc = classMap.get(type);
-
-        if (desc != null) {
-            return desc.getSelf();
-        }
-
-        if (org.omg.CORBA.portable.IDLEntity.class.isAssignableFrom(type)
-                && isIDLEntity(type)) {
-            IDLEntityDescriptor idlDesc = new IDLEntityDescriptor(type, this);
-            desc = idlDesc;
-            classMap.put(type, desc);
-            idlDesc.initIDL();
-        } else if (java.lang.Throwable.class.isAssignableFrom(type)) {
-            desc = new ExceptionDescriptor(type, this);
-            classMap.put(type, desc);
-            desc.init();
-            repidMap.put(desc.getRepositoryID(), desc);
-
-        } else if (type.isArray()) {
-            desc = ArrayDescriptor.get(type, this);
-            classMap.put(type, desc);
-            desc.init();
-            repidMap.put(desc.getRepositoryID(), desc);
-        } else if (!type.isInterface()
-                && java.io.Serializable.class.isAssignableFrom(type)) {
-            desc = new ValueDescriptor(type, this);
-            classMap.put(type, desc);
-            desc.init();
-            repidMap.put(desc.getRepositoryID(), desc);
-        } else if (java.rmi.Remote.class.isAssignableFrom(type)) {
-            if (type.isInterface()) {
-                desc = new RemoteInterfaceDescriptor(type, this);
-            } else {
-                desc = new RemoteClassDescriptor(type, this);
-            }
-
-            classMap.put(type, desc);
-            desc.init();
-            repidMap.put(desc.getRepositoryID(), desc);
-        } else if (type.isPrimitive()) {
-            desc = getSimpleDescriptor(type);
-            classMap.put(type, desc);
-            repidMap.put(desc.getRepositoryID(), desc);
-
-        } else if (Object.class.isAssignableFrom(type)) {
-            if (isAbstractInterface(type)) {
-
-                logger.finer("encoding " + type + " as abstract interface");
-                desc = new AbstractObjectDescriptor(type, this);
-
-            } else {
-
-                logger.finer("encoding " + type + " as a abstract value");
-                desc = new ValueDescriptor(type, this);
-            }
-
-            classMap.put(type, desc);
-            desc.init();
-            repidMap.put(desc.getRepositoryID(), desc);
-
-        } else {
-            throw new RuntimeException("cannot handle class " + type.getName());
-        }
-
-        logger.fine("Class " + type.getName() + " resolves to " + desc.getClass().getName());
+    public TypeDescriptor getDescriptor(Class<?> type) {
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Requesting type descriptor for class \"%s\"", type.getName()));
+        final TypeDescriptor desc = localDescriptors.get(type);
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Class \"%s\" resolves to %s", type.getName(), desc));
         return desc;
     }
 
-    private boolean isIDLEntity(Class type) {
-        Class[] supers = type.getInterfaces();
-
-        for (int i = 0; supers != null && i < supers.length; i++) {
-            if (supers[i].equals(IDLEntity.class)) {
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    SimpleDescriptor getSimpleDescriptor(Class type) {
-        if (type == Boolean.TYPE) {
-            return boolean_descriptor;
-        } else if (type == Byte.TYPE) {
-            return byte_descriptor;
-        } else if (type == Short.TYPE) {
-            return short_descriptor;
-        } else if (type == Character.TYPE) {
-            return char_descriptor;
-        } else if (type == Integer.TYPE) {
-            return int_descriptor;
-        } else if (type == Long.TYPE) {
-            return long_descriptor;
-        } else if (type == Float.TYPE) {
-            return float_descriptor;
-        } else if (type == Double.TYPE) {
-            return double_descriptor;
-        } else if (type == Void.TYPE) {
-            return void_descriptor;
-        } else if (!type.isPrimitive()) {
-            throw new IllegalArgumentException("Cannot resolve simple descriptor for primitive types");
-        } else {
-            throw new RuntimeException("internal error: " + type);
-        }
-    }
-
-    SimpleDescriptor boolean_descriptor = new BooleanDescriptor(this);
-
-    SimpleDescriptor byte_descriptor = new ByteDescriptor(this);
-
-    SimpleDescriptor char_descriptor = new CharDescriptor(this);
-
-    SimpleDescriptor short_descriptor = new ShortDescriptor(this);
-
-    SimpleDescriptor int_descriptor = new IntegerDescriptor(this);
-
-    SimpleDescriptor long_descriptor = new LongDescriptor(this);
-
-    SimpleDescriptor float_descriptor = new FloatDescriptor(this);
-
-    SimpleDescriptor double_descriptor = new DoubleDescriptor(this);
-
-    SimpleDescriptor void_descriptor = new VoidDescriptor(this);
-
-    static final java.lang.Class REMOTE_EXCEPTION = java.rmi.RemoteException.class;
-
-    boolean isAbstractInterface(Class type) {
-        if (!type.isInterface())
-            return false;
-
-        Class[] interfaces = type.getInterfaces();
-        for (Class anInterface : interfaces) {
-            if (!isAbstractInterface(anInterface))
-                return false;
-        }
-
-        java.lang.reflect.Method[] methods = type.getDeclaredMethods();
-        for (Method method : methods) {
-            if (!isRemoteMethod(method))
-                return false;
-        }
-
-        return true;
-    }
-
-    boolean isRemoteMethod(java.lang.reflect.Method m) {
-        Class[] ex = m.getExceptionTypes();
-
-        for (Class anEx : ex) {
-            if (anEx.isAssignableFrom(REMOTE_EXCEPTION))
-                return true;
-        }
-
-        return false;
+    public TypeDescriptor getDescriptor(String repId) {
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("Requesting type descriptor for repId \"%s\"", repId));
+        final TypeDescriptor desc = repIdDescriptors.get(repId);
+        if (logger.isLoggable(Level.FINE))
+            logger.fine(String.format("RepId \"%s\" resolves to %s", repId, desc));
+        return desc;
     }
 
     /**
@@ -291,27 +298,23 @@
      * @return ValueDescriptor
      * @throws ClassNotFoundException  something might go wrong.
      */
-    public ValueDescriptor getDescriptor(Class clz, String repid,
+    public ValueDescriptor getDescriptor(Class<?> clz, String repid,
             RunTime runtime) throws ClassNotFoundException {
         if (repid == null) {
             return (ValueDescriptor) getDescriptor(clz);
         }
 
-        ValueDescriptor clzdesc = (ValueDescriptor) repidMap.get(repid);
+        ValueDescriptor clzdesc = (ValueDescriptor) repIdDescriptors.get(repid, clz);
         if (clzdesc != null) {
             return clzdesc;
         }
 
         if (clz != null) {
-            logger.fine("Requesting type descriptor for class " + clz.getName() + " with repid " + repid); 
+            logger.fine("Requesting type descriptor for class " + clz.getName() + " with repid " + repid);
             // special handling for array value types.
             if (clz.isArray()) {
                 //TODO don't we need to look up the FVD for the array element?
-                ValueDescriptor desc = ArrayDescriptor.get(clz, this);
-                classMap.put(clz, desc);
-                desc.init();
-                repidMap.put(desc.getRepositoryID(), desc);
-                return desc;
+                return (ValueDescriptor) localDescriptors.get(clz);
             }
             clzdesc = (ValueDescriptor) getDescriptor(clz);
             String localID = clzdesc.getRepositoryID();
@@ -326,7 +329,7 @@
             // and padding and these can't be reliably identified without this remote info.  cf YOKO-434.
         }
 
-        logger.fine("Requesting type descriptor for repid " + repid); 
+        logger.fine("Requesting type descriptor for repid " + repid);
         CodeBase codebase = CodeBaseHelper.narrow(runtime);
         if (codebase == null) {
             throw new MARSHAL("cannot locate RunTime CodeBase");
@@ -340,139 +343,21 @@
                     codebase);
         }
 
-        clzdesc = new FVDValueDescriptor(fvd, clz, this, repid, super_desc);
-        repidMap.put(repid, clzdesc);
+        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) {
+            clzdesc = newDesc;
+            repIdDescriptors.put(clzdesc);
+        }
 
         return clzdesc;
     }
-
-    public static String idToClass(String repid) {
-        // debug
-        logger.finer("idToClass " + repid);
-
-        if (repid.startsWith("IDL:")) {
-
-            ByteString id = new ByteString(repid);
-
-            try {
-                int end = id.lastIndexOf(':');
-                ByteString s = end < 0 ? id.substring(4) : id.substring(4, end);
-
-                ByteBuffer bb = new ByteBuffer();
-
-                //
-                // reverse order of dot-separated name components up
-                // till the first slash.
-                //
-                int firstSlash = s.indexOf('/');
-                if (firstSlash > 0) {
-                    ByteString prefix = s.substring(0, firstSlash);
-                    ByteString[] elems = prefix.split('.');
-
-                    for (int i = elems.length - 1; i >= 0; i--) {
-                        bb.append(fixName(elems[i]));
-                        bb.append('.');
-                    }
-
-                    s = s.substring(firstSlash + 1);
-                }
-
-                //
-                // Append slash-separated name components ...
-                //
-                ByteString[] elems = s.split('/');
-                for (int i = 0; i < elems.length; i++) {
-                    bb.append(fixName(elems[i]));
-                    if (i != elems.length - 1)
-                        bb.append('.');
-                }
-
-                String result = bb.toString();
-
-                logger.finer("idToClassName " + repid + " => " + result);
-
-                return result;
-            } catch (IndexOutOfBoundsException ex) {
-                logger.log(Level.FINE, "idToClass " + ex.getMessage(), ex);
-                return null;
-            }
-
-        } else if (repid.startsWith("RMI:")) {
-            int end = repid.indexOf(':', 4);
-            return end < 0 ? repid.substring(4) : repid.substring(4, end);
-        }
-
-        return null;
-    }
-
-    static String fixName(String name) {
-        return (new ByteString(name)).toString();
-    }
-
-    static ByteString fixName(ByteString name) {
-        if (keyWords.contains(name)) {
-            ByteBuffer buf = new ByteBuffer();
-            buf.append('_');
-            buf.append(name);
-            return buf.toByteString();
-        }
-
-        ByteString result = name;
-        ByteString current = name;
-
-        boolean match = true;
-        while (match) {
-
-            int len = current.length();
-            match = false;
-
-            for (ByteString reservedPostfixe : reservedPostfixes) {
-                if (current.endsWith(reservedPostfixe)) {
-                    ByteBuffer buf = new ByteBuffer();
-                    buf.append('_');
-                    buf.append(result);
-                    result = buf.toByteString();
-
-                    int resultLen = reservedPostfixe.length();
-                    if (len > resultLen)
-                        current = current.substring(0, len - resultLen);
-                    else
-                        current = new ByteString("");
-
-                    match = true;
-                    break;
-                }
-            }
-
-        }
-
-        return name;
-    }
-
-    static final java.util.Set<ByteString> keyWords = new java.util.HashSet<ByteString>();
-
-    static final ByteString[] reservedPostfixes = new ByteString[] {
-            new ByteString("Helper"), new ByteString("Holder"),
-            new ByteString("Operations"), new ByteString("POA"),
-            new ByteString("POATie"), new ByteString("Package"),
-            new ByteString("ValueFactory") };
-
-    static {
-        String[] words = { "abstract", "boolean", "break", "byte", "case",
-                "catch", "char", "class", "clone", "const", "continue",
-                "default", "do", "double", "else", "equals", "extends",
-                "false", "final", "finalize", "finally", "float", "for",
-                "getClass", "goto", "hashCode", "if", "implements", "import",
-                "instanceof", "int", "interface", "long", "native", "new",
-                "notify", "notifyAll", "null", "package", "private",
-                "protected", "public", "return", "short", "static", "super",
-                "switch", "synchronized", "this", "throw", "throws",
-                "toString", "transient", "true", "try", "void", "volatile",
-                "wait", "while" };
-
-        for (String word : words) {
-            keyWords.add(new ByteString(word));
-        }
-    }
-
 }
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 5ed52e7..d7f2ab0 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
@@ -19,12 +19,15 @@
 package org.apache.yoko.rmi.impl;
 
 import java.io.Externalizable;
+import java.io.IOException;
 import java.io.Serializable;
-import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Constructor;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
+import java.rmi.AccessException;
 import java.rmi.MarshalException;
+import java.rmi.NoSuchObjectException;
 import java.rmi.Remote;
 import java.rmi.RemoteException;
 import java.rmi.ServerError;
@@ -32,54 +35,85 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.PrivilegedActionException;
-import java.util.logging.Logger;
+import java.security.PrivilegedExceptionAction;
 import java.util.logging.Level;
+import java.util.logging.Logger;
 
+import javax.rmi.PortableRemoteObject;
 import javax.rmi.CORBA.Stub;
 import javax.rmi.CORBA.Tie;
 import javax.rmi.CORBA.Util;
 import javax.rmi.CORBA.UtilDelegate;
 import javax.rmi.CORBA.ValueHandler;
-import javax.rmi.PortableRemoteObject;
 
-import org.apache.yoko.osgi.ProviderLocator;
 import org.apache.yoko.rmi.util.GetSystemPropertyAction;
+import org.apache.yoko.osgi.ProviderLocator;
 import org.omg.CORBA.Any;
+import org.omg.CORBA.BAD_PARAM;
+import org.omg.CORBA.COMM_FAILURE;
+import org.omg.CORBA.INVALID_TRANSACTION;
+import org.omg.CORBA.INV_OBJREF;
 import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.NO_IMPLEMENT;
+import org.omg.CORBA.NO_PERMISSION;
+import org.omg.CORBA.OBJECT_NOT_EXIST;
+import org.omg.CORBA.SystemException;
 import org.omg.CORBA.TCKind;
+import org.omg.CORBA.TRANSACTION_REQUIRED;
+import org.omg.CORBA.TRANSACTION_ROLLEDBACK;
 import org.omg.CORBA.TypeCode;
 import org.omg.CORBA.portable.IDLEntity;
 import org.omg.CORBA.portable.UnknownException;
 
 public class UtilImpl implements UtilDelegate {
-    static final Logger logger = Logger.getLogger(UtilImpl.class.getName());
+    private static final Logger logger = Logger.getLogger(UtilImpl.class.getName());
 
     // Note: this field must be declared before the static intializer that calls Util.loadClass
     // since that method will call loadClass0 which uses this field... if it is below the static
     // initializer the _secman field will be null
     private static final SecMan _secman = getSecMan();
 
-    static final Class JAVAX_TRANSACTION_USERTRANSACTION_CLASS;
-
+    private static final ClassLoader BEST_GUESS_AT_EXTENSION_CLASS_LOADER;
     static {
-        Class userTransactionClass;
-        try {
-            userTransactionClass = Util.loadClass("javax.transaction.userTransaction", null, null);
+        ClassLoader candidateLoader = getClassLoader(UtilImpl.class);
+
+        if (candidateLoader == null) {
+            // looks like this class was loaded by the boot class loader
+            // so it is safe to try loading stuff by reflection without
+            // worrying about whether we have imported the packages into the OSGi bundle
+            candidateLoader = findFirstNonNullLoader(
+                    "sun.net.spi.nameservice.dns.DNSNameService",
+                    "javax.transaction.UserTransaction");
         }
-        catch (ClassNotFoundException e) {
-            logger.log(Level.FINE, "error loading transaction class", e);
-            userTransactionClass = null;
+
+        // We will try to find the extension class
+        // loader by ascending the loader hierarchy 
+        // starting from whatever loader we found.
+        for (ClassLoader l = candidateLoader; l != null; l = l.getParent()) {
+            candidateLoader = l;
         }
-        JAVAX_TRANSACTION_USERTRANSACTION_CLASS = userTransactionClass;
+        
+        BEST_GUESS_AT_EXTENSION_CLASS_LOADER = candidateLoader;
+    }
+
+    private static ClassLoader findFirstNonNullLoader(String...classNames) {
+        for (String className : classNames) {
+            try {
+                final Class<?> c = Class.forName(className);
+                ClassLoader cl = getClassLoader(c);
+                if (cl != null) return cl;
+            } catch (Exception|NoClassDefFoundError swallowed) {
+            }
+        }
+        return null;
     }
 
     /**
      * Translate a CORBA SystemException to the corresponding RemoteException
      */
-    public RemoteException mapSystemException(
-            final org.omg.CORBA.SystemException theException) {
+    public RemoteException mapSystemException(final SystemException theException) {
 
-        org.omg.CORBA.SystemException ex = theException;
+        SystemException ex = theException;
 
         if (ex instanceof UnknownException) {
             Throwable orig = ((UnknownException) ex).originalEx;
@@ -95,27 +129,10 @@
             }
         }
 
-        Class exclass = ex.getClass();
+        Class<? extends SystemException> exclass = ex.getClass();
         String name = exclass.getName();
 
-        Class exclz = (Class) CORBA_TO_RMI_MAP.get(name);
-
-        if (exclz == null) {
-            exclz = RemoteException.class;
-
-            Class exc = ex.getClass();
-
-            for (int i = 0; i < CORBA_TO_RMI_EXCEPTION.length; i += 2) {
-                if (CORBA_TO_RMI_EXCEPTION[i].isAssignableFrom(exc)) {
-                    exclz = CORBA_TO_RMI_EXCEPTION[i + 1];
-                    break;
-                }
-            }
-        }
-
-        RemoteException rex = null;
-
-        // construct the exception message according to �1.4.8
+         // construct the exception message according to �1.4.8
 
         StringBuffer buf = new StringBuffer("CORBA ");
 
@@ -145,97 +162,96 @@
 
         String exceptionMessage = buf.toString();
 
-        try {
-
-            rex = (RemoteException) newInstance(exclz,
-                    new Class[]{String.class},
-                    new Object[]{exceptionMessage});
-
-            rex.detail = ex;
-
-        } catch (RuntimeException ex2) {
-
-            rex = new RemoteException(exceptionMessage, ex2);
-        }
-
-        return rex;
+        return createRemoteException(ex, exceptionMessage);
     }
 
-    static org.omg.CORBA.SystemException mapRemoteException(RemoteException rex) {
-        if (rex.detail != null
-                && rex.detail instanceof org.omg.CORBA.SystemException)
+    private RemoteException createRemoteException(SystemException sysEx, String s) {
+        RemoteException result;
+        try {
+            throw sysEx;
+        } catch (BAD_PARAM|COMM_FAILURE|MARSHAL e) {
+            result = new MarshalException(s);
+        } catch (INV_OBJREF|NO_IMPLEMENT|OBJECT_NOT_EXIST e) {
+            result = new NoSuchObjectException(s);
+        } catch(NO_PERMISSION e) {
+            result = new AccessException(s);
+        } catch (TRANSACTION_REQUIRED e) {
+            result = createRemoteException("javax.transaction.TransactionRequiredException", s);
+        } catch (TRANSACTION_ROLLEDBACK e) {
+            result = createRemoteException("javax.transaction.TransactionRolledbackException", s);
+        } catch (INVALID_TRANSACTION e) {
+            result = createRemoteException("javax.transaction.InvalidTransactionException", s);
+        } catch (SystemException catchAll) {
+            result = new RemoteException(s);
+        }
+        result.detail = sysEx;
+        return result;
+    }
+    
+    private static RemoteException createRemoteException(String className, String s) {
+        RemoteException result;
+        try {
+            @SuppressWarnings("unchecked")
+            Class<? extends RemoteException> clazz =  Util.loadClass(className, null, null);
+            Constructor<? extends RemoteException> ctor = clazz.getConstructor(String.class);
+            result = ctor.newInstance(s);
+        } catch (Throwable t) {
+            result = new RemoteException(s);
+            result.addSuppressed(t);
+        }
+        return result;
+    }
+
+    static SystemException mapRemoteException(RemoteException rex) {
+        if (rex.detail instanceof org.omg.CORBA.SystemException)
             return (org.omg.CORBA.SystemException) rex.detail;
 
-        if (rex.detail != null && rex.detail instanceof RemoteException)
+        if (rex.detail instanceof RemoteException)
             rex = (RemoteException) rex.detail;
+        
+        SystemException sysEx;
 
         if (rex instanceof java.rmi.NoSuchObjectException) {
-            throw new org.omg.CORBA.INV_OBJREF(rex.getMessage());
-
+            sysEx = new org.omg.CORBA.INV_OBJREF(rex.getMessage());
         } else if (rex instanceof java.rmi.AccessException) {
-            throw new org.omg.CORBA.NO_PERMISSION(rex.getMessage());
-
+            sysEx = new org.omg.CORBA.NO_PERMISSION(rex.getMessage());
         } else if (rex instanceof java.rmi.MarshalException) {
-            throw new org.omg.CORBA.MARSHAL(rex.getMessage());
-
-        } else if (rex instanceof javax.transaction.TransactionRequiredException) {
-            throw new org.omg.CORBA.TRANSACTION_REQUIRED(rex.getMessage());
-
-        } else if (rex instanceof javax.transaction.TransactionRolledbackException) {
-            throw new org.omg.CORBA.TRANSACTION_ROLLEDBACK(rex.getMessage());
-
-        } else if (rex instanceof javax.transaction.InvalidTransactionException) {
-            throw new org.omg.CORBA.INVALID_TRANSACTION(rex.getMessage());
-
-            /*
-             * } else if (rex.detail != null) { throw new
-             * org.omg.CORBA.portable.UnknownException (rex.detail);
-             */
-
+            sysEx = new org.omg.CORBA.MARSHAL(rex.getMessage());
         } else {
-            throw new org.omg.CORBA.portable.UnknownException(rex);
-
+            sysEx = createSystemException(rex);
         }
-
+        sysEx.initCause(rex);
+        throw sysEx;
     }
-
+    
+    private static SystemException createSystemException(RemoteException rex) {
+        return createSystemException(rex, rex.getClass());
+    }
+    
     /**
-     * Generic function for reflective instantiation
+     * utility method to check for JTA exception types without linking to the JTA classes directly
      */
-    private Object newInstance(final Class cls, final Class[] arg_types,
-                               final Object[] args) {
-        return java.security.AccessController
-                .doPrivileged(new java.security.PrivilegedAction() {
-                    public Object run() {
-                        try {
-                            java.lang.reflect.Constructor cons = cls
-                                    .getConstructor(arg_types);
-
-                            return cons.newInstance(args);
-
-                        } catch (NoSuchMethodException ex) {
-                            return new RuntimeException("cannot instantiate "
-                                    + cls + ": " + ex.getMessage(), ex);
-
-                        } catch (InstantiationException ex) {
-                            return new RuntimeException("cannot instantiate "
-                                    + cls + ": " + ex.getMessage(), ex);
-
-                        } catch (IllegalAccessException ex) {
-                            return new RuntimeException("cannot instantiate "
-                                    + cls + ": " + ex.getMessage(), ex);
-
-                        } catch (IllegalArgumentException ex) {
-                            return new RuntimeException("cannot instantiate "
-                                    + cls + ": " + ex.getMessage(), ex);
-
-                        } catch (InvocationTargetException ex) {
-                            return new RuntimeException("cannot instantiate "
-                                    + cls + ": " + ex.getMessage(), ex);
-
-                        }
-                    }
-                });
+    private static SystemException createSystemException(RemoteException rex, Class<?> fromClass) {
+        // Recurse up the parent chain,
+        // until we reach a known JTA type. 
+        switch(fromClass.getName()) {
+            // Of course, we place some known elephants in Cairo.
+            case "java.lang.Object":
+            case "java.lang.Throwable":
+            case "java.lang.Exception":
+            case "java.lang.RuntimeException":
+            case "java.lang.Error":
+            case "java.io.IOException":
+            case "java.rmi.RemoteException":
+                return new UnknownException(rex);
+            case "javax.transaction.InvalidTransactionException":
+                return new INVALID_TRANSACTION(rex.getMessage());
+            case "javax.transaction.TransactionRolledbackException":
+                return new TRANSACTION_ROLLEDBACK(rex.getMessage());
+            case "javax.transaction.TransactionRequiredException":
+                return new TRANSACTION_REQUIRED(rex.getMessage());
+        }
+        return createSystemException(rex, fromClass.getSuperclass());
     }
 
     /**
@@ -321,7 +337,7 @@
 
             case TCKind._tk_abstract_interface:
                 org.omg.CORBA_2_3.portable.InputStream in23 = (org.omg.CORBA_2_3.portable.InputStream) any
-                        .create_input_stream();
+                .create_input_stream();
                 return in23.read_abstract_interface();
 
             case TCKind._tk_string:
@@ -353,7 +369,7 @@
      * instances of java.rmi.Remote for objects that have already been exported.
      */
     public void writeRemoteObject(org.omg.CORBA.portable.OutputStream out,
-                                  Object obj) throws org.omg.CORBA.SystemException {
+            Object obj) throws org.omg.CORBA.SystemException {
         org.omg.CORBA.Object objref = null;
 
         if (obj == null) {
@@ -391,8 +407,7 @@
         out.write_Object(objref);
     }
 
-    public void writeAbstractObject(org.omg.CORBA.portable.OutputStream out,
-                                    Object obj) {
+    public void writeAbstractObject(org.omg.CORBA.portable.OutputStream out, Object obj) {
         logger.finer("writeAbstractObject.1 " + " out=" + out);
 
         if (obj instanceof org.omg.CORBA.Object || obj instanceof Serializable) {
@@ -428,7 +443,8 @@
         out_.write_abstract_interface(obj);
     }
 
-    protected java.util.Map tie_map() {
+    @SuppressWarnings("unchecked")
+    protected java.util.Map<Remote, Tie> tie_map() {
         return RMIState.current().tie_map;
     }
 
@@ -447,15 +463,14 @@
         if (obj == null)
             return null;
 
-        return (Tie) tie_map().get(obj);
+        return tie_map().get(obj);
     }
 
     public ValueHandler createValueHandler() {
-        return RMIState.current().createValueHandler();
-        // return new ValueHandlerImpl (null);
+        return ValueHandlerImpl.get();
     }
 
-    public String getCodebase(Class clz) {
+    public String getCodebase(@SuppressWarnings("rawtypes") Class clz) {
         if (clz == null)
             return null;
 
@@ -476,8 +491,7 @@
             return null;
 
         // ignore standard extensions
-        if (JAVAX_TRANSACTION_USERTRANSACTION_CLASS != null &&
-                theLoader == JAVAX_TRANSACTION_USERTRANSACTION_CLASS.getClassLoader())
+        if (theLoader == BEST_GUESS_AT_EXTENSION_CLASS_LOADER)
             return null;
 
         RMIState state = RMIState.current();
@@ -501,10 +515,11 @@
             // ignore
         }
 
-        return (String) AccessController.doPrivileged(new GetSystemPropertyAction("java.rmi.server.codebase"));
+        return AccessController.doPrivileged(new GetSystemPropertyAction("java.rmi.server.codebase"));
     }
 
     static class SecMan extends java.rmi.RMISecurityManager {
+        @SuppressWarnings("rawtypes")
         public Class[] getClassContext() {
             return super.getClassContext();
         }
@@ -512,18 +527,18 @@
 
     private static SecMan getSecMan() {
         try {
-            return (SecMan) AccessController
-                    .doPrivileged(new java.security.PrivilegedExceptionAction() {
-                        public Object run() {
-                            return new SecMan();
-                        }
-                    });
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<SecMan>() {
+                public SecMan run() {
+                    return new SecMan();
+                }
+            });
         } catch (PrivilegedActionException e) {
             throw new RuntimeException(e);
         }
 
     }
 
+    @SuppressWarnings("rawtypes")
     public Class loadClass(String name, String codebase, ClassLoader loader)
             throws ClassNotFoundException {
         try {
@@ -535,7 +550,7 @@
         }
     }
 
-    static public Class loadClass0(String name, String codebase, ClassLoader loader)
+    static public Class<?> loadClass0(String name, String codebase, ClassLoader loader)
             throws ClassNotFoundException {
 
         try {
@@ -543,11 +558,11 @@
         } catch (ClassNotFoundException e) {
             //skip
         }
-        Class result = null;
+        Class<?> result = null;
 
         ClassLoader stackLoader = null;
         ClassLoader thisLoader = Util.class.getClassLoader();
-        Class[] stack = _secman.getClassContext();
+        Class<?>[] stack = _secman.getClassContext();
         for (int i = 1; i < stack.length; i++) {
             ClassLoader testLoader = stack[i].getClassLoader();
             if (testLoader != null && testLoader != thisLoader) {
@@ -584,36 +599,17 @@
 
         if (codebase != null && !"".equals(codebase)
                 && !Boolean.getBoolean("java.rmi.server.useCodeBaseOnly")) {
-            try {
-                logger.finer("trying RMIClassLoader");
-
-                URLClassLoader url_loader = new URLClassLoader(
-                        new URL[]{new URL(codebase)}, loader);
-
+            logger.finer("trying RMIClassLoader");
+            try (URLClassLoader url_loader = new URLClassLoader(new URL[]{new URL(codebase)}, loader)) {
                 result = url_loader.loadClass(name);
-
-                // log.info("SUCESSFUL class download "+name+" from "+codebase,
-                // new Throwable("TRACE"));
-
             } catch (ClassNotFoundException ex) {
                 logger.log(Level.FINER, "RMIClassLoader says " + ex.getMessage(), ex);
-
-                // log.info("FAILED class download "+name+" from "+codebase,
-                // ex);
-
-                // skip //
             } catch (MalformedURLException ex) {
                 logger.log(Level.FINER, "RMIClassLoader says " + ex.getMessage(), ex);
-
-                logger.finer("FAILED class download " + name + " from "
-                        + codebase + " " + ex.getMessage());
-
-                // skip //
+                logger.finer("FAILED class download " + name + " from " + codebase + " " + ex.getMessage());
             } catch (RuntimeException ex) {
-
-                logger.log(Level.FINER, "FAILED class download " + name + " from "
-                        + codebase + " " + ex.getMessage(), ex);
-
+                logger.log(Level.FINER, "FAILED class download " + name + " from " + codebase + " " + ex.getMessage(), ex);
+            } catch (IOException unimportant) {
             }
 
             if (result != null) {
@@ -696,40 +692,38 @@
     }
 
     static ClassLoader getContextClassLoader() {
-        return (ClassLoader) AccessController
-                .doPrivileged(new PrivilegedAction() {
-                    public Object run() {
-                        return Thread.currentThread().getContextClassLoader();
-                    }
-                });
+        return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+            public ClassLoader run() {
+                return Thread.currentThread().getContextClassLoader();
+            }
+        });
     }
 
-    static ClassLoader getClassLoader(final Class clz) {
+    static ClassLoader getClassLoader(final Class<?> clz) {
         if (System.getSecurityManager() == null) {
             return clz.getClassLoader();
         } else {
-            return (ClassLoader) AccessController
-                    .doPrivileged(new PrivilegedAction() {
-                        public Object run() {
-                            return clz.getClassLoader();
-                        }
-                    });
+            return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
+                public ClassLoader run() {
+                    return clz.getClassLoader();
+                }
+            });
         }
     }
 
     static Object copyRMIStub(RMIStub stub) throws RemoteException {
         ClassLoader loader = getContextClassLoader();
 
-        if (getClassLoader(stub._descriptor.getJavaClass()) == loader) {
+        if (getClassLoader(stub._descriptor.type) == loader) {
             return stub;
         }
 
         RemoteDescriptor desc = stub._descriptor;
 
-        Class targetClass;
+        Class<?> targetClass;
 
         try {
-            targetClass = Util.loadClass(desc.getJavaClass().getName(), stub
+            targetClass = Util.loadClass(desc.type.getName(), stub
                     ._get_codebase(), loader);
         } catch (ClassNotFoundException ex) {
             logger.log(Level.FINER, "copyRMIStub exception (current loader is: " + loader
@@ -780,7 +774,7 @@
          * mapSystemException (ex); }
          */
         try {
-            TypeRepository rep = RMIState.current().getTypeRepository();
+            TypeRepository rep = RMIState.current().repo;
             CopyState state = new CopyState(rep);
             return state.copy(obj);
         } catch (CopyRecursionException ex) {
@@ -811,7 +805,7 @@
 
         try {
 
-            TypeRepository rep = RMIState.current().getTypeRepository();
+            TypeRepository rep = RMIState.current().repo;
             CopyState state = new CopyState(rep);
             try {
                 return (Object[]) state.copy(objs);
@@ -862,12 +856,12 @@
         if (obj == null)
             return;
 
-        java.util.Map tie_map = tie_map();
+        java.util.Map<Remote, Tie> tie_map = tie_map();
 
         if (tie_map == null)
             return;
 
-        Tie tie = (Tie) tie_map.remove(obj);
+        Tie tie = tie_map.remove(obj);
 
         if (tie == null) {
             logger.fine("unexporting unknown instance of "
@@ -881,82 +875,4 @@
 
         tie.deactivate();
     }
-
-    static final Class[] RMI_TO_CORBA_EXCEPTION;
-
-//  We want to avoid a dependency on JTA, so we add these classes only if JTA is available.
-
-    static {
-        Class[] rmiToCorba;
-        try {
-            rmiToCorba = new Class[]{
-                    Util.loadClass("javax.transaction.HeuristicMixedException", null, null),
-                    org.omg.CosTransactions.HeuristicMixed.class,
-
-                    Util.loadClass("javax.transaction.HeuristicRollbackException", null, null),
-                    org.omg.CosTransactions.HeuristicRollback.class,
-
-                    Util.loadClass("javax.transaction.HeuristicCommitException", null, null),
-                    org.omg.CosTransactions.HeuristicCommit.class,
-
-                    Util.loadClass("javax.transaction.NotSupportedException", null, null),
-                    org.omg.CosTransactions.SubtransactionsUnavailable.class,
-
-                    Util.loadClass("javax.transaction.InvalidTransactionException", null, null),
-                    org.omg.CORBA.INVALID_TRANSACTION.class,
-
-                    Util.loadClass("javax.transaction.TransactionRequiredException", null, null),
-                    org.omg.CORBA.TRANSACTION_REQUIRED.class,
-
-                    Util.loadClass("javax.transaction.TransactionRolledbackException", null, null),
-                    org.omg.CORBA.TRANSACTION_ROLLEDBACK.class,
-
-                    Util.loadClass("javax.transaction.RollbackException", null, null),
-                    org.omg.CORBA.TRANSACTION_ROLLEDBACK.class
-            };
-
-        }
-        catch (ClassNotFoundException e) {
-            rmiToCorba = new Class[0];
-        }
-        RMI_TO_CORBA_EXCEPTION = rmiToCorba;
-    }
-
-    static final Class[] CORBA_TO_RMI_EXCEPTION = {
-            org.omg.CORBA.BAD_PARAM.class, java.rmi.MarshalException.class,
-
-            org.omg.CORBA.COMM_FAILURE.class, java.rmi.MarshalException.class,
-
-            org.omg.CORBA.INV_OBJREF.class,
-            java.rmi.NoSuchObjectException.class,
-
-            org.omg.CORBA.MARSHAL.class, java.rmi.MarshalException.class,
-
-            org.omg.CORBA.NO_IMPLEMENT.class,
-            java.rmi.NoSuchObjectException.class,
-
-            org.omg.CORBA.NO_PERMISSION.class, java.rmi.AccessException.class,
-
-            org.omg.CORBA.OBJECT_NOT_EXIST.class,
-            java.rmi.NoSuchObjectException.class,
-
-            org.omg.CORBA.TRANSACTION_REQUIRED.class,
-            javax.transaction.TransactionRequiredException.class,
-
-            org.omg.CORBA.TRANSACTION_ROLLEDBACK.class,
-            javax.transaction.TransactionRolledbackException.class,
-
-            org.omg.CORBA.INVALID_TRANSACTION.class,
-            javax.transaction.InvalidTransactionException.class};
-
-    static final java.util.Map CORBA_TO_RMI_MAP = new java.util.HashMap();
-
-    static {
-        for (int i = 0; i < CORBA_TO_RMI_EXCEPTION.length; i += 2) {
-            Class corba = CORBA_TO_RMI_EXCEPTION[i];
-            Class rmi = CORBA_TO_RMI_EXCEPTION[i + 1];
-
-            CORBA_TO_RMI_MAP.put(corba.getName(), rmi);
-        }
-    }
 }
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 cb8e99a..6e66d1c 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
@@ -1,130 +1,133 @@
 /**
-*
-* 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.
-*/ 
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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 static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableSet;
+
 import java.io.ByteArrayOutputStream;
 import java.io.DataOutputStream;
+import java.io.Externalizable;
 import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
 import java.io.ObjectStreamField;
+import java.io.PrintWriter;
 import java.io.Serializable;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.security.AccessController;
 import java.security.DigestOutputStream;
 import java.security.MessageDigest;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
 import java.util.Set;
-import java.util.logging.Logger;
 import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import org.apache.yoko.rmi.util.StringUtil;
+import org.omg.CORBA.AttributeDescription;
+import org.omg.CORBA.Initializer;
 import org.omg.CORBA.MARSHAL;
+import org.omg.CORBA.ORB;
+import org.omg.CORBA.OperationDescription;
 import org.omg.CORBA.TypeCode;
+import org.omg.CORBA.VM_NONE;
 import org.omg.CORBA.ValueMember;
 import org.omg.CORBA.ValueDefPackage.FullValueDescription;
+import org.omg.CORBA.portable.InputStream;
+import org.omg.CORBA.portable.OutputStream;
+import org.omg.CORBA.portable.UnknownException;
 import org.omg.SendingContext.CodeBase;
 import org.omg.SendingContext.CodeBaseHelper;
+import org.omg.SendingContext.RunTime;
 
 import sun.reflect.ReflectionFactory;
 
-public class ValueDescriptor extends TypeDescriptor {
-    static final Logger logger = Logger.getLogger(ValueDescriptor.class
-            .getName());
+class ValueDescriptor extends TypeDescriptor {
+    static final Logger logger = Logger.getLogger(ValueDescriptor.class.getName());
 
-    protected boolean _is_externalizable;
+    private boolean _is_externalizable;
 
-    protected boolean _is_serializable;
+    private boolean _is_serializable;
 
-    protected Method _write_replace_method;
+    private Method _write_replace_method;
 
-    protected Method _read_resolve_method;
+    private Method _read_resolve_method;
 
-    protected Constructor _constructor;
+    private Constructor _constructor;
 
-    protected Method _write_object_method;
+    private Method _write_object_method;
 
-    protected Method _read_object_method;
+    private Method _read_object_method;
 
-    protected Field _serial_version_uid_field;
+    private Field _serial_version_uid_field;
 
     protected ValueDescriptor _super_descriptor;
 
     protected FieldDescriptor[] _fields;
 
-    protected ObjectDeserializer _object_deserializer;
+    private ObjectDeserializer _object_deserializer;
 
-    protected boolean _is_immutable_value;
+    private boolean _is_immutable_value;
 
-    protected boolean _is_rmi_stub;
+    private boolean _is_rmi_stub;
 
-    private static Set _immutable_value_classes;
+    private String _custom_repid;
 
-    private static Object[] NO_ARGS = new Object[0];
+    private static final Set<? extends Class<? extends Serializable>> _immutable_value_classes = unmodifiableSet(new HashSet<>(asList(Integer.class,
+            Character.class, Boolean.class, Byte.class, Long.class, Float.class, Double.class, Short.class)));
 
-    static {
-        _immutable_value_classes = new HashSet();
-        _immutable_value_classes.add(Integer.class);
-        _immutable_value_classes.add(Character.class);
-        _immutable_value_classes.add(Boolean.class);
-        _immutable_value_classes.add(Byte.class);
-        _immutable_value_classes.add(Long.class);
-        _immutable_value_classes.add(Float.class);
-        _immutable_value_classes.add(Double.class);
-        _immutable_value_classes.add(Short.class);
-    }
-
-    protected long _hash_code;
+    private long _hash_code;
 
     ValueDescriptor(Class type, TypeRepository repository) {
         super(type, repository);
     }
 
-    public String getRepositoryID() {
-        if (_repid == null) {
-            StringBuffer buf = new StringBuffer("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(type.getName()),
+                _hash_code, getSerialVersionUID());
     }
 
-    long getSerialVersionUID() {
+    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;
+    }
+
+    protected long getSerialVersionUID() {
         if (_serial_version_uid_field != null) {
 
             try {
@@ -133,40 +136,36 @@
                 // skip //
             }
         }
-        java.io.ObjectStreamClass serialForm = java.io.ObjectStreamClass.lookup(getJavaClass());
-       
-        return serialForm != null ? serialForm.getSerialVersionUID() : 0L;
+        ObjectStreamClass serialForm = ObjectStreamClass.lookup(type);
+
+        return (serialForm != null) ? serialForm.getSerialVersionUID() : 0L;
     }
 
     public void init() {
         try {
             init0();
+            super.init();
 
             if (_fields == null) {
                 throw new RuntimeException("fields==null after init!");
             }
 
-        } catch (RuntimeException ex) {
-            logger.log(Level.FINE, "runtime error in ValueDescriptor.init " + ex.getMessage(), ex);
-        } catch (Error ex) {
+        } catch (RuntimeException | Error ex) {
             logger.log(Level.FINE, "runtime error in ValueDescriptor.init " + ex.getMessage(), ex);
         }
     }
 
-    public void init0() {
-        final Class type = getJavaClass();
-        final Class superClass = type.getSuperclass();
+    private void init0() {
+        final Class<?> superClass = type.getSuperclass();
 
         _is_rmi_stub = RMIStub.class.isAssignableFrom(type);
-        _is_externalizable = java.io.Externalizable.class
-                .isAssignableFrom(type);
-        _is_serializable = java.io.Serializable.class.isAssignableFrom(type);
+        _is_externalizable = Externalizable.class.isAssignableFrom(type);
+        _is_serializable = Serializable.class.isAssignableFrom(type);
 
         _is_immutable_value = _immutable_value_classes.contains(type);
 
-        if (superClass != null && superClass != java.lang.Object.class) {
-            TypeDescriptor superDesc = getTypeRepository().getDescriptor(
-                    superClass);
+        if ((superClass != null) && (superClass != Object.class)) {
+            TypeDescriptor superDesc = repo.getDescriptor(superClass);
 
             if (superDesc instanceof ValueDescriptor) {
                 _super_descriptor = (ValueDescriptor) superDesc;
@@ -174,293 +173,229 @@
 
         }
 
-        java.security.AccessController
-                .doPrivileged(new java.security.PrivilegedAction() {
-                    public Object run() {
+        AccessController.doPrivileged(new PrivilegedAction<Object>() {
+            public Object run() {
 
-                        for (Class curr = type; curr != null; curr = curr
-                                .getSuperclass()) {
+                for (Class<?> curr = type; curr != null; curr = curr.getSuperclass()) {
+                    //
+                    // get writeReplace, if any
+                    //
+                    try {
+                        _write_replace_method = curr.getDeclaredMethod("writeReplace");
+                        _write_replace_method.setAccessible(true);
 
-                            //
-                            // get writeReplace, if any
-                            //
-                            try {
-                                _write_replace_method = curr.getDeclaredMethod(
-                                        "writeReplace", new Class[0]);
-                                _write_replace_method.setAccessible(true);
+                        break;
+                    } catch (NoSuchMethodException ignored) {
+                    }
+                }
 
-                                break;
-                            } catch (NoSuchMethodException ex) {
+                //
+                // Get readResolve, if present
+                //
+                try {
+                    _read_resolve_method = type.getDeclaredMethod("readResolve");
+                    _read_resolve_method.setAccessible(true);
 
-                            }
-                        }
+                } catch (NoSuchMethodException ignored) {
+                }
 
-                        //
-                        // Get readResolve, if present
-                        //
-                        try {
-                            _read_resolve_method = type.getDeclaredMethod(
-                                    "readResolve", new Class[0]);
-                            _read_resolve_method.setAccessible(true);
+                // 
+                // get readObject
+                //
+                try {
+                    _read_object_method = type.getDeclaredMethod("readObject", ObjectInputStream.class);
+                    _read_object_method.setAccessible(true);
+                } catch (NoSuchMethodException ignored) {
+                }
 
-                        } catch (NoSuchMethodException ex) {
-                            // skip //
-                        }
+                // 
+                // get readObject
+                //
+                try {
+                    _write_object_method = type.getDeclaredMethod("writeObject", ObjectOutputStream.class);
+                    _write_object_method.setAccessible(true);
+                } catch (NoSuchMethodException ignored) {
+                }
 
-                        // 
-                        // get readObject
-                        //
-                        try {
-                            _read_object_method = type
-                                    .getDeclaredMethod(
-                                            "readObject",
-                                            new Class[] { java.io.ObjectInputStream.class });
-                            _read_object_method.setAccessible(true);
-                        } catch (NoSuchMethodException ex) {
-                            // skip //
-                        }
+                // 
+                // validate readObject
+                //
+                if ((_write_object_method == null) || !Modifier.isPrivate(_write_object_method.getModifiers())
+                        || Modifier.isStatic(_write_object_method.getModifiers()) || (_write_object_method.getDeclaringClass() != type)) {
 
-                        // 
-                        // get readObject
-                        //
-                        try {
-                            _write_object_method = type
-                                    .getDeclaredMethod(
-                                            "writeObject",
-                                            new Class[] { java.io.ObjectOutputStream.class });
-                            _write_object_method.setAccessible(true);
-                        } catch (NoSuchMethodException ex) {
-                            // skip //
-                        }
+                    _write_object_method = null;
 
-                        // 
-                        // validate readObject
-                        //
-                        if (_write_object_method == null
-                                || !Modifier.isPrivate(_write_object_method
-                                        .getModifiers())
-                                || Modifier.isStatic(_write_object_method
-                                        .getModifiers())
-                                || _write_object_method.getDeclaringClass() != getJavaClass()) {
+                }
 
-                            _write_object_method = null;
+                // 
+                // validate writeObject
+                //
+                if ((_read_object_method == null) || !Modifier.isPrivate(_read_object_method.getModifiers())
+                        || Modifier.isStatic(_read_object_method.getModifiers())) {
 
-                        }
+                    _read_object_method = null;
+                }
 
-                        // 
-                        // validate writeObject
-                        //
-                        if (_read_object_method == null
-                                || !Modifier.isPrivate(_read_object_method
-                                        .getModifiers())
-                                || Modifier.isStatic(_read_object_method
-                                        .getModifiers())) {
+                // 
+                // get serialVersionUID field
+                //
+                try {
+                    _serial_version_uid_field = type.getDeclaredField("serialVersionUID");
+                    if (Modifier.isStatic(_serial_version_uid_field.getModifiers())) {
+                        _serial_version_uid_field.setAccessible(true);
+                    } else {
+                        _serial_version_uid_field = null;
+                    }
+                } catch (NoSuchFieldException ex) {
+                    // skip //
+                }
 
-                            _read_object_method = null;
-                        }
+                // 
+                // get serialPersistentFields field
+                //
+                ObjectStreamField[] serial_persistent_fields = null;
+                try {
+                    Field _serial_persistent_fields_field = type.getDeclaredField("serialPersistentFields");
+                    _serial_persistent_fields_field.setAccessible(true);
 
-                        // 
-                        // get serialVersionUID field
-                        //
-                        try {
-                            _serial_version_uid_field = type
-                                    .getDeclaredField("serialVersionUID");
-                            if (Modifier.isStatic(_serial_version_uid_field
-                                    .getModifiers())) {
-                                _serial_version_uid_field.setAccessible(true);
-                            } else {
-                                _serial_version_uid_field = null;
-                            }
-                        } catch (NoSuchFieldException ex) {
-                            // skip //
-                        }
+                    serial_persistent_fields = (ObjectStreamField[]) _serial_persistent_fields_field.get(null);
 
-                        // 
-                        // get serialPersistentFields field
-                        //
-                        ObjectStreamField[] serial_persistent_fields = null;
-                        try {
-                            Field _serial_persistent_fields_field = type
-                                    .getDeclaredField("serialPersistentFields");
-                            _serial_persistent_fields_field.setAccessible(true);
+                } catch (IllegalAccessException | NoSuchFieldException ex) {
+                    // skip //
+                }
 
-                            serial_persistent_fields = (ObjectStreamField[]) _serial_persistent_fields_field
-                                    .get(null);
+                if (_is_externalizable) {
+                    //
+                    // Get the default constructor
+                    //
+                    try {
+                        _constructor = type.getDeclaredConstructor();
+                        _constructor.setAccessible(true);
 
-                        } catch (IllegalAccessException ex) {
-                            // skip //
-                        } catch (NoSuchFieldException ex) {
-                            // skip //
-                        }
-
-                        if (_is_externalizable) {
-                            //
-                            // Get the default constructor
-                            //
-                            try {
-                                _constructor = type
-                                        .getDeclaredConstructor(new Class[0]);
-                                _constructor.setAccessible(true);
-
-                            } catch (NoSuchMethodException ex) {
-                                logger.log(Level.WARNING, "Class " + type.getName()
-                                        + " is not properly externalizable.  "
-                                        + "It has not default constructor.", ex);
-                            }
-
-                        } else if (_is_serializable && !type.isInterface()) {
-
-                            Class initClass = type;
-
-                            while (initClass != null
-                                    && java.io.Serializable.class
-                                            .isAssignableFrom(initClass)) {
-                                initClass = initClass.getSuperclass();
-                            }
-
-                            if (initClass == null) {
-                                logger
-                                        .warning("Class "
-                                                + type.getName()
-                                                + " is not properly serializable.  "
-                                                + "It has no non-serializable super-class");
-                            } else {
-                                try {
-                                    Constructor init_cons = initClass
-                                            .getDeclaredConstructor(new Class[0]);
-
-                                    if (Modifier.isPublic(init_cons
-                                            .getModifiers())
-                                            || Modifier.isProtected(init_cons
-                                                    .getModifiers())) {
-                                        // do nothing - it's accessible
-
-                                    } else if (!samePackage(type, initClass)) {
-                                        logger
-                                                .warning("Class "
-                                                        + type.getName()
-                                                        + " is not properly serializable.  "
-                                                        + "The default constructor of its first "
-                                                        + "non-serializable super-class ("
-                                                        + initClass.getName()
-                                                        + ") is not accessible.");
-                                    }
-
-                                    _constructor = ReflectionFactory
-                                            .getReflectionFactory()
-                                            .newConstructorForSerialization(
-                                                    type, init_cons);
-
-                                    if (_constructor == null) {
-                                        logger
-                                                .warning("Unable to get constructor for serialization for class "
-                                                        + getJavaName());
-                                    } else {
-                                        _constructor.setAccessible(true);
-                                    }
-
-                                } catch (NoSuchMethodException ex) {
-                                    logger.log(Level.WARNING, 
-                                                     "Class "
-                                                    + type.getName()
-                                                    + " is not properly serializable.  "
-                                                    + "First non-serializable super-class ("
-                                                    + initClass.getName()
-                                                    + ") has not default constructor.", ex);
-                                }
-                            }
-                        }
-
-                        if (serial_persistent_fields == null) {
-
-                            //
-                            // Get relevant field definitions
-                            //
-
-                            Field[] ff = type.getDeclaredFields();
-
-                            if (ff == null || ff.length == 0) {
-                                _fields = new FieldDescriptor[0];
-
-                            } else {
-                                java.util.List flist = new java.util.ArrayList();
-
-                                for (int i = 0; i < ff.length; i++) {
-                                    Field f = ff[i];
-                                    int mod = f.getModifiers();
-                                    if (Modifier.isStatic(mod)
-                                            || Modifier.isTransient(mod)) {
-                                        continue;
-                                    }
-
-                                    f.setAccessible(true);
-                                    FieldDescriptor fd = FieldDescriptor.get(f);
-                                    fd.setTypeRepository(getTypeRepository());
-                                    flist.add(fd);
-                                }
-
-                                _fields = new FieldDescriptor[flist.size()];
-                                _fields = (FieldDescriptor[]) flist
-                                        .toArray(_fields);
-
-                                //
-                                // sort the fields
-                                //
-                                java.util.Arrays.sort(_fields);
-                            }
-
-                        } else {
-                            _fields = new FieldDescriptor[serial_persistent_fields.length];
-
-                            for (int i = 0; i < serial_persistent_fields.length; i++) {
-                                ObjectStreamField f = serial_persistent_fields[i];
-
-                                FieldDescriptor fd = null;
-
-                                try {
-                                    java.lang.reflect.Field rf = type
-                                            .getField(f.getName());
-                                    rf.setAccessible(true);
-
-                                    if (rf.getType() == f.getType()) {
-                                        fd = FieldDescriptor.get(rf);
-                                    }
-                                } catch (SecurityException ex) {
-                                } catch (NoSuchFieldException ex) {
-                                }
-
-                                if (fd == null) {
-                                    fd = FieldDescriptor.get(type, f);
-                                }
-
-                                fd.setTypeRepository(getTypeRepository());
-                                _fields[i] = fd;
-                            }
-
-                            //
-                            // sort the fields (this is also the case for serial
-                            // persistent
-                            // fields, because they have to map to some foreign
-                            // IDL).
-                            //
-                            java.util.Arrays.sort(_fields);
-                        }
-
-                        //
-                        // Compute the structural hasn
-                        //
-                        _hash_code = computeHashCode();
-
-                        // 
-                        // Setup the default deserializer
-                        //
-                        _object_deserializer = new ObjectDeserializer(
-                                ValueDescriptor.this);
-
-                        return null;
+                    } catch (NoSuchMethodException ex) {
+                        logger.log(Level.WARNING, "Class " + type.getName() + " is not properly externalizable.  "
+                                + "It has not default constructor.", ex);
                     }
 
-                });
+                } else if (_is_serializable && !type.isInterface()) {
+
+                    Class<?> initClass = type;
+
+                    while ((initClass != null) && Serializable.class.isAssignableFrom(initClass)) {
+                        initClass = initClass.getSuperclass();
+                    }
+
+                    if (initClass == null) {
+                        logger.warning("Class " + type.getName() + " is not properly serializable.  " + "It has no non-serializable super-class");
+                    } else {
+                        try {
+                            Constructor init_cons = initClass.getDeclaredConstructor();
+
+                            if (Modifier.isPublic(init_cons.getModifiers()) || Modifier.isProtected(init_cons.getModifiers())) {
+                                // do nothing - it's accessible
+
+                            } else if (!samePackage(type, initClass)) {
+                                logger.warning("Class " + type.getName() + " is not properly serializable.  "
+                                        + "The default constructor of its first " + "non-serializable super-class (" + initClass.getName()
+                                        + ") is not accessible.");
+                            }
+
+                            _constructor = ReflectionFactory.getReflectionFactory().newConstructorForSerialization(type, init_cons);
+
+                            if (_constructor == null) {
+                                logger.warning("Unable to get constructor for serialization for class " + java_name);
+                            } else {
+                                _constructor.setAccessible(true);
+                            }
+
+                        } catch (NoSuchMethodException ex) {
+                            logger.log(Level.WARNING, "Class " + type.getName() + " is not properly serializable.  "
+                                    + "First non-serializable super-class (" + initClass.getName() + ") has no default constructor.", ex);
+                        }
+                    }
+                }
+
+                if (serial_persistent_fields == null) {
+
+                    //
+                    // Get relevant field definitions
+                    //
+
+                    Field[] ff = type.getDeclaredFields();
+
+                    if ((ff == null) || (ff.length == 0)) {
+                        _fields = new FieldDescriptor[0];
+
+                    } else {
+                        List<FieldDescriptor> flist = new ArrayList<>();
+
+                        for (Field f : ff) {
+                            int mod = f.getModifiers();
+                            if (Modifier.isStatic(mod) || Modifier.isTransient(mod)) {
+                                continue;
+                            }
+
+                            f.setAccessible(true);
+                            FieldDescriptor fd = FieldDescriptor.get(f, repo);
+                            flist.add(fd);
+                        }
+
+                        _fields = new FieldDescriptor[flist.size()];
+                        _fields = flist.toArray(_fields);
+
+                        //
+                        // sort the fields
+                        //
+                        Arrays.sort(_fields);
+                    }
+
+                } else {
+                    _fields = new FieldDescriptor[serial_persistent_fields.length];
+
+                    for (int i = 0; i < serial_persistent_fields.length; i++) {
+                        ObjectStreamField f = serial_persistent_fields[i];
+
+                        FieldDescriptor fd = null;
+
+                        try {
+                            Field rf = type.getField(f.getName());
+                            rf.setAccessible(true);
+
+                            if (rf.getType() == f.getType()) {
+                                fd = FieldDescriptor.get(rf,repo);
+                            }
+                        } catch (SecurityException | NoSuchFieldException ex) {
+                        }
+
+                        if (fd == null) {
+                            fd = FieldDescriptor.get(type, f, repo);
+                        }
+                        _fields[i] = fd;
+                    }
+
+                    //
+                    // sort the fields (this is also the case for serial
+                    // persistent
+                    // fields, because they have to map to some foreign
+                    // IDL).
+                    //
+                    Arrays.sort(_fields);
+                }
+
+                //
+                // Compute the structural hash
+                //
+                _hash_code = computeHashCode();
+
+                // 
+                // Setup the default deserializer
+                //
+                _object_deserializer = new ObjectDeserializer(ValueDescriptor.this);
+
+                return null;
+            }
+
+        });
     }
 
     private boolean samePackage(Class type, Class initClass) {
@@ -473,52 +408,41 @@
     private String getPackageName(Class type) {
         String name = type.getName();
         int idx = name.lastIndexOf('.');
-        if (idx == -1) {
-            return "";
-        } else {
-            return name.substring(0, idx);
-        }
+        return (idx == -1) ? "" : name.substring(0, idx);
     }
 
     /** Read an instance of this value from a CDR stream */
     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;
-
-        return _in.read_value();
+        return ((org.omg.CORBA_2_3.portable.InputStream) in).read_value();
     }
 
     /** Write an instance of this value to a CDR stream */
-    public void write(org.omg.CORBA.portable.OutputStream out, Object value) {
-        org.omg.CORBA_2_3.portable.OutputStream _out = (org.omg.CORBA_2_3.portable.OutputStream) out;
-
-        _out.write_value((java.io.Serializable) value);
+    public void write(OutputStream out, Object value) {
+        ((org.omg.CORBA_2_3.portable.OutputStream) out).write_value((Serializable) value);
     }
 
     public boolean isCustomMarshalled() {
-        if (_is_externalizable)
-            return true;
-
-        if (_write_object_method != null)
-            return true;
-
-        return false;
+        return (_is_externalizable || (_write_object_method != null));
     }
 
-    public java.io.Serializable writeReplace(java.io.Serializable val) {
+    public boolean isChunked() {
+        if (isCustomMarshalled()) return true;
+        return (_super_descriptor != null) && _super_descriptor.isChunked();
+    }
+
+    public Serializable writeReplace(Serializable val) {
         if (_write_replace_method != null) {
             try {
-                return (java.io.Serializable) _write_replace_method.invoke(val,
-                        NO_ARGS);
+                return (Serializable) _write_replace_method.invoke(val);
 
-            } catch (java.lang.IllegalAccessException ex) {
-                throw (MARSHAL)new MARSHAL("cannot call " + _write_replace_method).initCause(ex);
+            } catch (IllegalAccessException ex) {
+                throw (MARSHAL) new MARSHAL("cannot call " + _write_replace_method).initCause(ex);
 
             } catch (IllegalArgumentException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
+                throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
 
             } catch (InvocationTargetException ex) {
-                throw new org.omg.CORBA.portable.UnknownException(ex
-                        .getTargetException());
+                throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
             }
 
         }
@@ -526,21 +450,19 @@
         return val;
     }
 
-    public java.io.Serializable readResolve(java.io.Serializable val) {
+    public Serializable readResolve(Serializable val) {
         if (_read_resolve_method != null) {
             try {
-                return (java.io.Serializable) _read_resolve_method.invoke(val,
-                        NO_ARGS);
+                return (Serializable) _read_resolve_method.invoke(val);
 
-            } catch (java.lang.IllegalAccessException ex) {
-                throw (MARSHAL)new MARSHAL("cannot call " + _read_resolve_method).initCause(ex);
+            } catch (IllegalAccessException ex) {
+                throw (MARSHAL) new MARSHAL("cannot call " + _read_resolve_method).initCause(ex);
 
             } catch (IllegalArgumentException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
+                throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
 
             } catch (InvocationTargetException ex) {
-                throw new org.omg.CORBA.portable.UnknownException(ex
-                        .getTargetException());
+                throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
             }
 
         }
@@ -548,31 +470,28 @@
         return val;
     }
 
-    public void writeValue(final org.omg.CORBA.portable.OutputStream out,
-            final java.io.Serializable value) {
+    public void writeValue(final OutputStream out, final Serializable value) {
         try {
 
-            ObjectWriter writer = (ObjectWriter) java.security.AccessController
-                    .doPrivileged(new java.security.PrivilegedAction() {
-                        public Object run() {
-                            try {
-                                return new CorbaObjectWriter(out, value);
-                            } catch (java.io.IOException ex) {
-                                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
-                            }
-                        }
-                    });
+            ObjectWriter writer = (ObjectWriter) AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    try {
+                        return new CorbaObjectWriter(out, value);
+                    } catch (IOException ex) {
+                        throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
+                    }
+                }
+            });
 
             writeValue(writer, value);
 
-        } catch (java.io.IOException ex) {
-            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
+        } catch (IOException ex) {
+            throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
         }
     }
 
-    protected void defaultWriteValue(ObjectWriter writer,
-            java.io.Serializable val) throws java.io.IOException {
-        logger.finer("writing fields for " + getJavaClass());
+    protected void defaultWriteValue(ObjectWriter writer, Serializable val) throws IOException {
+        logger.finer("writing fields for " + type);
         FieldDescriptor[] fields = _fields;
 
         if (fields == null) {
@@ -580,17 +499,16 @@
         }
 
         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);
         }
     }
 
-    protected void writeValue(ObjectWriter writer, java.io.Serializable val)
-            throws java.io.IOException {
+    protected void writeValue(ObjectWriter writer, Serializable val) throws IOException {
 
         if (_is_externalizable) {
-            writer.invokeWriteExternal((java.io.Externalizable) val);
+            writer.invokeWriteExternal((Externalizable) val);
             return;
         }
 
@@ -602,17 +520,10 @@
 
             try {
                 writer.invokeWriteObject(this, val, _write_object_method);
-
-            } catch (IllegalAccessException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
-
-            } catch (IllegalArgumentException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
-
+            } catch (IllegalAccessException | IllegalArgumentException ex) {
+                throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
             } catch (InvocationTargetException ex) {
-
-                throw new org.omg.CORBA.portable.UnknownException(ex
-                        .getTargetException());
+                throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
             }
 
         } else {
@@ -621,29 +532,23 @@
 
     }
 
-    public java.io.Serializable createBlankInstance() {
+    private Serializable createBlankInstance() {
         if (_constructor != null) {
 
             try {
-                return (java.io.Serializable) _constructor
-                        .newInstance(new Object[0]);
+                return (Serializable) _constructor.newInstance();
 
-            } catch (java.lang.IllegalAccessException ex) {
-                throw (MARSHAL)new MARSHAL("cannot call " + _constructor).initCause(ex);
+            } catch (IllegalAccessException ex) {
+                throw (MARSHAL) new MARSHAL("cannot call " + _constructor).initCause(ex);
 
-            } catch (IllegalArgumentException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
-
-            } catch (InstantiationException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
+            } catch (IllegalArgumentException | InstantiationException ex) {
+                throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
 
             } catch (InvocationTargetException ex) {
-                throw new org.omg.CORBA.portable.UnknownException(ex
-                        .getTargetException());
+                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 " + type.getName(), ex);
                 logger.warning("constructor => " + _constructor);
 
                 throw ex;
@@ -654,50 +559,49 @@
         }
     }
 
-    public java.io.Serializable readValue(
-            final org.omg.CORBA.portable.InputStream in,
-            final java.util.Map offsetMap, final java.lang.Integer offset) {
-        final java.io.Serializable value = createBlankInstance();
+    public Serializable readValue(final InputStream in, final Map<Integer, Object> offsetMap, final Integer offset) {
+        final Serializable value = createBlankInstance();
 
         offsetMap.put(offset, value);
 
         try {
-            ObjectReader reader = (ObjectReader) java.security.AccessController
-                    .doPrivileged(new java.security.PrivilegedAction() {
-                        public Object run() {
-                            try {
-                                return new CorbaObjectReader(in, offsetMap,
-                                        value);
-                            } catch (java.io.IOException ex) {
-                                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
-                            }
-                        }
-                    });
+            ObjectReader reader = (ObjectReader) AccessController.doPrivileged(new PrivilegedAction() {
+                public Object run() {
+                    try {
+                        return new CorbaObjectReader(in, offsetMap, value);
+                    } catch (IOException ex) {
+                        throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
+                    }
+                }
+            });
 
             readValue(reader, value);
 
-            return readResolve(value);
+            final Serializable resolved = readResolve(value);
+            if (value != resolved) {
+                offsetMap.put(offset, resolved);
+            }
+            return resolved;
 
-        } catch (java.io.IOException ex) {
-            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
+        } catch (IOException ex) {
+            throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
         }
 
     }
 
-    void print(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    void print(PrintWriter pw, Map<Object, Integer> recurse, Object val) {
         if (val == null) {
             pw.print("null");
         }
 
-        Integer old = (Integer) recurse.get(val);
+        Integer old = recurse.get(val);
         if (old != null) {
             pw.print("^" + old);
         } else {
-            Integer key = new Integer(System.identityHashCode(val));
+            int key = System.identityHashCode(val);
             recurse.put(val, key);
 
-            pw.println(getJavaClass().getName() + "@"
-                    + Integer.toHexString(key.intValue()) + "[");
+            pw.println(type.getName() + "@" + Integer.toHexString(key) + "[");
 
             printFields(pw, recurse, val);
 
@@ -705,7 +609,7 @@
         }
     }
 
-    void printFields(java.io.PrintWriter pw, java.util.Map recurse, Object val) {
+    void printFields(PrintWriter pw, Map recurse, Object val) {
         pw.print("(" + getClass().getName() + ")");
 
         if (_super_descriptor != null) {
@@ -725,8 +629,7 @@
 
     }
 
-    protected void defaultReadValue(ObjectReader reader,
-            java.io.Serializable value) throws java.io.IOException {
+    protected void defaultReadValue(ObjectReader reader, Serializable value) throws IOException {
         // System.out.println ("defaultReadValue "+getJavaClass());
 
         if (_fields == null) {
@@ -734,63 +637,55 @@
             return;
         }
 
-        logger.fine("reading fields for " + getJavaClass().getName());
+        logger.fine("reading fields for " + type.getName());
 
-        for (int i = 0; i < _fields.length; i++) {
+        for (FieldDescriptor _field : _fields) {
 
-            logger.fine("reading field " + _fields[i].getJavaName() + " of type " + _fields[i].getType().getName() + " using " + _fields[i].getClass().getName());
+            logger.fine("reading field " + _field.java_name + " of type " + _field.getType().getName() + " using " + _field.getClass().getName());
 
             try {
-                _fields[i].read(reader, value);
-            } catch (org.omg.CORBA.MARSHAL ex) {
-                if (ex.getMessage() == null) {
-                    org.omg.CORBA.MARSHAL exx = new org.omg.CORBA.MARSHAL(ex
-                            .getMessage()
-                            + ", while reading "
-                            + getJavaName()
-                            + "."
-                            + _fields[i].getJavaName(), ex.minor, ex.completed);
-                    exx.initCause(ex);
-                    throw exx;
-                } else {
+                _field.read(reader, value);
+            } catch (MARSHAL ex) {
+                if (ex.getMessage() != null)
                     throw ex;
-                }
+
+                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);
             }
         }
     }
 
-    java.util.Map readFields(ObjectReader reader) throws java.io.IOException {
-        if (_fields == null || _fields.length == 0) {
+    Map readFields(ObjectReader reader) throws IOException {
+        if ((_fields == null) || (_fields.length == 0)) {
             return Collections.EMPTY_MAP;
         }
 
-        logger.finer("reading fields for " + getJavaClass().getName());
+        logger.finer("reading fields for " + type.getName());
 
-        java.util.Map map = new HashMap();
+        Map map = new HashMap();
 
-        for (int i = 0; i < _fields.length; i++) {
+        for (FieldDescriptor _field : _fields) {
 
-            logger.finer("reading field " + _fields[i].getJavaName());
+            logger.finer("reading field " + _field.java_name);
 
-            _fields[i].readFieldIntoMap(reader, map);
+            _field.readFieldIntoMap(reader, map);
         }
 
         return map;
     }
 
-    void writeFields(ObjectWriter writer, java.util.Map fieldMap)
-            throws java.io.IOException {
-        if (_fields == null || _fields.length == 0) {
+    void writeFields(ObjectWriter writer, Map fieldMap) throws IOException {
+        if ((_fields == null) || (_fields.length == 0)) {
             return;
         }
 
-        logger.finer("writing fields for " + getJavaClass().getName());
+        logger.finer("writing fields for " + type.getName());
 
-        for (int i = 0; i < _fields.length; i++) {
+        for (FieldDescriptor _field : _fields) {
 
-            logger.finer("writing field " + _fields[i].getJavaName());
+            logger.finer("writing field " + _field.java_name);
 
-            _fields[i].writeFieldFromMap(writer, fieldMap);
+            _field.writeFieldFromMap(writer, fieldMap);
         }
 
     }
@@ -798,17 +693,12 @@
     /**
      * This methods reads the fields of a single class slice.
      */
-    protected void readValue(ObjectReader reader, java.io.Serializable value)
-            throws java.io.IOException {
+    protected void readValue(ObjectReader reader, Serializable value) throws IOException {
         if (_is_externalizable) {
-            java.io.Externalizable ext = (java.io.Externalizable) value;
-
             try {
-                reader.readExternal(ext);
+                reader.readExternal((Externalizable) value);
             } catch (ClassNotFoundException e) {
-                IOException ex = new IOException("cannot instantiate class");
-                ex.initCause(e);
-                throw ex;
+                throw new IOException("cannot instantiate class", e);
             }
             return;
         }
@@ -817,115 +707,112 @@
             _super_descriptor.readValue(reader, value);
         }
 
-        // System.out.println ("readValue "+getJavaClass());
-
-        if (isCustomMarshalled()) {
-
+        // check whether the class (not its ancestors) does any custom marshalling
+        if (_write_object_method != null) {
             // read custom marshalling value header
-            byte streamFormatVersion = reader.readByte();
-            boolean writeDefaultStateCalled = reader.readBoolean();
-            logger.log(Level.FINE, "Reading value in streamFormatVersion=" + streamFormatVersion 
-                    + " IsCalleddefaultWriteObject=" + writeDefaultStateCalled);
+            byte cmsfVersion = reader.readByte(); // custom marshal stream format version
+            boolean dwoCalled = reader.readBoolean(); // was defaultWriteObject() called?
+            logger.log(Level.FINE, "Reading value in streamFormatVersion=" + cmsfVersion + " defaultWriteObject=" + dwoCalled);
+
+            if (cmsfVersion == 2) {
+                // use a wrapped reader to open the secondary custom valuetype
+                ObjectReader wrapper = new CustomMarshaledObjectReader(reader);
+                readSerializable(_read_object_method == null ? reader : wrapper, value);
+                // invoke close to skip to the end of the secondary custom valuetype
+                wrapper.close();
+                return;
+            }
         }
 
+        readSerializable(reader, value);
+
+    }
+
+    private void readSerializable(ObjectReader reader, Serializable value) throws IOException {
         if (_read_object_method != null) {
-
-            // System.out.println ("readValue "+getJavaClass()+" calling
-            // readObject");
-
             try {
                 reader.setCurrentValueDescriptor(this);
-                _read_object_method.invoke(value, new Object[] { reader });
+                _read_object_method.invoke(value, reader);
                 reader.setCurrentValueDescriptor(null);
 
-            } catch (IllegalAccessException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
-            } catch (IllegalArgumentException ex) {
-                throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
+            } catch (IllegalAccessException | IllegalArgumentException ex) {
+                throw (MARSHAL) new MARSHAL(ex.getMessage()).initCause(ex);
             } catch (InvocationTargetException ex) {
-                throw new org.omg.CORBA.portable.UnknownException(ex
-                        .getTargetException());
+                throw (UnknownException) new UnknownException(ex.getTargetException()).initCause(ex.getTargetException());
             }
 
         } else {
             defaultReadValue(reader, value);
         }
-
     }
 
     protected long computeHashCode() {
-        Class type = getJavaClass();
-        long hash = 0L;
+        Class type = this.type;
 
         if (_is_externalizable) {
             return 1L;
+        }
 
-        } else if (!java.io.Serializable.class.isAssignableFrom(type)) {
+        if (!Serializable.class.isAssignableFrom(type)) {
             return 0;
+        }
 
-        } else
-            try {
-                ByteArrayOutputStream barr = new ByteArrayOutputStream(512);
-                MessageDigest md = MessageDigest.getInstance("SHA");
-                DigestOutputStream digestout = new DigestOutputStream(barr, md);
-                DataOutputStream out = new DataOutputStream(digestout);
+        long hash = 0L;
+        try {
+            ByteArrayOutputStream barr = new ByteArrayOutputStream(512);
+            MessageDigest md = MessageDigest.getInstance("SHA");
+            DigestOutputStream digestout = new DigestOutputStream(barr, md);
+            DataOutputStream out = new DataOutputStream(digestout);
 
-                Class superType = type.getSuperclass();
-                if (superType != null) {
-                    TypeDescriptor desc = getTypeRepository().getDescriptor(
-                            superType);
-                    out.writeLong(desc.getHashCode());
-                }
-
-                if (_write_object_method == null)
-                    out.writeInt(1);
-                else
-                    out.writeInt(2);
-
-                FieldDescriptor[] fds = new FieldDescriptor[_fields.length];
-                for (int i = 0; i < _fields.length; i++) {
-                    fds[i] = _fields[i];
-                }
-
-                if (fds.length > 1)
-                    java.util.Arrays.sort(fds, compareByName);
-
-                for (int i = 0; i < fds.length; i++) {
-                    FieldDescriptor f = fds[i];
-                    out.writeUTF(f.getJavaName());
-                    out.writeUTF(makeSignature(f.getType()));
-                }
-
-                /*
-                 * Field[] fields = type.getDeclaredFields ();
-                 * 
-                 * if (fields.length > 1) java.util.Arrays.sort (fields,
-                 * compareByName);
-                 * 
-                 * for(int i = 0; i < fields.length; i++) { Field f = fields[i];
-                 * int mod = f.getModifiers (); if (!Modifier.isTransient(mod) &&
-                 * !Modifier.isStatic (mod)) { out.writeUTF(f.getName());
-                 * out.writeUTF( makeSignature (f.getType ())); } }
-                 */
-
-                out.flush();
-
-                byte data[] = md.digest();
-                int end = Math.min(8, data.length);
-                for (int j = 0; j < end; j++) {
-                    hash += (long) (data[j] & 0xff) << j * 8;
-                }
-            } catch (java.lang.Exception ex) {
-                throw new RuntimeException("cannot compute RMI hash code", ex);
+            Class superType = type.getSuperclass();
+            if (superType != null) {
+                TypeDescriptor desc = repo.getDescriptor(superType);
+                out.writeLong(desc.getHashCode());
             }
 
+            if (_write_object_method == null)
+                out.writeInt(1);
+            else
+                out.writeInt(2);
+
+            FieldDescriptor[] fds = new FieldDescriptor[_fields.length];
+            System.arraycopy(_fields, 0, fds, 0, _fields.length);
+
+            if (fds.length > 1)
+                Arrays.sort(fds, compareByName);
+
+            for (FieldDescriptor f : fds) {
+                out.writeUTF(f.java_name);
+                out.writeUTF(makeSignature(f.getType()));
+            }
+
+            /*
+             * Field[] fields = type.getDeclaredFields (); if (fields.length >
+             * 1) java.util.Arrays.sort (fields, compareByName); for(int i = 0;
+             * i < fields.length; i++) { Field f = fields[i]; int mod =
+             * f.getModifiers (); if (!Modifier.isTransient(mod) &&
+             * !Modifier.isStatic (mod)) { out.writeUTF(f.getName());
+             * out.writeUTF( makeSignature (f.getType ())); } }
+             */
+
+            out.flush();
+
+            byte[] data = md.digest();
+            int end = Math.min(8, data.length);
+            for (int j = 0; j < end; j++) {
+                hash += (long) (data[j] & 0xff) << (j * 8);
+            }
+        } catch (Exception ex) {
+            throw new RuntimeException("cannot compute RMI hash code", ex);
+        }
+
         return hash;
     }
 
-    private static java.util.Comparator compareByName = new java.util.Comparator() {
+    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);
         }
     };
@@ -934,56 +821,68 @@
         return _hash_code;
     }
 
-    protected org.omg.CORBA.ValueMember[] _value_members = null;
+    private volatile ValueMember[] valueMembers = null;
+    protected ValueMember[] genValueMembers() {
+        final ValueMember[] members = new ValueMember[_fields.length];
+        for (int i = 0; i < _fields.length; i++) {
+            members[i] = _fields[i].getValueMember(repo);
+        }
 
-    org.omg.CORBA.ValueMember[] getValueMembers() {
-        if (_value_members == null) {
-            _value_members = new org.omg.CORBA.ValueMember[_fields.length];
-            for (int i = 0; i < _fields.length; i++) {
-                _value_members[i] = _fields[i]
-                        .getValueMember(getTypeRepository());
+        return members;
+    }
+    final ValueMember[] getValueMembers() {
+        getTypeCode(); // ensure recursion through typecode
+        if (null == valueMembers) {
+            synchronized (repo) {
+                if (null == valueMembers) valueMembers = genValueMembers();
             }
         }
-
-        return _value_members;
+        return valueMembers;
     }
 
-    org.omg.CORBA.TypeCode getTypeCode() {
-        if (_type_code != null)
-            return _type_code;
+    @Override
+    protected TypeCode genTypeCode() {
+        ORB orb = ORB.init();
+        setTypeCode(orb.create_recursive_tc(getRepositoryID()));
 
-        org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init();
-        _type_code = orb.create_recursive_tc(getRepositoryID());
+        TypeCode _base = ((_super_descriptor == null) ? null : _super_descriptor.getTypeCode());
 
-        org.omg.CORBA.TypeCode _base = (_super_descriptor == null ? null
-                : _super_descriptor.getTypeCode());
-
-        Class javaClass = getJavaClass();
-        if (!javaClass.isArray()) {
-            _type_code = orb.create_value_tc(getRepositoryID(), javaClass
-                    .getSimpleName(), org.omg.CORBA.VM_NONE.value, _base,
-                    getValueMembers());
+        TypeCode tc;
+        if (type.isArray()) {
+            TypeDescriptor desc = repo.getDescriptor(type.getComponentType());
+            tc = desc.getTypeCode();
+            tc = orb.create_sequence_tc(0, tc);
+            tc = orb.create_value_box_tc(getRepositoryID(), "Sequence", tc);
         } else {
-            TypeDescriptor desc = getTypeRepository().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);
+            tc = orb.create_value_tc(getRepositoryID(), type.getSimpleName(), VM_NONE.value, _base, getValueMembers());
         }
 
-        return _type_code;
+        return tc;
     }
 
-    org.omg.CORBA.ValueDefPackage.FullValueDescription getFullValueDescription() {
-        return new org.omg.CORBA.ValueDefPackage.FullValueDescription(
-                getJavaClass().getName(), getRepositoryID(), false, // is_abstract
-                isCustomMarshalled(), "", "1.0",
-                new org.omg.CORBA.OperationDescription[0],
-                new org.omg.CORBA.AttributeDescription[0],
-                getValueMembers(),
-                new org.omg.CORBA.Initializer[0], new String[0], new String[0],
-                false, // is_truncatable
-                (_super_descriptor == null ? "" : _super_descriptor
-                        .getRepositoryID()), getTypeCode());
+    private static final OperationDescription[] ZERO_OPERATIONS = {};
+    private static final AttributeDescription[] ZERO_ATTRIBUTES = {};
+    private static final Initializer[] ZERO_INITIALIZERS = {};
+    private static final String[] ZERO_STRINGS = {};
+    
+    FullValueDescription getFullValueDescription() {
+        FullValueDescription fvd = new FullValueDescription();
+        fvd.name = type.getName();
+        fvd.id = getRepositoryID();
+        fvd.is_abstract = false;
+        fvd.is_custom = isCustomMarshalled();
+        fvd.defined_in = "";
+        fvd.version = "1.0";
+        fvd.operations = ZERO_OPERATIONS;
+        fvd.attributes = ZERO_ATTRIBUTES;
+        fvd.members = getValueMembers();
+        fvd.initializers = ZERO_INITIALIZERS;
+        fvd.supported_interfaces = ZERO_STRINGS;
+        fvd.abstract_base_values = ZERO_STRINGS;
+        fvd.is_truncatable = false;
+        fvd.base_value = ((_super_descriptor == null) ? "" : _super_descriptor.getRepositoryID());
+        fvd.type = getTypeCode();
+        return fvd;
     }
 
     class ObjectDeserializer {
@@ -992,11 +891,7 @@
 
         String repository_id;
 
-        FieldDescriptor[] fields;
-
-        ValueDescriptor localDescriptor() {
-            return ValueDescriptor.this;
-        }
+        final FieldDescriptor[] fields;
 
         ObjectDeserializer(ValueDescriptor desc) {
             fields = desc._fields;
@@ -1007,32 +902,27 @@
             }
         }
 
-        ObjectDeserializer(FullValueDescription desc,
-                org.omg.SendingContext.RunTime runtime) throws IOException {
-            Class myClass = ValueDescriptor.this.getJavaClass();
+        ObjectDeserializer(FullValueDescription desc, RunTime runtime) throws IOException {
+            Class myClass = type;
             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);
+                Class clz = ValueHandlerImpl.getClassFromRepositoryID(desc.base_value);
+                TypeDescriptor tdesc = repo.getDescriptor(clz);
 
-                if (tdesc != null && tdesc instanceof ValueDescriptor) {
-                    super_descriptor = ((ValueDescriptor) tdesc)
-                            .getObjectDeserializer(desc.base_value, runtime);
+                if ((tdesc instanceof ValueDescriptor)) {
+                    super_descriptor = ((ValueDescriptor) tdesc).getObjectDeserializer(desc.base_value, runtime);
                 }
             }
         }
     }
 
-    ObjectDeserializer getObjectDeserializer(String repositoryID,
-            org.omg.SendingContext.RunTime runtime) throws java.io.IOException {
+    private ObjectDeserializer getObjectDeserializer(String repositoryID, RunTime runtime) throws IOException {
         if (repositoryID.equals(getRepositoryID())) {
             return _object_deserializer;
         }
@@ -1047,7 +937,7 @@
         return new ObjectDeserializer(desc, codebase);
     }
 
-    static Class getClassFromTypeCode(TypeCode tc) {
+    private static Class getClassFromTypeCode(TypeCode tc) {
         return null;
     }
 
@@ -1061,21 +951,19 @@
             return orig;
         }
 
-        java.io.Serializable oorig = (java.io.Serializable) orig;
+        Serializable oorig = (Serializable) orig;
 
         logger.finer("copying " + orig);
 
         oorig = writeReplace(oorig);
 
         ValueDescriptor wdesc;
-        if (oorig != orig) {
-            wdesc = (ValueDescriptor) getTypeRepository().getDescriptor(
-                    oorig.getClass());
-
-            logger.finer("writeReplace -> " + getJavaClass().getName());
-
-        } else {
+        if (oorig == orig) {
             wdesc = this;
+        } else {
+            wdesc = (ValueDescriptor) repo.getDescriptor(oorig.getClass());
+
+            logger.finer("writeReplace -> " + type.getName());
         }
 
         return wdesc.copyObject2(oorig, state);
@@ -1085,7 +973,7 @@
      * this is called after write-replace on the type descriptor of the correct
      * type for writing
      */
-    Serializable copyObject2(Serializable oorig, CopyState state) {
+    private Serializable copyObject2(Serializable oorig, CopyState state) {
 
         // create instance of copied object, and register
         Serializable copy = createBlankInstance();
@@ -1098,41 +986,29 @@
         return readObject(writer, copy);
     }
 
-    ObjectWriter writeObject(java.io.Serializable oorig, CopyState state) {
-
-        ObjectWriter writer = null;
-
+    private ObjectWriter writeObject(Serializable oorig, CopyState state) {
         try {
-
-            writer = state.createObjectWriter(oorig);
+            ObjectWriter writer = state.createObjectWriter(oorig);
             writeValue(writer, oorig);
-
             return writer;
-
-        } catch (java.io.IOException ex) {
-            throw (MARSHAL)new MARSHAL(ex.getMessage()).initCause(ex);
+        } catch (IOException ex) {
+            String msg = String.format("%s writing %s", ex, type.getName());
+            throw (MARSHAL) new MARSHAL(msg).initCause(ex);
         }
     }
 
-    java.io.Serializable readObject(ObjectWriter writer,
-            java.io.Serializable copy) {
-
-        ObjectReader reader = writer.getObjectReader(copy);
-
+    private Serializable readObject(ObjectWriter writer, Serializable copy) {
         try {
+            ObjectReader reader = writer.getObjectReader(copy);
             readValue(reader, copy);
-        } catch (java.io.IOException ex) {
-            MARSHAL m = new MARSHAL(ex.getMessage() + " reading instance of "
-                    + getJavaClass().getName());
-            m.initCause(ex);
-            throw m;
+            return readResolve(copy);
+        } catch (IOException ex) {
+            String msg = String.format("%s reading instance of %s", ex, type.getName());
+            throw (MARSHAL) new MARSHAL(msg).initCause(ex);
         }
-
-        return readResolve(copy);
     }
 
-    void writeMarshalValue(java.io.PrintWriter pw, String outName,
-            String paramName) {
+    void writeMarshalValue(PrintWriter pw, String outName, String paramName) {
         pw.print(outName);
         pw.print('.');
         pw.print("write_value");
@@ -1146,46 +1022,45 @@
 
         pw.print(paramName);
         pw.print(',');
-        MethodDescriptor.writeJavaType(pw, getJavaClass());
+        MethodDescriptor.writeJavaType(pw, type);
         pw.print(".class)");
     }
 
-    void writeUnmarshalValue(java.io.PrintWriter pw, String inName) {
+    void writeUnmarshalValue(PrintWriter pw, String inName) {
         pw.print(inName);
         pw.print('.');
         pw.print("read_value");
         pw.print('(');
-        MethodDescriptor.writeJavaType(pw, getJavaClass());
+        MethodDescriptor.writeJavaType(pw, type);
         pw.print(".class)");
     }
 
-    void addDependencies(java.util.Set classes) {
-        Class c = getJavaClass();
+    @Override
+    void addDependencies(Set<Class<?>> classes) {
+        Class c = type;
 
-        if (c == java.lang.Object.class || classes.contains(c))
+        if ((c == Object.class) || classes.contains(c))
             return;
 
         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]);
+        for (Class iface : ifaces) {
+            TypeDescriptor desc = repo.getDescriptor(iface);
             desc.addDependencies(classes);
         }
 
         if (_fields != null) {
-            for (int i = 0; i < _fields.length; i++) {
-                if (_fields[i].isPrimitive())
+            for (FieldDescriptor _field : _fields) {
+                if (_field.isPrimitive())
                     continue;
 
-                TypeDescriptor desc = getTypeRepository().getDescriptor(
-                        _fields[i].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 01189c9..8a8bd23 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;
 
@@ -34,26 +33,34 @@
     static final Logger logger = Logger.getLogger(ValueHandlerImpl.class
             .getName());
 
-    TypeRepository repository;
+    private final TypeRepository repo;
 
     RunTimeCodeBaseImpl codeBase;
 
-    private TypeRepository getRepository() {
-        return RMIState.current().getTypeRepository(); // repository;
+    private ValueHandlerImpl() {
+        this.repo = TypeRepository.get();
     }
 
-    ValueHandlerImpl(TypeRepository rep) {
-        this.repository = rep;
+    private static enum HandlerHolder {
+        ;
+        static final ValueHandlerImpl value = new ValueHandlerImpl();
+    }
+
+    public static ValueHandlerImpl get() {
+        return HandlerHolder.value;
     }
 
     private ValueDescriptor desc(Class clz) {
-        return (ValueDescriptor) getRepository().getDescriptor(clz);
+        return (ValueDescriptor) repo.getDescriptor(clz);
+    }
+
+    private ValueDescriptor desc(String repId) {
+        return (ValueDescriptor) repo.getDescriptor(repId);
     }
 
     private ValueDescriptor desc(Class clz, String repid, RunTime runtime) {
         try {
-            return (ValueDescriptor) getRepository().getDescriptor(clz, repid,
-                    runtime);
+            return repo.getDescriptor(clz, repid, runtime);
         } catch (ClassNotFoundException ex) {
             MARSHAL m = new MARSHAL("class not found " + ex.getMessage());
             m.initCause(ex);
@@ -124,11 +131,12 @@
     }
 
     public java.lang.String getRMIRepositoryID(java.lang.Class clz) {
-        return getRepository().getDescriptor(clz).getRepositoryID();
+        return repo.getDescriptor(clz).getRepositoryID();
     }
 
+    @Override
     public boolean isCustomMarshaled(java.lang.Class clz) {
-        return desc(clz).isCustomMarshalled();
+        return desc(clz).isChunked();
     }
 
     public synchronized org.omg.SendingContext.RunTime getRunTimeCodeBase() {
@@ -168,7 +176,7 @@
         if (val instanceof RMIStub) {
 
             RMIStub stub = (RMIStub) val;
-            Class type = stub._descriptor.getJavaClass();
+            Class type = stub._descriptor.type;
 
             RMIState state = RMIState.current();
             Stub result = state.getStaticStub(stub._get_codebase(), type);
@@ -263,25 +271,23 @@
         return result;
     }
 
-    FullValueDescription meta(String id) {
+    FullValueDescription meta(String repId) {
+        if (logger.isLoggable(Level.FINER))
+            logger.finer(String.format("meta \"%s\"", repId));
         try {
-            // System.out.println ("ValueHandlerImpl::meta "+id);
+            ValueDescriptor desc = desc(repId);
+            if (null == desc) {
+                Class clz = getClassFromRepositoryID(repId);
 
-            Class clz = getClassFromRepositoryID(id);
+                if (clz == null) {
+                    logger.warning("class not found: " + repId);
+                    throw new org.omg.CORBA.MARSHAL(0x4f4d0001,
+                            CompletionStatus.COMPLETED_MAYBE);
+                }
 
-            if (clz == null) {
-                logger.warning("class not found: " + id);
-                throw new org.omg.CORBA.MARSHAL(0x4f4d0001,
-                        CompletionStatus.COMPLETED_MAYBE);
+                desc = desc(clz);
             }
 
-            if (logger.isLoggable(Level.FINER)) {
-                logger.finer("meta " + id);
-            }
-
-            ValueDescriptor desc = (ValueDescriptor) getRepository()
-                    .getDescriptor(clz);
-
             return desc.getFullValueDescription();
         } catch (Throwable ex) {
             logger.log(Level.WARNING, "exception in meta", ex);
@@ -329,7 +335,7 @@
     }
 
     private void addIfRMIClass(java.util.List list, Class clz) {
-        TypeDescriptor desc = getRepository().getDescriptor(clz);
+        TypeDescriptor desc = repo.getDescriptor(clz);
 
         if (desc instanceof RemoteDescriptor)
             list.add(desc);
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-rmi-impl/src/main/java/org/apache/yoko/rmi/osgi/activator/Activator.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/osgi/activator/Activator.java
new file mode 100644
index 0000000..573112f
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/osgi/activator/Activator.java
@@ -0,0 +1,46 @@
+package org.apache.yoko.rmi.osgi.activator;
+
+import javax.rmi.CORBA.Stub;
+
+import org.apache.yoko.osgi.locator.ProviderRegistryImpl;
+import org.apache.yoko.osgi.locator.Register;
+import org.apache.yoko.osgi.locator.activator.AbstractBundleActivator;
+import org.omg.stub.java.rmi._Remote_Stub;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+
+public class Activator extends AbstractBundleActivator {
+
+    private ServiceRegistration<Register> sr;
+    private ProviderRegistryImpl register;
+    
+    public Activator() {
+        super(new Info[] {
+                   new Info(_Remote_Stub.class.getName(), _Remote_Stub.class.getName(), 1),
+                   new Info(Stub.class.getName(), Stub.class.getName(), 1)
+               }, 
+               new Info[] {
+                   new Info("javax.rmi.CORBA.PortableRemoteObjectClass", "org.apache.yoko.rmi.impl.PortableRemoteObjectImpl", 1),
+                   new Info("javax.rmi.CORBA.UtilClass", "org.apache.yoko.rmi.impl.UtilImpl", 1),
+                   new Info("org.apache.yoko.rmi.PortableRemoteObjectExtClass", "org.apache.yoko.rmi.impl.PortableRemoteObjectExtImpl", 1),
+                   new Info("org.apache.yoko.rmi.RMIStubInitializerClass", "org.apache.yoko.rmi.impl.RMIStubInitializer", 1),
+                   new Info("javax.rmi.CORBA.StubClass", "org.apache.yoko.rmi.impl.StubImpl", 1)
+               });
+    }
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        register = new ProviderRegistryImpl();
+        register.start();
+        sr = context.registerService(Register.class, register, null);
+        super.start(context);
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        super.stop(context);
+        sr.unregister();
+        register.stop();
+    }
+    
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/DynamicHashMap.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/DynamicHashMap.java
deleted file mode 100755
index 945fe73..0000000
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/DynamicHashMap.java
+++ /dev/null
@@ -1,261 +0,0 @@
-/**
-*
-* 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.util;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-/**
- * Class <code>DynamicHashMap</code> is a generic dynamic hash map.
- */
-public class DynamicHashMap extends GenericMap implements Map {
-    class Entry extends GenericMap.Entry {
-        Entry next;
-
-        int hash;
-
-        Object key;
-
-        Object value;
-
-        Entry(int hash, Object key, Object value, Entry next) {
-            this.hash = hash;
-            this.key = key;
-            this.value = value;
-            this.next = next;
-        }
-
-        public Object getKey() {
-            return key;
-        }
-
-        public Object getValue() {
-            return value;
-        }
-
-        public Object setValue(Object value) {
-            Object result = this.value;
-            this.value = value;
-            return result;
-        }
-
-        boolean sameKey(int hash, Object key) {
-            return this.hash == hash && keyEquals(this.key, key);
-        }
-    }
-
-    /** the hash index */
-    private Entry[] table;
-
-    /** the current range for table. */
-    private int range;
-
-    private float ratio;
-
-    /** translate hash code bucket to index */
-    private int index(int hash) {
-        return (hash & 0x7ffffff) % range;
-    }
-
-    /** the default and only constructor */
-    public DynamicHashMap() {
-        clear();
-    }
-
-    public void clear() {
-        range = 3;
-        size = 0;
-        ratio = 0.75F;
-        table = new Entry[range];
-    }
-
-    /** return the element with the given key */
-    public Object get(Object key) {
-        int hash = keyHash(key);
-        return get(hash, key);
-    }
-
-    public Object get(int hash, Object key) {
-        int idx = index(hash);
-
-        for (Entry ent = table[idx]; ent != null; ent = ent.next) {
-            if (ent.sameKey(hash, key))
-                return ent.value;
-        }
-
-        return null;
-    }
-
-    /** return the element with the given key */
-    public boolean containsKey(Object key) {
-        int hash = keyHash(key);
-        return containsKey(hash, key);
-    }
-
-    public boolean containsKey(int hash, Object key) {
-        int idx = index(hash);
-
-        for (Entry ent = table[idx]; ent != null; ent = ent.next) {
-            if (ent.sameKey(hash, key))
-                return true;
-        }
-
-        return false;
-    }
-
-    public Object put(Object key, Object value) {
-        int hash = keyHash(key);
-        return put(hash, key, value);
-    }
-
-    public Object put(int hash, Object key, Object value) {
-        int idx = index(hash);
-
-        for (Entry ent = table[idx]; ent != null; ent = ent.next) {
-            if (ent.sameKey(hash, key)) {
-                return ent.setValue(value);
-            }
-        }
-
-        if (1.0F * size / range > ratio) {
-            grow();
-            idx = index(hash);
-        }
-
-        table[idx] = new Entry(hash, key, value, table[idx]);
-
-        size += 1;
-
-        return null;
-    }
-
-    public Object remove(Object key) {
-        int hash = keyHash(key);
-        return remove(hash, key);
-    }
-
-    public Object remove(int hash, Object key) {
-        int idx = index(hash);
-
-        Entry entry = table[idx];
-        if (entry != null) {
-
-            if (entry.sameKey(hash, key)) {
-                table[idx] = entry.next;
-                size -= 1;
-                return entry.getValue();
-
-            } else {
-                Entry ahead = entry.next;
-
-                while (ahead != null) {
-                    if (ahead.sameKey(hash, key)) {
-                        entry.next = ahead.next;
-                        size -= 1;
-                        return ahead.getValue();
-                    }
-
-                    entry = ahead;
-                    ahead = ahead.next;
-                }
-            }
-        }
-
-        // it was not found at all!
-        return null;
-    }
-
-    private void grow() {
-        int old_range = range;
-        Entry[] old_table = table;
-
-        range = old_range * 2 + 1;
-        table = new Entry[range];
-
-        for (int i = 0; i < old_range; i++) {
-            Entry entry = old_table[i];
-
-            while (entry != null) {
-                Entry ahead = entry.next;
-                int idx = index(entry.hash);
-                entry.next = table[idx];
-                table[idx] = entry;
-                entry = ahead;
-            }
-        }
-    }
-
-    final class EntryIterator implements Iterator {
-        int idx;
-
-        Entry entry;
-
-        EntryIterator() {
-            idx = 0;
-            entry = table[0];
-            locateNext();
-        }
-
-        private void locateNext() {
-            // we reached the end of a list
-            while (entry == null) {
-                // goto next bucket
-                idx += 1;
-                if (idx == range) {
-                    // we reached the end
-                    return;
-                }
-
-                // entry is the first element of this bucket
-                entry = table[idx];
-            }
-        }
-
-        public boolean hasNext() {
-            return (entry != null);
-        }
-
-        public Object next() {
-            Object result = entry;
-
-            if (result == null) {
-                throw new NoSuchElementException();
-            } else {
-                entry = entry.next;
-                locateNext();
-                return result;
-            }
-        }
-
-        public void remove() {
-            Entry remove = entry;
-
-            entry = entry.next;
-            locateNext();
-
-            DynamicHashMap.this.remove(remove.key);
-        }
-    }
-
-    protected Iterator entryIterator() {
-        return new EntryIterator();
-    }
-
-}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/GenericMap.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/GenericMap.java
deleted file mode 100755
index b97648b..0000000
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/GenericMap.java
+++ /dev/null
@@ -1,257 +0,0 @@
-/**
-*
-* 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.util;
-
-import java.util.AbstractCollection;
-import java.util.AbstractSet;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-
-abstract class GenericMap implements Map {
-    protected int size;
-
-    public int size() {
-        return size;
-    }
-
-    public boolean isEmpty() {
-        return size() == 0;
-    }
-
-    protected int keyHash(Object key) {
-        if (key == null)
-            return 0;
-        else
-            return key.hashCode();
-    }
-
-    protected boolean keyEquals(Object key1, Object key2) {
-        if (key1 == null)
-            return key2 == null;
-        else
-            return key1.equals(key2);
-    }
-
-    protected int valueHash(Object value) {
-        if (value == null)
-            return 0;
-        else
-            return value.hashCode();
-    }
-
-    protected boolean valueEquals(Object value1, Object value2) {
-        if (value1 == null)
-            return value2 == null;
-        else
-            return value1.equals(value2);
-    }
-
-    abstract class Entry implements Map.Entry {
-        public int hashCode() {
-            return keyHash(getKey()) ^ valueHash(getValue());
-        }
-
-        public boolean equals(Object other) {
-            if (other instanceof Map.Entry) {
-                Map.Entry ent = (Map.Entry) other;
-                return keyEquals(getKey(), ent.getKey())
-                        && valueEquals(getValue(), ent.getValue());
-            } else {
-                return false;
-            }
-        }
-
-    }
-
-    public void putAll(Map other) {
-        if (other == this)
-            return;
-
-        Iterator it = other.entrySet().iterator();
-        while (it.hasNext()) {
-            Map.Entry entry = (Map.Entry) it.next();
-            put(entry.getKey(), entry.getValue());
-        }
-    }
-
-    protected abstract Iterator entryIterator();
-
-    protected Iterator keyIterator() {
-        return new KeyIterator();
-    }
-
-    protected Iterator valueIterator() {
-        return new ValueIterator();
-    }
-
-    abstract class KeyOrValueIterator implements Iterator {
-        Iterator iter = entryIterator();
-
-        public boolean hasNext() {
-            return iter.hasNext();
-        }
-
-        protected Map.Entry nextEntry() {
-            return (Map.Entry) iter.next();
-        }
-
-        public void remove() {
-            throw new UnsupportedOperationException();
-        }
-
-    }
-
-    class KeyIterator extends KeyOrValueIterator {
-        public Object next() {
-            return nextEntry().getKey();
-        }
-    }
-
-    class ValueIterator extends KeyOrValueIterator {
-        public Object next() {
-            return nextEntry().getValue();
-        }
-    }
-
-    /**
-     * I don't quite understand why we need to replace this method from
-     * AbstractCollection, but it has been observed that toArray returns the
-     * *reverse* order of elements. --Kresten
-     */
-
-    private static Object[] toArray(Object[] arr, int size, Iterator it) {
-        Object[] out = null;
-
-        if (arr != null && arr.length >= size) {
-            out = arr;
-        } else if (arr == null) {
-            out = new Object[size];
-        } else {
-            out = (Object[]) java.lang.reflect.Array.newInstance(arr.getClass()
-                    .getComponentType(), size);
-        }
-
-        for (int i = 0; i < size; i++) {
-            out[i] = it.next();
-        }
-
-        if (out.length > size)
-            out[size] = null;
-
-        return out;
-    }
-
-    public Collection values() {
-        return new AbstractCollection() {
-            public Iterator iterator() {
-                return valueIterator();
-            }
-
-            public int size() {
-                return GenericMap.this.size();
-            }
-
-            public Object[] toArray(Object[] arr) {
-                return GenericMap.toArray(arr, size(), iterator());
-            }
-        };
-    }
-
-    public Set keySet() {
-        return new AbstractSet() {
-            public Iterator iterator() {
-                return keyIterator();
-            }
-
-            public int size() {
-                return GenericMap.this.size();
-            }
-
-            public Object[] toArray(Object[] arr) {
-                return GenericMap.toArray(arr, size(), iterator());
-            }
-        };
-    }
-
-    public int hashCode() {
-        int code = 0;
-        Iterator it = entryIterator();
-        while (it.hasNext()) {
-            code += it.next().hashCode();
-        }
-        return code;
-    }
-
-    public boolean equals(Object other) {
-        if (other instanceof Map) {
-            Map map = (Map) other;
-
-            if (map.size() != size())
-                return false;
-
-            Iterator it = entryIterator();
-            while (it.hasNext()) {
-                Entry ent = (Entry) it.next();
-                Object key = ent.getKey();
-                Object val = ent.getValue();
-
-                if (map.containsKey(key)) {
-                    Object otherVal = map.get(key);
-                    if (!valueEquals(val, otherVal))
-                        return false;
-                }
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public Set entrySet() {
-        return new AbstractSet() {
-            public Iterator iterator() {
-                return entryIterator();
-            }
-
-            public int size() {
-                return size;
-            }
-
-            public Object[] toArray(Object[] arr) {
-                return GenericMap.toArray(arr, size(), iterator());
-            }
-        };
-    }
-
-    /** return the element with the given key */
-    public boolean containsValue(Object value) {
-        Iterator it = valueIterator();
-        while (it.hasNext()) {
-            if (valueEquals(value, it.next()))
-                return true;
-        }
-        return false;
-    }
-
-    public boolean containsKey(Object key) {
-        return get(key) != null;
-    }
-
-}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/GetSystemPropertyAction.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/GetSystemPropertyAction.java
index 5b74119..4281243 100644
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/GetSystemPropertyAction.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/GetSystemPropertyAction.java
@@ -23,7 +23,7 @@
  * Simple utility class for retrieving a system property
  * value using the AccessController.
  */
-public class GetSystemPropertyAction implements PrivilegedAction {
+public class GetSystemPropertyAction implements PrivilegedAction<String> {
     // property name to retrieve
     String name;
     // potential default value
@@ -57,7 +57,7 @@
      * @return The retrieved property.  Returns either null or the
      *         specified default value if this has not been set.
      */
-    public java.lang.Object run() {
+    public String run() {
         if (defaultValue == null) {
             return System.getProperty(name);
         }
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/Key.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/Key.java
new file mode 100644
index 0000000..456e9b0
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/Key.java
@@ -0,0 +1,5 @@
+package org.apache.yoko.rmi.util;
+
+interface Key<T> {
+    T get();
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/SearchKey.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/SearchKey.java
new file mode 100644
index 0000000..1661182
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/SearchKey.java
@@ -0,0 +1,28 @@
+package org.apache.yoko.rmi.util;
+
+public class SearchKey<T> implements Key<T> {
+    private final T value;
+    private final int hash;
+
+    public SearchKey(T value) {
+        this.value = value;
+        hash = value.hashCode();
+    }
+
+    @Override
+    public T get() {
+        return value;
+    }
+
+    @Override
+    public int hashCode() {
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!!!(o instanceof Key)) return false;
+        return value.equals(((Key)o).get());
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/WeakKey.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/WeakKey.java
new file mode 100644
index 0000000..07f66bd
--- /dev/null
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/WeakKey.java
@@ -0,0 +1,27 @@
+package org.apache.yoko.rmi.util;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+public class WeakKey<T> extends WeakReference<T> implements Key<T> {
+    private final int hash;
+
+    public WeakKey(T r, ReferenceQueue<T> q) {
+        super(r, q);
+        hash = r.hashCode();
+    }
+
+    @Override
+    public int hashCode() {
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (!!!(o instanceof Key)) return false;
+        final Object otherKey = ((Key<?>)o).get();
+        if (null == otherKey) return false;
+        return otherKey.equals(get());
+    }
+}
diff --git a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/stub/StubClass.java b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/stub/StubClass.java
index f5f3559..4f270b5 100755
--- a/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/stub/StubClass.java
+++ b/yoko-rmi-impl/src/main/java/org/apache/yoko/rmi/util/stub/StubClass.java
@@ -246,7 +246,7 @@
                 } catch (InstantiationException ex) {
                     logger.log(Level.WARNING, "", ex);
                 } catch (InvocationTargetException ex) {
-                    logger.log(Level.WARNING, "", ex);
+                    logger.log(Level.WARNING, "", ex.getCause());
                 } catch (IllegalAccessException ex) {
                     logger.log(Level.WARNING, "", ex);
                 }
diff --git a/yoko-rmi-impl/src/main/resources/OSGI-INF/blueprint/provider.xml b/yoko-rmi-impl/src/main/resources/OSGI-INF/blueprint/provider.xml
deleted file mode 100644
index 2842534..0000000
--- a/yoko-rmi-impl/src/main/resources/OSGI-INF/blueprint/provider.xml
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-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.
--->
-<!--
-
-  blueprint configuration for jndi providers
-  -->
-
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
-    <service id="yokoRegister"
-             interface="org.apache.yoko.osgi.locator.Register"
-             activation="eager">
-        <ref component-id="yokoRegistryBean"/>
-    </service>
-    <bean id="yokoRegistryBean"
-          class="org.apache.yoko.osgi.locator.ProviderRegistryImpl"
-          init-method="start"
-          destroy-method="stop"
-          activation="eager"/>
-
-    <bean class="org.apache.yoko.osgi.locator.ProviderBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>javax.rmi.CORBA.UtilClass</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.rmi.impl.UtilImpl</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="yokoRegistryBean"/>
-        </argument>
-    </bean>
-    <bean class="org.apache.yoko.osgi.locator.ServiceBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>javax.rmi.CORBA.PortableRemoteObjectClass</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.rmi.impl.PortableRemoteObjectImpl</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="yokoRegistryBean"/>
-        </argument>
-    </bean>
-    <bean class="org.apache.yoko.osgi.locator.ServiceBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>org.apache.yoko.rmi.PortableRemoteObjectExtClass</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.rmi.impl.PortableRemoteObjectExtImpl</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="yokoRegistryBean"/>
-        </argument>
-    </bean>
-    <bean class="org.apache.yoko.osgi.locator.ServiceBean"
-          activation="eager"
-          init-method="start"
-          destroy-method="stop">
-        <argument>
-            <value>javax.rmi.CORBA.StubClass</value>
-        </argument>
-        <argument>
-            <value>org.apache.yoko.rmi.impl.StubImpl</value>
-        </argument>
-        <argument>
-            <ref component-id="blueprintBundle"/>
-        </argument>
-        <argument>
-            <ref component-id="yokoRegistryBean"/>
-        </argument>
-    </bean>
-
-
-</blueprint>
\ No newline at end of file
diff --git a/yoko-rmi-spec/pom.xml b/yoko-rmi-spec/pom.xml
index 4b7ad1c..4506f7b 100644
--- a/yoko-rmi-spec/pom.xml
+++ b/yoko-rmi-spec/pom.xml
@@ -35,10 +35,33 @@
             <artifactId>yoko-spec-corba</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.apache.yoko</groupId>
+            <artifactId>yoko-osgi</artifactId>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
         </dependency>
     </dependencies>
+    <build>
+        <!--<sourceDirectory>${basedir}/src/main/generated-sources/idl</sourceDirectory>-->
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.yoko.rmispec.util;version=1.0, 
+                            javax.rmi.*;version=2.4,
+                            org.omg.stub.java.rmi;version=2.4
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
 
 </project>
diff --git a/yoko-rmi-spec/src/main/java/javax/rmi/CORBA/UtilDelegate.java b/yoko-rmi-spec/src/main/java/javax/rmi/CORBA/UtilDelegate.java
index 0c903e5..c90f4d9 100644
--- a/yoko-rmi-spec/src/main/java/javax/rmi/CORBA/UtilDelegate.java
+++ b/yoko-rmi-spec/src/main/java/javax/rmi/CORBA/UtilDelegate.java
@@ -20,6 +20,7 @@
 import java.rmi.Remote;
 import java.rmi.RemoteException;
 import java.rmi.NoSuchObjectException;
+
 import org.omg.CORBA.ORB;
 import org.omg.CORBA.SystemException;
 import org.omg.CORBA.portable.InputStream;
@@ -29,9 +30,10 @@
     Object copyObject(Object o, ORB orb) throws RemoteException;
     Object[] copyObjects(Object[] objs, ORB orb) throws RemoteException;
     ValueHandler createValueHandler();
-    String getCodebase(Class clz);
+    String getCodebase(@SuppressWarnings("rawtypes") Class clz);
     Tie getTie(Remote t);
     boolean isLocal(Stub s) throws RemoteException;
+    @SuppressWarnings("rawtypes")
     Class loadClass(String name, String codebase, ClassLoader loader) throws ClassNotFoundException;
     RemoteException mapSystemException(SystemException e);
     Object readAny(InputStream is);
diff --git a/yoko-rmi-spec/src/main/java/org/apache/yoko/rmispec/util/UtilLoader.java b/yoko-rmi-spec/src/main/java/org/apache/yoko/rmispec/util/UtilLoader.java
index 1bbcb5c..cbcd57d 100644
--- a/yoko-rmi-spec/src/main/java/org/apache/yoko/rmispec/util/UtilLoader.java
+++ b/yoko-rmi-spec/src/main/java/org/apache/yoko/rmispec/util/UtilLoader.java
@@ -36,24 +36,24 @@
     // since that method will call loadClass0 which uses this field... if it is below the static
     // initializer the _secman field will be null
     private static final SecMan _secman = getSecMan();
-    
+
     static public Class<?> loadServiceClass(String delegateName, String delegateKey) throws ClassNotFoundException {
-    	
-    	try {
-    		Class<?> cls = ProviderLocator.getServiceClass(delegateKey, null, null);
+
+        try {
+            Class<?> cls = ProviderLocator.getServiceClass(delegateKey, null, null);
             if (cls != null) {
                 return cls;
             }
-    	} catch (ClassNotFoundException e){
-    		// skip
-    	}
-    	
-    	return loadClass0(delegateName, null, null);
+        } catch (ClassNotFoundException e){
+            // skip
+        }
+
+        return loadClass0(delegateName, null, null);
     }
 
     static public Class loadClass(String name, String codebase, ClassLoader loader)
             throws ClassNotFoundException {
-        
+
 
         try {
             return ProviderLocator.loadClass(name, null, loader);
@@ -63,12 +63,12 @@
 
         return loadClass0(name, codebase, loader);
     }
-    
+
     private static Class<?> loadClass0(String name, String codebase, ClassLoader loader) 
-    	throws ClassNotFoundException {
-    	Class result = null;
-    	
-    	ClassLoader stackLoader = null;
+            throws ClassNotFoundException {
+        Class result = null;
+
+        ClassLoader stackLoader = null;
         ClassLoader thisLoader = UtilLoader.class.getClassLoader(); 
         Class[] stack = _secman.getClassContext();
         for (int i = 1; i < stack.length; i++) {
@@ -170,11 +170,13 @@
             loader = getContextClassLoader();
         }
 
-        try {
-            logger.finer("trying local loader");
-            result = loader.loadClass(name);
-        } catch (ClassNotFoundException ex) {
-            logger.log(Level.FINER, "LocalLoader says " + ex.getMessage(), ex);
+        if (loader != null) { 
+            try {
+                logger.finer("trying local loader");
+                result = loader.loadClass(name);
+            } catch (ClassNotFoundException ex) {
+                logger.log(Level.FINER, "LocalLoader says " + ex.getMessage(), ex);
+            }
         }
 
         if (result != null) {
diff --git a/yoko-rmi-spec/src/main/java/org/omg/stub/java/rmi/_Remote_Stub.java b/yoko-rmi-spec/src/main/java/org/omg/stub/java/rmi/_Remote_Stub.java
new file mode 100644
index 0000000..bea03f5
--- /dev/null
+++ b/yoko-rmi-spec/src/main/java/org/omg/stub/java/rmi/_Remote_Stub.java
@@ -0,0 +1,12 @@
+package org.omg.stub.java.rmi;
+
+import javax.rmi.CORBA.Stub;
+import java.rmi.Remote;
+
+public class _Remote_Stub extends Stub implements Remote {
+    private static final String[] _type_ids = {};
+
+    public String[] _ids() {
+        return _type_ids;
+    }
+}
diff --git a/yoko-spec-corba/pom.xml b/yoko-spec-corba/pom.xml
index b167be8..cb2f75d 100755
--- a/yoko-spec-corba/pom.xml
+++ b/yoko-spec-corba/pom.xml
@@ -30,6 +30,11 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.apache.yoko</groupId>
+            <artifactId>yoko-osgi</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>
@@ -39,6 +44,18 @@
         <!--<sourceDirectory>${basedir}/src/main/generated-sources/idl</sourceDirectory>-->
         <plugins>
             <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.omg.*;version=2.4,
+                            org.apache.*;version=1.0
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
                 <groupId>org.codehaus.mojo</groupId>
                 <artifactId>build-helper-maven-plugin</artifactId>
                 <executions>
diff --git a/yoko-spec-corba/src/main/generated-sources/idl/org/omg/CosNaming/NameComponent.java b/yoko-spec-corba/src/main/generated-sources/idl/org/omg/CosNaming/NameComponent.java
index 8266985..6cb61a3 100644
--- a/yoko-spec-corba/src/main/generated-sources/idl/org/omg/CosNaming/NameComponent.java
+++ b/yoko-spec-corba/src/main/generated-sources/idl/org/omg/CosNaming/NameComponent.java
@@ -1,26 +1,32 @@
 package org.omg.CosNaming;
 
-
 /**
-* org/omg/CosNaming/NameComponent.java .
-* Error reading Messages File.
-* Error reading Messages File.
-* Thursday, January 14, 2010 1:08:58 AM PST
-*/
+ * org/omg/CosNaming/NameComponent.java . Error reading Messages File. Error
+ * reading Messages File. Thursday, January 14, 2010 1:08:58 AM PST
+ */
 
-public final class NameComponent implements org.omg.CORBA.portable.IDLEntity
-{
-  public String id = null;
-  public String kind = null;
+public final class NameComponent implements org.omg.CORBA.portable.IDLEntity {
+    private static final long serialVersionUID = -1052538183391762390L;
+    public String id = null;
+    public String kind = null;
 
-  public NameComponent ()
-  {
-  } // ctor
+    public NameComponent() {
+    }
 
-  public NameComponent (String _id, String _kind)
-  {
-    id = _id;
-    kind = _kind;
-  } // ctor
+    public NameComponent(String _id, String _kind) {
+        id = _id;
+        kind = _kind;
+    }
 
-} // class NameComponent
+    @Override
+    public String toString() {
+        final String eid = escape(id);
+        return ((!!!"".equals(eid)) && "".equals(kind)) ? eid : (eid + '.' + escape(kind));
+    }
+    
+    /** escape DOT, SLASH, and BACKSLASH as per CosNaming v1.4 section 2.4.2 */
+    private static String escape(String s) {
+        if (s == null) return s;
+        return s.replaceAll("([\\\\\\./])", "\\\\$1");
+    }
+}
diff --git a/yoko-spec-corba/src/main/java/org/omg/CORBA/portable/UnknownException.java b/yoko-spec-corba/src/main/java/org/omg/CORBA/portable/UnknownException.java
index 5783bb6..057319b 100755
--- a/yoko-spec-corba/src/main/java/org/omg/CORBA/portable/UnknownException.java
+++ b/yoko-spec-corba/src/main/java/org/omg/CORBA/portable/UnknownException.java
@@ -21,7 +21,7 @@
     public Throwable originalEx;
 
     public UnknownException(Throwable ex) {
-        super("", 0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
+        super("originalEx: " + ex, 0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE);
         originalEx = ex;
     }
 }
diff --git a/yoko-spec-corba/src/main/java/org/omg/CORBA/portable/ValueInputStream.java b/yoko-spec-corba/src/main/java/org/omg/CORBA/portable/ValueInputStream.java
new file mode 100644
index 0000000..fe5034d
--- /dev/null
+++ b/yoko-spec-corba/src/main/java/org/omg/CORBA/portable/ValueInputStream.java
@@ -0,0 +1,32 @@
+/**
+ *
+ * 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.
+ */
+/*
+ * Created on Mar 1, 2004
+ *
+ * To change the template for this generated file go to
+ * Window - Preferences - Java - Code Generation - Code and Comments
+ */
+package org.omg.CORBA.portable;
+
+/**
+ * @author ngmr
+ */
+public interface ValueInputStream {
+	public void end_value();
+	public void start_value();
+}
diff --git a/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPoint.java b/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPoint.java
index e76566a..157173a 100755
--- a/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPoint.java
+++ b/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPoint.java
@@ -26,19 +26,11 @@
 {
     private static final String _ob_id = "IDL:omg.org/IIOP/ListenPoint:1.0";
 
-    public
-    ListenPoint()
-    {
-    }
-
-    public
-    ListenPoint(String host,
-                short port)
-    {
+    public ListenPoint(String host, short port) {
         this.host = host;
         this.port = port;
     }
 
-    public String host;
-    public short port;
+    public final String host;
+    public final short port;
 }
diff --git a/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPointHelper.java b/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPointHelper.java
index bc679da..5e7d62c 100755
--- a/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPointHelper.java
+++ b/yoko-spec-corba/src/main/java/org/omg/IIOP/ListenPointHelper.java
@@ -72,10 +72,7 @@
     public static ListenPoint
     read(org.omg.CORBA.portable.InputStream in)
     {
-        ListenPoint _ob_v = new ListenPoint();
-        _ob_v.host = in.read_string();
-        _ob_v.port = in.read_ushort();
-        return _ob_v;
+        return new ListenPoint(in.read_string(), in.read_ushort());
     }
 
     public static void
diff --git a/yoko-spec-corba/src/main/java/org/omg/IOP/ExceptionDetailMessage.java b/yoko-spec-corba/src/main/java/org/omg/IOP/ExceptionDetailMessage.java
new file mode 100644
index 0000000..e91718b
--- /dev/null
+++ b/yoko-spec-corba/src/main/java/org/omg/IOP/ExceptionDetailMessage.java
@@ -0,0 +1,26 @@
+/*
+ *  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.omg.IOP;
+
+//
+//IDL:omg.org/IOP/ExceptionDetailMessage:1.0
+//
+/***/
+
+public interface ExceptionDetailMessage {
+    int value = (int)(14L);
+}
diff --git a/yoko-spec-corba/src/main/java/org/omg/IOP/RMICustomMaxStreamFormat.java b/yoko-spec-corba/src/main/java/org/omg/IOP/RMICustomMaxStreamFormat.java
new file mode 100644
index 0000000..bdcf54c
--- /dev/null
+++ b/yoko-spec-corba/src/main/java/org/omg/IOP/RMICustomMaxStreamFormat.java
@@ -0,0 +1,27 @@
+/*
+ *  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.omg.IOP;
+
+//
+//IDL:omg.org/IOP/RMICustomMaxStreamFormat:1.0
+//
+/***/
+
+public interface RMICustomMaxStreamFormat {
+    int value = (int)(17L);
+}
diff --git a/yoko-spec-corba/src/main/java/org/omg/IOP/TAG_RMI_CUSTOM_MAX_STREAM_FORMAT.java b/yoko-spec-corba/src/main/java/org/omg/IOP/TAG_RMI_CUSTOM_MAX_STREAM_FORMAT.java
new file mode 100644
index 0000000..9381247
--- /dev/null
+++ b/yoko-spec-corba/src/main/java/org/omg/IOP/TAG_RMI_CUSTOM_MAX_STREAM_FORMAT.java
@@ -0,0 +1,26 @@
+/*
+ *  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.omg.IOP;
+
+//
+//IDL:omg.org/IOP/TAG_RMI_CUSTOM_MAX_STREAM_FORMAT:1.0
+//
+/***/
+
+public interface TAG_RMI_CUSTOM_MAX_STREAM_FORMAT {
+    int value = (int)(38L);
+}
diff --git a/yoko-util/pom.xml b/yoko-util/pom.xml
new file mode 100644
index 0000000..22a7200
--- /dev/null
+++ b/yoko-util/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* 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.
+* -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>yoko</artifactId>
+        <groupId>org.apache.yoko</groupId>
+        <version>1.5-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>yoko-util</artifactId>
+
+    <name>Apache Yoko Implementation Utilities</name>
+
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <!-- this contains the osgi-relevant classes in the endorsed dir -->
+        <dependency>
+            <groupId>org.apache.yoko</groupId>
+            <artifactId>yoko-spec-corba</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.yoko</groupId>
+            <artifactId>yoko-rmi-spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>1.10.19</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Export-Package>
+                            org.apache.yoko.util.*
+                        </Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <!-- <argLine>-verbose:class</argLine> -->
+                    <includes>
+                        <include>**/*Test.java</include>
+                    </includes>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/Cache.java b/yoko-util/src/main/java/org/apache/yoko/util/Cache.java
new file mode 100644
index 0000000..6b69b92
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/Cache.java
@@ -0,0 +1,53 @@
+package org.apache.yoko.util;
+
+import java.util.Map;
+
+public interface Cache<K, V> {
+    /** Get the number of cached values */
+    int size();
+
+    /** Get the number of cached values not currently in use */
+    int idleCount();
+
+    /**
+     * Retrieve the value for the given key.
+     * The caller must ensure the returned reference is closed
+     */
+    Reference<V> get(K key);
+
+    /**
+     * Retrieve or compute the value for the given key.
+     * The caller must ensure that the returned reference is closed.
+     * @return an auto-closeable reference to the cached value
+     */
+    Reference<V> getOrCreate(K key, KeyedFactory<K, V> keyedFactory);
+
+    /**
+     * Retrieve or compute the value for the given key.
+     * The caller must ensure that the returned reference is closed.
+     * @return an auto-closeable reference to the cached value
+     */
+    Reference<V> getOrCreate(K key, Factory<V> factory);
+
+    /**
+     * Uncache an item. No cleanup will be performed.
+     * @throws IllegalStateException if valueRef has already been closed
+     */
+    void remove(Reference<V> ref);
+
+    /**
+     * Uncache an item. No cleanup will be performed.
+     * @return true iff the item was removed
+     */
+    boolean remove(K key, V value);
+
+    /**
+     * Remove some idle entries.
+     * @return the number of entries removed
+     */
+    int clean();
+
+    Map<K, V> snapshot();
+
+    interface Cleaner<V> {void clean(V value);}
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/Factory.java b/yoko-util/src/main/java/org/apache/yoko/util/Factory.java
new file mode 100644
index 0000000..0c86537
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/Factory.java
@@ -0,0 +1,5 @@
+package org.apache.yoko.util;
+
+public interface Factory<V> {
+    V create();
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/Fifa.java b/yoko-util/src/main/java/org/apache/yoko/util/Fifa.java
new file mode 100644
index 0000000..403c397
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/Fifa.java
@@ -0,0 +1,6 @@
+package org.apache.yoko.util;
+
+/** A first-in, first-accessed holder of stuff */
+public interface Fifa<T> extends Sequential<T> {
+    T peek();
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/Fifo.java b/yoko-util/src/main/java/org/apache/yoko/util/Fifo.java
new file mode 100644
index 0000000..e85376e
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/Fifo.java
@@ -0,0 +1,6 @@
+package org.apache.yoko.util;
+
+/** A first-in, first-out holder of stuff */
+public interface Fifo<T> extends Sequential<T> {
+    Object remove();
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/KeyedFactory.java b/yoko-util/src/main/java/org/apache/yoko/util/KeyedFactory.java
new file mode 100644
index 0000000..4212dd7
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/KeyedFactory.java
@@ -0,0 +1,5 @@
+package org.apache.yoko.util;
+
+public interface KeyedFactory<K, V> {
+    V create(K key);
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/Reference.java b/yoko-util/src/main/java/org/apache/yoko/util/Reference.java
new file mode 100644
index 0000000..5d15034
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/Reference.java
@@ -0,0 +1,9 @@
+package org.apache.yoko.util;
+
+public interface Reference<T> extends AutoCloseable {
+    /** Get the referent, which is guaranteed to be non-null */
+    T get();
+    /** Finish using the reference */
+    @Override
+    void close();
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/Sequential.java b/yoko-util/src/main/java/org/apache/yoko/util/Sequential.java
new file mode 100644
index 0000000..ad1cd20
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/Sequential.java
@@ -0,0 +1,18 @@
+package org.apache.yoko.util;
+
+/** A holder of stuff */
+public interface Sequential<T> {
+    int size();
+
+    Place<T> put(T elem);
+
+    interface Place<T> {
+        /**
+         * Relinquish this place in the sequence.
+         *
+         * @return the element if it is successfully removed from the sequence<br>
+         * or <code>null</code> if the element has already been removed by another operation
+         */
+        T relinquish();
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/cmsf/CmsfThreadLocal.java b/yoko-util/src/main/java/org/apache/yoko/util/cmsf/CmsfThreadLocal.java
new file mode 100644
index 0000000..7a07e8d
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/cmsf/CmsfThreadLocal.java
@@ -0,0 +1,99 @@
+package org.apache.yoko.util.cmsf;
+
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public final class CmsfThreadLocal {
+    private static final Logger LOGGER = Logger.getLogger(CmsfThreadLocal.class.getName());
+    private static final ThreadLocal<CmsfInfo> cmsfInfo = new ThreadLocal<CmsfInfo>() {
+        @Override protected CmsfInfo initialValue() {
+            return new CmsfInfo();
+        }
+    };
+
+    private CmsfThreadLocal() {}
+
+    private static final class CmsfInfo {
+        public Frame head = Frame.DEFAULT;
+        public boolean override = false;
+    }
+
+    private static final class Frame {
+        static final Frame DEFAULT = new Frame();
+        public final Version version;
+        public final Frame prev;
+
+        private Frame() {
+            this.version = Version.CMSFv1;
+            this.prev = this;
+        }
+
+        Frame(Version version, Frame prev) {
+            this.version = version;
+            this.prev = prev;
+        }
+    }
+    private enum Version {
+        CMSFv1(1), CMSFv2(2);
+
+        public final byte value;
+
+        private Version(int value) {
+            this.value = (byte)(value & 0xff);
+        }
+
+        static Version get(byte value) {
+            return (value >= 2) ? CMSFv2 : CMSFv1;
+        }
+    }
+
+    public static final class CmsfOverride implements AutoCloseable {
+        private final CmsfInfo info;
+
+        CmsfOverride(CmsfInfo info) {
+            this.info = info;
+            info.override = true;
+        }
+
+        @Override
+        public void close() {
+            info.override = false;
+        }
+    }
+
+    public static CmsfOverride override() {
+        return new CmsfOverride(cmsfInfo.get());
+    }
+
+    public static void push(byte cmsfv) {
+        final CmsfInfo info = cmsfInfo.get();
+        final Version version = Version.get(cmsfv);
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer(String.format("CMSF thread local version pushed onto stack: %s", version));
+        info.head = new Frame(version, info.head);
+    }
+
+    public static byte get() {
+        final CmsfInfo info = cmsfInfo.get();
+        final boolean override = info.override;
+        final Version version = (override) ? Version.CMSFv1 : info.head.version;
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer(String.format("CMSF thread local version retrieved: %s, override is %b", version, override));
+        return version.value;
+    }
+
+    public static byte pop() {
+        final CmsfInfo info = cmsfInfo.get();
+        final Version version = info.head.version;
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer(String.format("CMSF thread local version popped from stack: %s", version));
+        info.head = info.head.prev;
+        return version.value;
+    }
+
+    public static void reset() {
+        if (LOGGER.isLoggable(Level.FINER))
+            LOGGER.finer("CMSF thread local stack reset");
+        cmsfInfo.remove();
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/cmsf/RepIds.java b/yoko-util/src/main/java/org/apache/yoko/util/cmsf/RepIds.java
new file mode 100644
index 0000000..3fd7d4a
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/cmsf/RepIds.java
@@ -0,0 +1,288 @@
+package org.apache.yoko.util.cmsf;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+
+import javax.rmi.CORBA.Util;
+
+public enum RepIds {
+    ;
+
+    public interface Query {
+        public Query suffix(String suffix);
+        public Query codebase(String codebase);
+        public Class<?> toClass();
+        public String toClassName();
+    }
+
+    private static final class QueryImpl implements Query {
+        public final String repid;
+        public final String suffix;
+        public final String codebase;
+
+        private QueryImpl(String repid) {
+            this(Objects.requireNonNull(repid), "", null);
+        }
+
+        private QueryImpl(String repid, String suffix, String codebase) {
+            this.repid = repid;
+            this.suffix = suffix;
+            this.codebase = codebase;
+        }
+
+        @Override
+        public QueryImpl suffix(String suffix) {
+            return new QueryImpl(repid, Objects.requireNonNull(suffix), codebase);
+        }
+
+        @Override
+        public QueryImpl codebase(String codebase) {
+            return new QueryImpl(repid, suffix, codebase);
+        }
+
+        @Override
+        public Class<?> toClass() {
+            return RepIds.toClass(this);
+        }
+
+        @Override
+        public String toClassName() {
+            return RepIds.toClassName(this);
+        }
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(RepIds.class.getName());
+
+    public static Query query(String repid) {
+        return new QueryImpl(repid);
+    }
+
+    private static Class<?> toClass(final QueryImpl query) {
+        final String repid = query.repid;
+        final String suffix = query.suffix;
+        final String codebase = query.codebase;
+        if (LOGGER.isLoggable(Level.FINE))
+            LOGGER.fine(String.format("Searching for class from repid \"%s\" using suffix \"%s\"", repid, suffix));
+        Class<?> result = null;
+
+        //Special case IDL:omg.org/CORBA/WStringValue:1.0
+        if ("IDL:omg.org/CORBA/WStringValue:1.0".equals(repid) && "".equals(suffix)) return String.class;
+
+        final String className = toClassName(query);
+
+        if (LOGGER.isLoggable(Level.FINE))
+            LOGGER.fine(String.format("Class name from repid \"%s\" using suffix \"%s\" is \"%s\"", repid, suffix, className));
+
+        if (className != null) {
+            try {
+                // get the appropriate class for the loading.
+                ClassLoader loader = Thread.currentThread().getContextClassLoader();
+                result = Util.loadClass(className, codebase, loader);
+            } catch (ClassNotFoundException ex) {
+                if (LOGGER.isLoggable(Level.FINE))
+                    LOGGER.fine(String.format("Class \"%s\" not found", className));
+                // ignore
+            }
+        }
+
+        return result;
+    }
+
+    private static final Pattern dotPattern = Pattern.compile(Pattern.quote("."));
+    private static final Pattern slashPattern = Pattern.compile(Pattern.quote("/"));
+
+    private static String toClassName(QueryImpl query) {
+        final String repid = query.repid;
+        final String suffix = query.suffix;
+
+        //Special case IDL:omg.org/CORBA/WStringValue:1.0
+        if ("IDL:omg.org/CORBA/WStringValue:1.0".equals(repid) && "".equals(suffix)) return String.class.getName();
+
+        String result = null;
+        if (repid.startsWith("IDL:")) {
+            result = idlToClassName(repid);
+        } else if (repid.startsWith("RMI:")) {
+            result = rmiToClassName(repid);
+        }
+        if (result != null) {
+            result += suffix;
+            result = removeUnicodeEscapes(result);
+        }
+        return result;
+    }
+
+    private static String rmiToClassName(final String repid) {
+        String result;
+        final int end = repid.indexOf (':', 4);
+        result = end < 0 ? repid.substring (4) : repid.substring (4, end);
+        return result;
+    }
+
+    private static String idlToClassName(final String repid) {
+        try {
+            final StringBuilder sb = new StringBuilder(repid.length());
+
+            final int end = repid.lastIndexOf(':');
+            String s = end < 0 ? repid.substring(4) : repid.substring(4, end);
+
+            //
+            // reverse order of dot-separated name components up
+            // till the first slash.
+            //
+            final int firstSlash = s.indexOf('/');
+            if (firstSlash > 0) {
+                String prefix = s.substring(0, firstSlash);
+                String[] elems = dotPattern.split(prefix);
+                Collections.reverse(Arrays.asList(elems)); //reverses the order in the underlying array - i.e. 'elems'
+                for (String elem: elems) {
+                    sb.append(fixName(elem)).append('.');
+                }
+
+                s = s.substring(firstSlash + 1);
+            }
+
+            //
+            // Append slash-separated name components ...
+            //
+            for (String elem: slashPattern.split(s)) {
+                sb.append(fixName(elem)).append('.');
+            }
+            sb.deleteCharAt(sb.length() - 1); // eliminate final '.'
+
+            return sb.toString();
+        } catch (IndexOutOfBoundsException ex) {
+            // id has bad format
+            return null;
+        }
+    }
+
+    private static String removeUnicodeEscapes(String in) {
+        // if no escape sequences are in the string, this is easy
+        int escape = in.indexOf("\\U");
+        if (escape < 0) {
+            return in;
+        }
+
+        StringBuilder out = new StringBuilder(in.length());
+        int start = 0;
+
+        while (escape >= 0) {
+            out.append(in.substring(start, escape));
+            // step over the escape sequence
+            escape += 2;
+
+            int value = 0;
+            for (int i=0; i<4; i++) {
+                char ch = in.charAt(escape++);
+                switch (ch) {
+                  case '0':
+                  case '1':
+                  case '2':
+                  case '3':
+                  case '4':
+                  case '5':
+                  case '6':
+                  case '7':
+                  case '8':
+                  case '9':
+                     value = (value << 4) + ch - '0';
+                     break;
+                  case 'a':
+                  case 'b':
+                  case 'c':
+                  case 'd':
+                  case 'e':
+                  case 'f':
+                     value = (value << 4) + 10 + ch - 'a';
+                     break;
+                  case 'A':
+                  case 'B':
+                  case 'C':
+                  case 'D':
+                  case 'E':
+                  case 'F':
+                     value = (value << 4) + 10 + ch - 'A';
+                     break;
+                  default:
+                      // not sure what to do here.  Just treat it as a 0 nibble
+                      value = (value << 4);
+                }
+            }
+            // now append this as a char value
+            out.append((char)value);
+            // now step and find the next one
+            start = escape;
+            escape = in.indexOf("\\U", escape);
+        }
+        // don't forget the trailing segment
+        if (start < in.length()) {
+            out.append(in.substring(start));
+        }
+        return out.toString();
+    }
+
+    private static final Set<String> keywords = createStringSet(
+            "abstract", "assert", "boolean", "break", "byte", "case",
+            "catch", "char", "class", "clone", "const", "continue",
+            "default", "do", "double", "else", "equals", "extends",
+            "false", "final", "finalize", "finally", "float", "for",
+            "getClass", "goto", "hashCode", "if", "implements", "import",
+            "instanceof", "int", "interface", "long", "native", "new",
+            "notify", "notifyAll", "null", "package", "private",
+            "protected", "public", "return", "short", "static", "super",
+            "switch", "synchronized", "this", "throw", "throws",
+            "toString", "transient", "true", "try", "void", "volatile",
+            "wait", "while");
+
+    private static Set<String> createStringSet(String...strings) {
+        return Collections.unmodifiableSet(new HashSet<String>(Arrays.asList(strings)));
+    }
+
+    private static final List<String> reservedSuffixes = createStringList(
+            "Helper", "Holder", "Operations", "POA",
+            "POATie", "Package", "ValueFactory");
+
+    private static List<String> createStringList(String...strings) {
+        return Collections.unmodifiableList(Arrays.asList(strings));
+    }
+
+    private static String fixName(String name) {
+        assert(name.indexOf('.') == -1); // Not for absolute names
+
+        int nameLen = name.length();
+        if (nameLen == 0)
+            return name;
+
+        if (keywords.contains(name)) return "_" + name;
+
+        //
+        // Prepend an underscore for each of the reserved suffixes
+        //
+        String result = name;
+        String curr = name;
+
+        OUTER_LOOP: while (true) {
+            for (String reservedSuffix: reservedSuffixes) {
+                if (curr.endsWith(reservedSuffix)) {
+                    result = "_" + result;
+
+                    int currLength = curr.length();
+                    int resLength = reservedSuffix.length();
+                    if (currLength == resLength)
+                        return result;
+                    curr = curr.substring(0, currLength - resLength);
+                    continue OUTER_LOOP;
+                }
+            }
+            return result;
+        }
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ConcurrentFifo.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ConcurrentFifo.java
new file mode 100644
index 0000000..67d2eb3
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ConcurrentFifo.java
@@ -0,0 +1,164 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.Fifa;
+import org.apache.yoko.util.Fifo;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * A thread-safe queue that allows concurrent modification of non-adjacent elements.
+ */
+class ConcurrentFifo<T> implements Fifo<T>, Fifa<T> {
+    /*
+     * This class relies on consistent lock ordering. Locks are ALWAYS obtained
+     * in the order of elements in the queue. The locks used are the monitors
+     * of the node elements, and each node's monitor guards the relationship
+     * between that node and its successor. By implication, it guards the other
+     * node's back reference as well.
+     *
+     * So, for a delete operation, two nodes must be locked: the node to be
+     * deleted, and the previous node, but NOT IN THAT ORDER! Moreover, after
+     * the previous node is locked, the relationship must be checked to ensure
+     * it is still current. The convention observed is that next() is only
+     * accessed while the lock is held, and it is cross-checked against any
+     * unguarded calls to prev().
+     *
+     * NOTE: this is not double-check locking (DCL) because the early access
+     * never obviates a synchronized block, and results are always checked 
+     * within the guarded section. Therefore, it is not necessary for any of
+     * the non-final fields to be volatile.
+     * 
+     * DCL: https://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#dcl
+     *
+     * If inconsistency is detected, all locks are to be released and the
+     * operation restarted from scratch, unless it can be determined the
+     * operation has definitively failed due to concurrent modification.
+     *
+     * Operations on non-adjacent nodes are concurrent. Concurrent operations
+     * on a node or on adjacent nodes will contend for monitors, but never
+     * deadlock.
+     */
+
+    private final Head<T> head = new Head<>();
+    private final Foot<T> foot = new Foot<>(head);
+    protected final AtomicInteger size = new AtomicInteger(0);
+
+    @Override
+    public int size() { return size.get(); }
+
+    /**
+     * Get, without removing it, the oldest remaining element from this FIFO.
+     * This method does not block and returns an answer consistent with the state of the FIFO at some point.
+     *
+     * @return the oldest remaining element or <code>null</code> if the FIFO was empty
+     */
+    @Override
+    public T peek() {
+        return recursivePeek(head);
+    }
+
+    /**
+     * Find the first non-null value.
+     */
+    private T recursivePeek(PNode<T> start) {
+        synchronized (start) {
+            NNode<T> nn = start.next();
+            if (nn == foot) return null;
+            VNode<T> node = (VNode<T>) nn;
+            T result = node.get();
+            return (result == null) ? recursivePeek(node) : result;
+        }
+    }
+
+    /**
+     * Add an element to the end of this FIFO.
+     *
+     * @param elem must not be <code>null</code>
+     * @return an object representing the place in the queue
+     */
+    @Override
+    public Place<T> put(T elem) {
+        do {
+            final PNode<T> pnode = foot.prev();
+            // lock penultimate node
+            synchronized (pnode) {
+                // RETRY if structure changed
+                if (pnode.next() != foot) continue;
+                // create a new node
+                final VNode<T> node = createNode(elem);
+                // insert new node
+                synchronized (node) {
+                    node.insertAfter(pnode);
+                    size.incrementAndGet();
+                }
+                // return place in queue
+                return new Place<T>() {
+                    @Override
+                    public T relinquish() {
+                        return remove(node);
+                    }
+                };
+            }
+        } while (true);
+    }
+
+    protected VNode<T> createNode(T elem) {
+        return new StrongNode<>(requireNonNull(elem));
+    }
+
+    /**
+     * Remove the least recently added element.
+     *
+     * @return the removed element, or <code>null</code> if the FIFO was empty.
+     */
+    @Override
+    public T remove() {
+        return recursiveRemove(head);
+    }
+
+    /**
+     * Find and remove the first non-null value
+     */
+    private T recursiveRemove(PNode<T> start) {
+        synchronized (start) {
+            NNode<T> nn = start.next();
+            if (nn == foot) return null;
+            VNode<T> node = (VNode<T>) nn;
+            T result = node.get();
+            if (result == null)
+                return recursiveRemove(node);
+            synchronized (node) {
+                node.delete();
+                size.decrementAndGet();
+                return result;
+            }
+        }
+    }
+
+    /**
+     * Remove the specified node from the FIFO, if present.
+     * @return the element if it was successfully removed,
+     *         otherwise <code>null</code>
+     */
+    protected T remove(VNode<T> node) {
+        do {
+            // retrieve previous node
+            final PNode<T> pNode = node.prev();
+            // FAIL if node already deleted
+            if (pNode == null) return null;
+            // lock previous node
+            synchronized (pNode) {
+                // RETRY if structure has changed
+                if (pNode.next() != node) continue;
+                // Remove node from chain and report success
+                synchronized (node) {
+                    node.delete();
+                    size.decrementAndGet();
+                }
+                return node.get();
+            }
+        } while (true);
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/CountedEntry.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/CountedEntry.java
new file mode 100644
index 0000000..0177f5f
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/CountedEntry.java
@@ -0,0 +1,153 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.Reference;
+import org.apache.yoko.util.Sequential;
+
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * A thread-safe, reference-counting entry for use in a cache.
+ * If threads race to call @link{#clear} and @link{#obtain},
+ * one or other method will return <code>null</code>.
+ * <br>
+ * Entries with a reference count of zero will be put onto the
+ * provided @link{Sequential} object, and removed on successful
+ * calls to either @link{#clear} or @link{#obtain}.
+ */
+class CountedEntry<K, V> {
+    private static final int CLEANED = Integer.MIN_VALUE;
+    private static final int NOT_READY = -1;
+    private static final int IDLE = -2;
+    private final AtomicInteger refCount = new AtomicInteger(NOT_READY);
+    private final Sequential<CountedEntry<K, V>> idleEntries;
+    private Sequential.Place<?> idlePlace;
+    private V value;
+    final K key;
+
+    /** Create a not-yet-ready CountedEntry - the next operation must be to call setValue() or abort() */
+    CountedEntry(K key, Sequential<CountedEntry<K, V>> idleEntries) {
+        this.key = key;
+        this.idleEntries = idleEntries;
+    }
+
+    ValueReference setValue(V value) {
+        this.value = Objects.requireNonNull(value);
+        notifyReady(1);
+        return new ValueReference();
+    }
+
+    void abort() {
+        assert value == null;
+        notifyReady(CLEANED);
+    }
+
+    private synchronized void notifyReady(int newCount) {
+        boolean success = refCount.compareAndSet(NOT_READY, newCount);
+        assert success;
+        this.notifyAll();
+    }
+
+    private synchronized void blockWhileNotReady() {
+        while (refCount.get() == NOT_READY) {
+            try {
+                this.wait();
+            } catch (InterruptedException ignored) {
+            }
+        }
+    }
+
+    // Acquire a reference to this entry.
+    private boolean acquire() {
+        RESPIN: do {
+            int oldCount = refCount.get();
+            switch (oldCount) {
+                case CLEANED:
+                    // terminal state - must fail
+                    return false;
+                case NOT_READY:
+                    blockWhileNotReady();
+                    continue RESPIN;
+                case IDLE:
+                    // grab the ref while it's idle or start again
+                    if (!!!refCount.compareAndSet(IDLE, NOT_READY)) continue RESPIN;
+                    // remove from the idle list
+                    Object self = idlePlace.relinquish();
+                    assert this == self;
+                    idlePlace = null;
+                    // let other threads know this entry is accessible again
+                    notifyReady(1);
+                    return true;
+                default:
+                    // increment the value retrieved or start again
+                    if (!!!refCount.compareAndSet(oldCount, oldCount + 1)) continue RESPIN;
+                    return true;
+            }
+        } while (true);
+    }
+
+    // Release a reference to this entry. Only the owner of the reference should call this method.
+    private boolean release() {
+        int newCount = refCount.decrementAndGet();
+        if (newCount != 0) return true;
+
+        // try to IDLE this entry
+        if (!!!refCount.compareAndSet(0, NOT_READY))
+            // some other thread revived or purged this entry, so no need to IDLE it now
+            return true;
+
+        idlePlace = idleEntries.put(this);
+        notifyReady(IDLE);
+        return true;
+    }
+
+    // Mark this entry unusable. Return value if entry is modified, null otherwise.
+    V clear() {
+        if (!!! refCount.compareAndSet(IDLE, CLEANED)) return null;
+        // safe to read/update idlePlace since this is the only thread that has moved it from IDLE
+        try {
+            Object self = idlePlace.relinquish();
+            assert self == this;
+            return value;
+        } finally {
+            value = null;
+            idlePlace = null;
+        }
+    }
+
+    ValueReference obtain() {return acquire() ? new ValueReference() : null;}
+
+    /** Clear an entry that still has valid references */
+    private CountedEntry<K, V> purge() {
+        RESPIN: do {
+            int oldCount = refCount.get();
+            if (oldCount == CLEANED) return null;
+            if (oldCount < 1) throw new IllegalStateException();
+            if (!!! refCount.compareAndSet(oldCount, CLEANED)) continue RESPIN;
+            return this;
+        } while (true);
+    }
+
+    final class ValueReference implements Reference<V> {
+        private final ReferenceCloserTask closer = new ReferenceCloserTask();
+        public V get() {return value;}
+        public void close() {closer.run();}
+        CountedEntry<K, V> invalidateAndGetEntry() {return closer.purge();}
+        Runnable getCloserTask() {return closer;}
+    }
+
+    /**
+     * In order to drive cleanup after a ValueReference becomes unreachable,
+     * we need to store the clean up details in a separate object that holds
+     * no strong reference back to the ValueReference object
+     */
+    final class ReferenceCloserTask implements Runnable {
+        boolean closed;
+        public synchronized void run() {closed = closed || release();}
+        synchronized CountedEntry<K,V> purge() {
+            if (closed) throw new IllegalStateException();
+            closed = true;
+            return CountedEntry.this.purge();
+        }
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/Foot.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/Foot.java
new file mode 100644
index 0000000..cc433f8
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/Foot.java
@@ -0,0 +1,15 @@
+package org.apache.yoko.util.concurrent;
+
+import static java.util.Objects.requireNonNull;
+
+final class Foot<T> implements NNode<T> {
+    private PNode<T> prev;
+    
+    public PNode<T> prev() {return prev;}
+    public void prev(PNode<T> pnode) {prev = pnode;}
+    
+    Foot(Head<T> head) {
+        this.prev = requireNonNull(head);
+        head.next(this);
+    }
+}
\ No newline at end of file
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/Head.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/Head.java
new file mode 100644
index 0000000..9f52e63
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/Head.java
@@ -0,0 +1,7 @@
+package org.apache.yoko.util.concurrent;
+
+final class Head<T> implements PNode<T> {
+    private NNode<T> next;
+    public NNode<T> next() {return next;}
+    public void next(NNode<T> nnode) {next = nnode;}
+}
\ No newline at end of file
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/NNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/NNode.java
new file mode 100644
index 0000000..51863fd
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/NNode.java
@@ -0,0 +1,7 @@
+package org.apache.yoko.util.concurrent;
+
+interface NNode<T> {
+    PNode<T> prev();
+    
+    void prev(PNode<T> pnode);
+}
\ No newline at end of file
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/PNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/PNode.java
new file mode 100644
index 0000000..9ee2fdf
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/PNode.java
@@ -0,0 +1,7 @@
+package org.apache.yoko.util.concurrent;
+
+interface PNode<T> {
+    NNode<T> next();
+    
+    void next(NNode<T> nnode);
+}
\ No newline at end of file
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ReferenceCountedCache.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ReferenceCountedCache.java
new file mode 100644
index 0000000..ca5374e
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/ReferenceCountedCache.java
@@ -0,0 +1,136 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.*;
+
+import java.lang.ref.ReferenceQueue;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+public class ReferenceCountedCache<K, V> implements Cache<K,V> {
+
+    private final ConcurrentMap<K, CountedEntry<K, V>> map = new ConcurrentHashMap<>();
+    private final Fifa<CountedEntry<K, V>> idleEntries = new ConcurrentFifo<>();
+    private volatile int threshold;
+    private volatile int sweep;
+    private final Cleaner<V> cleaner;
+    private final ReferenceQueue<Reference<V>> gcQueue;
+
+    /**
+     * Create a new cache
+     * @param cleaner   the object to use to clean entries
+     * @param threshold the number of values above which to start cleaning up
+     * @param sweep     the number of unused values to clear up
+     */
+    public ReferenceCountedCache(Cleaner<V> cleaner, int threshold, int sweep) {
+        this.threshold = threshold;
+        this.sweep = sweep;
+        this.cleaner = cleaner;
+        gcQueue = new ReferenceQueue<>();
+    }
+
+    @Override
+    public int size() {
+        return map.size();
+    }
+
+    @Override
+    public int idleCount() {
+        return idleEntries.size();
+    }
+
+    @Override
+    public Reference<V> get(K key) {
+        CountedEntry<K, V> entry = map.get(key);
+        if (entry == null) return null;
+        return entry == null ? null : track(entry.obtain());
+    }
+
+    @Override
+    public Reference<V> getOrCreate(K key, KeyedFactory<K, V> valueFactory) {
+        CountedEntry<K,V>.ValueReference result;
+        do {
+            CountedEntry<K, V> entry = map.get(key);
+            if (entry == null) {
+                // try putting a new entry in the map
+                CountedEntry<K, V> newEntry = new CountedEntry<>(key, idleEntries);
+                entry = map.putIfAbsent(key, newEntry);
+                if (entry == null) {
+                    // this thread won the race to create the new entry
+                    V value = null;
+                    try {
+                        value = valueFactory.create(key);
+                        return track(newEntry.setValue(value));
+                    } finally {
+                        if (value == null) {
+                            // create() threw an exception, so clean up
+                            // and make sure no-one else tries to use this entry
+                            newEntry.abort();
+                            map.remove(key, newEntry);
+                        }
+                    }
+                }
+            }
+            result = entry.obtain();
+        } while (result == null); // the entry was cleared - try again
+        return track(result);
+    }
+
+    protected CountedEntry<K,V>.ValueReference track(CountedEntry<K,V>.ValueReference ref) {return ref;}
+
+    @Override
+    public final Reference<V> getOrCreate(K key, final Factory<V> factory) {
+        return getOrCreate(key, new KeyedFactory<K, V>() {
+            @Override
+            public V create(K key) {
+                return factory.create();
+            }
+        });
+    }
+
+    @Override
+    public void remove(Reference<V> ref) {remove(((CountedEntry<K,V>.ValueReference) ref).invalidateAndGetEntry());}
+
+    @Override
+    public boolean remove(K key, V value) {
+        if (key == null) return false;
+        CountedEntry<K, V> entry = map.get(key);
+        try (Reference ref = entry.obtain();) {
+            if (ref == null) return false;
+            if (ref.get() != value) return false;
+            remove(ref);
+            return true;
+        }
+    }
+
+    protected void remove(CountedEntry<K,V> entry) {if (entry != null) map.remove(entry.key, entry);}
+
+    @Override
+    public int clean() {
+        if (size() <= threshold) return 0;
+        int removed = 0;
+        while (removed < sweep) {
+            CountedEntry<K, V> e = idleEntries.peek();
+            if (e == null) break;
+            V clearedValue = e.clear();
+            if (clearedValue == null) continue;
+            if (!!!map.remove(e.key, e))
+                throw new IllegalStateException("Entry already removed");
+            cleaner.clean(clearedValue);
+            removed++;
+        }
+        return removed;
+    }
+
+    @Override
+    public Map<K, V> snapshot() {
+        Map<K, V> result = new HashMap<>();
+        for (Map.Entry<K,CountedEntry<K, V>> entry : map.entrySet()) {
+            try (Reference<V> ref = entry.getValue().obtain()){
+                result.put(entry.getKey(), ref.get());
+            } catch (NullPointerException ignored) {}
+        }
+        return result;
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/StrongNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/StrongNode.java
new file mode 100644
index 0000000..b870ca4
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/StrongNode.java
@@ -0,0 +1,29 @@
+package org.apache.yoko.util.concurrent;
+
+final class StrongNode<T> implements VNode<T> {
+    private final T value;
+    private PNode<T> prev;
+    private NNode<T> next;
+    
+    StrongNode(T value) {this.value = value;}
+    public PNode<T> prev() {return prev;}
+    public NNode<T> next() {return next;}
+    public void prev(PNode<T> pnode) {prev = pnode;}
+    public void next(NNode<T> nnode) {next = nnode;}
+    public T get() {return value;}
+
+    public void insertAfter(PNode<T> pnode) {
+        NNode<T> nnode = pnode.next();
+        this.next = nnode;
+        this.prev = pnode;
+        nnode.prev(this);
+        pnode.next(this);
+    }
+
+    public void delete() {
+        this.prev.next(this.next);
+        this.next.prev(this.prev);
+        this.prev = null;
+        this.next = null;
+    }
+}
\ No newline at end of file
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/VNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/VNode.java
new file mode 100644
index 0000000..1aef732
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/VNode.java
@@ -0,0 +1,10 @@
+package org.apache.yoko.util.concurrent;
+
+public interface VNode<T> extends PNode<T>, NNode<T> {
+    T get();
+
+    void insertAfter(PNode<T> pnode);
+
+    void delete();
+
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakConcurrentFifo.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakConcurrentFifo.java
new file mode 100644
index 0000000..2191a94
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakConcurrentFifo.java
@@ -0,0 +1,70 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.KeyedFactory;
+
+import java.lang.ref.ReferenceQueue;
+
+import static java.util.Objects.requireNonNull;
+
+public class WeakConcurrentFifo<T> extends ConcurrentFifo<T> {
+    private final ReferenceQueue<T> refQueue = new ReferenceQueue<>();
+    private final KeyedFactory<? super T, Runnable> cleanupFactory;
+
+    WeakConcurrentFifo(KeyedFactory<? super T, Runnable> cleanupFactory) {
+        this.cleanupFactory = requireNonNull(cleanupFactory);
+    }
+
+    @Override
+    public int size() {
+        cleanup();
+        return super.size();
+    }
+
+    @Override
+    public T peek() {
+        cleanup();
+        return super.peek();
+    }
+
+    @Override
+    public Place<T> put(T elem) {
+        cleanup();
+        return super.put(elem);
+    }
+
+    @Override
+    public T remove() {
+        cleanup();
+        return super.remove();
+    }
+
+    @Override
+    protected VNode<T> createNode(T elem) {
+        return new WeakNode<>(elem, refQueue, cleanupFactory.create(elem));
+    }
+
+    private void cleanup() {
+        do {
+            @SuppressWarnings("unchecked")
+            WeakNode<T> wn = (WeakNode<T>) refQueue.poll();
+            if (wn == null) return;
+            cleanup(wn);
+        } while (true);
+    }
+
+    private void cleanup(WeakNode<T> wn) {
+        RESPIN: do {
+            PNode<T> prev = wn.prev();
+            if (prev == null) return; // this node is already removed
+            synchronized (prev) {
+                if (wn.prev() != prev) continue RESPIN; // something changed!
+                synchronized (wn) {
+                    wn.delete();
+                    size.decrementAndGet();
+                    wn.cleanup.run();
+                    return;
+                }
+            }
+        } while (true);
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakCountedCache.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakCountedCache.java
new file mode 100644
index 0000000..6c0dffe
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakCountedCache.java
@@ -0,0 +1,35 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.KeyedFactory;
+
+public class WeakCountedCache<K, V> extends ReferenceCountedCache<K, V> {
+    private final WeakConcurrentFifo<CountedEntry<K,V>.ValueReference> referenceTracker
+            = new WeakConcurrentFifo<>(new CleanupFactory());
+
+    /**
+     * Create a new cache
+     *
+     * @param cleaner   the object to use to clean entries
+     * @param threshold the number of values above which to start cleaning up
+     * @param sweep     the number of unused values to clear up
+     */
+    public WeakCountedCache(Cleaner<V> cleaner, int threshold, int sweep) {
+        super(cleaner, threshold, sweep);
+    }
+
+    @Override
+    protected CountedEntry<K,V>.ValueReference track(CountedEntry<K,V>.ValueReference ref) {
+        if (ref != null)
+            referenceTracker.put(ref);
+        return ref;
+    }
+
+    private final class CleanupFactory implements KeyedFactory<CountedEntry<K,V>.ValueReference, Runnable> {
+        public Runnable create(CountedEntry<K, V>.ValueReference key) {
+            // Do NOT keep the key around, since this must only be held weakly.
+            // Instead, keep the closer task so we can clean up after the key is collected.
+            // Subsequent calls to close do nothing, so it's safe to run this multiple times.
+            return key.getCloserTask();
+        }
+    }
+}
diff --git a/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakNode.java b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakNode.java
new file mode 100644
index 0000000..1235b5f
--- /dev/null
+++ b/yoko-util/src/main/java/org/apache/yoko/util/concurrent/WeakNode.java
@@ -0,0 +1,34 @@
+package org.apache.yoko.util.concurrent;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+final class WeakNode<T> extends WeakReference<T> implements VNode<T> {
+    final Runnable cleanup;
+    private PNode<T> prev;
+    private NNode<T> next;
+
+    WeakNode(T value, ReferenceQueue<T> q, Runnable cleanup) {
+        super(value, q);
+        this.cleanup = cleanup;
+    }
+    public PNode<T> prev() {return prev;}
+    public NNode<T> next() {return next;}
+    public void prev(PNode<T> pnode) {prev = pnode;}
+    public void next(NNode<T> nnode) {next = nnode;}
+
+    public void insertAfter(PNode<T> pnode) {
+        NNode<T> nnode = pnode.next();
+        this.next = nnode;
+        this.prev = pnode;
+        nnode.prev(this);
+        pnode.next(this);
+    }
+
+    public void delete() {
+        this.prev.next(this.next);
+        this.next.prev(this.prev);
+        this.prev = null;
+        this.next = null;
+    }
+}
\ No newline at end of file
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();
+    }
+}
diff --git a/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ConcurrentFifoTest.java b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ConcurrentFifoTest.java
new file mode 100644
index 0000000..4818250
--- /dev/null
+++ b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ConcurrentFifoTest.java
@@ -0,0 +1,274 @@
+package org.apache.yoko.util.concurrent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.yoko.util.Sequential;
+import org.junit.Before;
+import org.junit.Test;
+
+@SuppressWarnings("unused")
+public class ConcurrentFifoTest {
+    private static final List<String> ELEMS = new ArrayList<>();
+
+    static {
+        for (char c1 = 'A'; c1 <= 'Z'; c1++)
+            for (char c2 = 'a'; c2 <= 'z'; c2++)
+                ELEMS.add("" + c1 + c2);
+    }
+
+    ConcurrentFifo<String> fifo;
+    Set<Sequential.Place<String>> places;
+    volatile CyclicBarrier startBarrier;
+
+    @Before
+    public void setupFifo() {
+        fifo = new ConcurrentFifo<>();
+    }
+
+    @Before
+    public void setupPlaces() {
+        places = Collections.newSetFromMap(new ConcurrentHashMap<Sequential.Place<String>, Boolean>());
+    }
+
+    @Before
+    public void nullifyStartBarrier() {
+        startBarrier = null;
+    }
+
+    @Test
+    public void testPuttingStuff() throws Exception {
+        // create tasks
+        List<Adder> tasks = new ArrayList<>();
+        for (String dummy : ELEMS)
+            tasks.add(new Adder());
+
+        // run the tasks concurrently
+        List<List<String>> expectedOrders = runConcurrently(tasks);
+
+        // convert the fifo to a list
+        List<String> actualOrder = drainFifo();
+
+        assertEquals(ELEMS.size() * ELEMS.size(), actualOrder.size());
+
+        // check correct ordering per Adder:
+        // as we tally the elements in order,
+        // the number of ELEM[n] encountered 
+        // should always be greater than or 
+        // equal to the number of ELEM[n+1] 
+        // encountered
+        TreeMap<String, Integer> tallySheet = new TreeMap<>();
+        // start with zero for every element
+        for (String elem : ELEMS) tallySheet.put(elem,  0);
+        // place known elephant in Cairo
+        tallySheet.put("", Integer.MAX_VALUE);
+        int index = -1;
+        for (String elem : actualOrder) {
+            index ++;
+            int newTally = tallySheet.get(elem) + 1;
+            tallySheet.put(elem, newTally);
+            Entry<String, Integer> lowerEntry = tallySheet.lowerEntry(elem);
+            String msg = String.format("Element out of order at index %d: %d \"%s\" found but only %d \"%s\"", index, newTally, elem, lowerEntry.getValue(), lowerEntry.getKey());
+            assertTrue(msg, lowerEntry.getValue() >= newTally);
+        }
+    }
+
+    @Test
+    public void testPickingStuff() throws Exception {
+        // pre-populate elements
+        for (String elem : ELEMS)
+            places.add(fifo.put(elem));
+
+        // create tasks
+        List<Constrictor> tasks = new ArrayList<>();
+        for (String elem : ELEMS)
+            tasks.add(new Constrictor());
+
+        // run the tasks concurrently
+        List<List<String>> removalLists = runConcurrently(tasks);
+        for (List<String> list : removalLists) if (!!!list.isEmpty()) System.out.println(list);
+
+        // convert the queue to a list
+        List<String> remainingElements = drainFifo();
+
+        // check for the right number of entries
+        assertEquals(Collections.emptyList(), remainingElements);
+
+        // check everything was removed exactly once
+        List<String> checkedRemovals = concatenate(removalLists);
+        Collections.sort(checkedRemovals);
+        assertEquals(ELEMS, checkedRemovals);
+    }
+
+    @Test
+    public void testGettingStuff() throws Exception {
+        // pre-populate elements
+        for (String elem : ELEMS)
+            places.add(fifo.put(elem));
+
+        // create tasks
+        List<Wiper> tasks = new ArrayList<>();
+        for (String elem : ELEMS)
+            tasks.add(new Wiper());
+
+        // run the tasks concurrently
+        List<List<String>> removalLists = runConcurrently(tasks);
+        for (List<String> list : removalLists) if (!!!list.isEmpty()) System.out.println(list);
+
+        // convert the queue to a list
+        List<String> remainingElements = drainFifo();
+
+        // check for the right number of entries
+        assertEquals(Collections.emptyList(), remainingElements);
+
+        // check everything was removed exactly once
+        List<String> checkedRemovals = concatenate(removalLists);
+        Collections.sort(checkedRemovals);
+        assertEquals(ELEMS, checkedRemovals);
+
+        // check no-one removed anything out of order
+        // i.e. each list of removed elements should remain unchanged by sorting
+        for (List<String> removed : removalLists)
+            assertEquals(new ArrayList<>(new TreeSet<>(removed)), removed);
+    }
+
+    @Test
+    public void testAllOpsConcurrently() throws Exception {
+        // pre-populate all the possible elements
+        for (String elem : ELEMS)
+            places.add(fifo.put(elem));
+
+        // create tasks
+        List<Callable<List<String>>> tasks = new ArrayList<>();
+        for (int i = 0; i < 1000; i++) {
+            switch (i % 4) {
+            case 0:
+            case 2:
+                tasks.add(new Adder());
+                break;
+            case 1:
+                tasks.add(new Constrictor());
+                break;
+            case 3:
+                tasks.add(new Wiper());
+                break;
+            }
+        }
+
+        List<String> added = new ArrayList<>(), removed = new ArrayList<>();
+
+        // collate additions and subtractions
+        Iterator<Callable<List<String>>> iterator = tasks.iterator();
+        for (List<String> results : runConcurrently(tasks))
+            (iterator.next() instanceof Adder ? added : removed).addAll(results);
+        added.addAll(ELEMS); // these were added up front
+        Collections.sort(added);
+        List<String> remainder = drainFifo();
+        removed.addAll(remainder);
+        Collections.sort(removed);
+
+        assertEquals(added, removed);
+
+    }
+
+    private <T> List<T> concatenate(List<List<T>> lists) {
+        List<T> result = new ArrayList<>();
+        for (List<T> list : lists)
+            result.addAll(list);
+        return result;
+    }
+
+    private List<String> drainFifo() {
+        List<String> queuedOrder = new ArrayList<>();
+        do {
+            String o = fifo.remove();
+            if (o == null) break;
+            queuedOrder.add(o);
+        } while (true);
+        return queuedOrder;
+    }
+
+    private <T> List<T> runConcurrently(List<? extends Callable<T>> tasks)
+            throws InterruptedException, ExecutionException {
+        // start all the threads
+        startBarrier = new CyclicBarrier(tasks.size());
+        ExecutorService xs = Executors.newFixedThreadPool(tasks.size());
+        try {
+            List<Future<T>> futures = new ArrayList<>();
+            for (Callable<T> task : tasks)
+                futures.add(xs.submit(task));
+
+            // collect the results
+            List<T> results = new ArrayList<>();
+            for (Future<T> future : futures)
+                results.add(future.get());
+            return results;
+        } finally {
+            xs.shutdown();
+        }
+    }
+
+    /** Adds stuff to the FIFO */
+    class Adder implements Callable<List<String>> {
+        @Override
+        public List<String> call() throws Exception {
+            List<String> added = new ArrayList<>();
+            startBarrier.await();
+            for (String elem : new ArrayList<>(ELEMS)) {
+                places.add(fifo.put(elem));
+                added.add(elem);
+            }
+            return added;
+        }
+    }
+
+    /** Constrains the FIFO by removing specific elements */
+    class Constrictor implements Callable<List<String>> {
+        @Override
+        public List<String> call() throws Exception {
+            List<String> constricted = new ArrayList<>();
+            startBarrier.await();
+            while (!!! places.isEmpty()) {
+                // get a copy of the known places in the fifo and shuffle it
+                List<Sequential.Place<String>> myPlaces = new ArrayList<>(places);
+                Collections.shuffle(myPlaces);
+                // remove everything we can
+                for (Sequential.Place<String> place : myPlaces) {
+                    String elem = place.relinquish();
+                    if (elem != null)
+                        constricted.add(elem);
+                    places.remove(place);
+                }
+            }
+            return constricted;
+        }
+    }
+
+    /** Wipes out the FIFO by getting all the elements */
+    class Wiper implements Callable<List<String>> {
+        @Override
+        public List<String> call() throws Exception {
+            List<String> wiped = new ArrayList<>();
+            startBarrier.await();
+            for (String elem = fifo.remove(); elem != null; elem = fifo.remove())
+                wiped.add(elem);
+            return wiped;
+        }
+    }
+}
diff --git a/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ReferenceCountedCacheTest.java b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ReferenceCountedCacheTest.java
new file mode 100644
index 0000000..65c304e
--- /dev/null
+++ b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/ReferenceCountedCacheTest.java
@@ -0,0 +1,255 @@
+package org.apache.yoko.util.concurrent;
+
+import static org.mockito.Mockito.*;
+import static org.junit.Assert.*;
+
+import org.apache.yoko.util.Cache;
+import org.apache.yoko.util.KeyedFactory;
+import org.apache.yoko.util.Reference;
+import org.junit.After;
+import org.junit.Test;
+
+import org.junit.runner.RunWith;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.util.*;
+import java.util.concurrent.*;
+
+@RunWith(MockitoJUnitRunner.class)
+public class ReferenceCountedCacheTest {
+    private static final ConcurrentLinkedQueue<Integer> createdInts = new ConcurrentLinkedQueue<>();
+    private static final ConcurrentLinkedQueue<Integer> deletedInts = new ConcurrentLinkedQueue<>();
+    private static class StringToInteger implements KeyedFactory<String, Integer>, Cache.Cleaner<Integer> {
+        @Override
+        public Integer create(String key) {
+            Integer result = new Integer(key);
+            createdInts.add(result);
+            return result;
+        }
+
+        @Override
+        public void clean(Integer value) {
+            deletedInts.add(value);
+        }
+    }
+    private static class BadFactory implements KeyedFactory<String, Integer> {
+        @Override
+        public Integer create(String key) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    @Spy
+    StringToInteger factory;
+    @Spy
+    BadFactory badFactory;
+    ReferenceCountedCache<String, Integer> cache;
+    volatile CyclicBarrier startBarrier, endBarrier;
+    volatile boolean retrieving = true;
+
+    @After
+    public void setup() {
+        createdInts.clear();
+        deletedInts.clear();
+        cache = null;
+        retrieving = true;
+        startBarrier = endBarrier = null;
+    }
+
+    @Test
+    public void testGetAndCreate() {
+        cache = new ReferenceCountedCache<>(factory, 0, 5);
+        assertEquals(null, cache.get("1"));
+        try (Reference<Integer> ref = cache.getOrCreate("1", factory);)
+        {assertEquals(Integer.valueOf(1), ref.get());}
+        try (Reference<Integer> ref = cache.get("1");)
+        {assertEquals(Integer.valueOf(1), ref.get());}
+        cache.clean();
+        assertEquals(null, cache.get("1"));
+    }
+
+    @Test
+    public void testFailedCreateDoesNotPolluteCache() {
+        cache = new ReferenceCountedCache<>(factory, 0, 5);
+        assertEquals(null, cache.get("1"));
+        try (Reference<Integer> ref = cache.getOrCreate("1", badFactory);) {
+            fail("getOrCreate() should throw an exception");
+        } catch (UnsupportedOperationException expected) {}
+
+        assertEquals(null, cache.get("1"));
+
+        try (Reference<Integer> ref = cache.getOrCreate("1", factory);)
+        {assertEquals(Integer.valueOf(1), ref.get());}
+        try (Reference<Integer> ref = cache.get("1");)
+        {assertEquals(Integer.valueOf(1), ref.get());}
+        cache.clean();
+        assertEquals(null, cache.get("1"));
+    }
+
+    @Test
+    public void testCreateAndClean() {
+        cache = new ReferenceCountedCache<>(factory, 3, 5);
+        cache.getOrCreate("0", factory).close();
+        cache.getOrCreate("1", factory).close();
+        assertEquals(2, cache.snapshot().size());
+        cache.getOrCreate("2", factory).close();
+        assertEquals(3, cache.snapshot().size());
+        cache.getOrCreate("3", factory).close();
+        assertEquals(4, cache.snapshot().size());
+        long cleaned = cache.clean();
+        assertEquals(4, cleaned);
+        assertEquals(0, cache.snapshot().size());
+    }
+
+    @Test
+    public void testCreateEntries() {
+        cache = new ReferenceCountedCache<>(factory, 0, 0);
+        // new entries should result in factory invocations
+        cache.getOrCreate("0", factory);
+        verify(factory).create("0");
+        cache.getOrCreate("1", factory);
+        verify(factory).create("1");
+        // existing entries should not invoke the factory further
+        cache.getOrCreate("0", factory);
+        cache.getOrCreate("1", factory);
+        verify(factory, times(2)).create(anyString());
+        System.out.println(createdInts);
+    }
+
+    @Test
+    public void testReleaseResults() {
+        cache = new ReferenceCountedCache<>(factory, 3, 5);
+        Reference<Integer> r0, r1, r2, r3, r4, r5;
+        r0 = cache.getOrCreate("0", factory);
+        r1 = cache.getOrCreate("1", factory);
+        r2 = cache.getOrCreate("2", factory);
+        // check the references are to the right values
+        assertEquals(Integer.valueOf(0), r0.get());
+        assertEquals(Integer.valueOf(1), r1.get());
+        assertEquals(Integer.valueOf(2), r2.get());
+        // check the size is correct
+        assertEquals(3, cache.size());
+        assertEquals(0, cache.idleCount());
+        r0.close();
+        // after releasing one ref, we should see only the unused count go up.
+        assertEquals(3, cache.size());
+        assertEquals(1, cache.idleCount());
+        r1.close();
+
+        assertEquals(3, cache.size());
+        assertEquals(2, cache.idleCount());
+
+        // this should do nothing
+        cache.clean();
+
+        assertEquals(3, cache.size());
+        assertEquals(2, cache.idleCount());
+
+        // this should force a cleanup
+        r3 = cache.getOrCreate("3", factory);
+        cache.clean();
+        assertEquals(2, cache.size());
+        assertEquals(0, cache.idleCount());
+
+        // check the expected methods were called on the factory
+        verify(factory).clean(0);
+        verify(factory).clean(1);
+        verify(factory, times(2)).clean(anyInt());
+    }
+
+    @Test
+    public void testMultiThreaded() throws Exception {
+        cache = new ReferenceCountedCache<>(factory, 15, 7);
+        int retrievers = 50;
+        int cleaners = 5;
+        startBarrier = new CyclicBarrier(retrievers + 1);
+        endBarrier = new CyclicBarrier(retrievers);
+        retrieving = true;
+        ExecutorService xs = Executors.newFixedThreadPool(retrievers + cleaners);
+        List<Future<List<Integer>>> retrievals = new ArrayList<>();
+        List<Future<Long>> cleanTallies = new ArrayList<>();
+
+        for (int i = 0; i < retrievers; i++)
+            retrievals.add(xs.submit(new Retriever(20)));
+        for (int i = 0; i < cleaners; i++)
+            cleanTallies.add(xs.submit(new Cleaner()));
+
+        startBarrier.await();
+        long cleaned = 0;
+        for (Future<Long> cleanTally : cleanTallies)
+            cleaned += cleanTally.get();
+
+        Set<Integer> results = newIdentityHashSet();
+        for (Future<List<Integer>> retrieval : retrievals)
+            results.addAll(retrieval.get());
+
+        Set<Integer> created = newIdentityHashSet(createdInts);
+
+        Set<Integer> deleted = newIdentityHashSet(deletedInts);
+
+        System.out.printf("%ncreated %d values", created.size());
+        System.out.printf("%ndeleted %d values", deleted.size());
+        System.out.printf("%nfetched %d values", results.size());
+        System.out.printf("%ncleaned %d values", cleaned);
+        System.out.printf("%nremaining entries: %s%n", cache.snapshot());
+
+        assertEquals(deleted.size(), cleaned);
+        assertEquals(created, unionByIdentity(deleted, cache.snapshot().values()));
+        assertEquals(created, results);
+    }
+
+    private static <T> Set<T> newIdentityHashSet() {
+        return Collections.newSetFromMap(new IdentityHashMap<T, Boolean>());
+    }
+
+    private static <T> Set<T> newIdentityHashSet(Collection<? extends T> c) {
+        Set<T> result = newIdentityHashSet();
+        result.addAll(c);
+        return result;
+    }
+
+    private static <T> Set<T> unionByIdentity(Collection<T>...collections) {
+        Set<T> result = newIdentityHashSet();
+        for(Collection<T> c : collections)
+            result.addAll(c);
+        return result;
+    }
+
+
+    class Retriever implements Callable<List<Integer>> {
+        final int bound;
+        final Random random = new Random();
+
+        Retriever(int bound) { this.bound = bound; }
+
+        @Override
+        public List<Integer> call() throws Exception {
+            List<Integer> list = new ArrayList<>();
+            try {
+                startBarrier.await();
+                for (int i = 0; i < 1_000; i++) {
+                    try (Reference<Integer> ref = cache.getOrCreate("" + random.nextInt(bound), factory)) {
+                        list.add(ref.get());
+                    }
+                }
+                endBarrier.await();
+                retrieving = false;
+            } catch (Throwable t) {
+                System.out.printf("Retriever aborted with %s.%n", t);
+                t.printStackTrace(System.out);
+            }
+            return list;
+
+        }
+    }
+
+    class Cleaner implements Callable<Long> {
+        @Override
+        public Long call() throws Exception {
+            long cleaned = 0;
+            while (retrieving) cleaned += cache.clean();
+            return cleaned;
+        }
+    }
+}
diff --git a/yoko-util/src/test/java/org/apache/yoko/util/concurrent/WeakConcurrentFifoTest.java b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/WeakConcurrentFifoTest.java
new file mode 100644
index 0000000..e7435e9
--- /dev/null
+++ b/yoko-util/src/test/java/org/apache/yoko/util/concurrent/WeakConcurrentFifoTest.java
@@ -0,0 +1,112 @@
+package org.apache.yoko.util.concurrent;
+
+import org.apache.yoko.util.KeyedFactory;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.*;
+
+public class WeakConcurrentFifoTest extends ConcurrentFifoTest {
+    // must not use a mock here because it will hold onto all its arguments strongly
+    private final KeyedFactory<String, Runnable> factory =  new KeyedFactory<String, Runnable>() {
+        public Runnable create(String key) {return cleanup;}
+    };
+
+    // must not use the @Mock annotation and Mockito's injection
+    // because it intermittently fails to count invocations correctly
+    private Runnable cleanup;
+    private ReferenceQueue<?> referenceQueue = new ReferenceQueue<>();
+
+    @Before
+    @Override
+    public void setupFifo() {
+        cleanup = mock(Runnable.class);
+        fifo = new WeakConcurrentFifo<>(factory);
+    }
+
+    @Test
+    public void testWeakRefsGetCollectedOnRemove() throws Exception {
+        WeakReference[] refs;
+
+        refs = enqueueStringsCollectably("foo", "foo", "bar", "bar", "bar", "bar");
+        fifo.put("baz"); // strings in constant pool are never GC'd
+
+        assertEquals(refs.length + 1, fifo.size());
+        assertEquals("foo", fifo.remove());
+        assertEquals(refs.length, fifo.size());
+
+        gcUntilCleared(refs);
+
+        verify(cleanup, times(0)).run();
+        assertEquals("baz", fifo.remove());
+        verify(cleanup, times(refs.length - 1)).run();
+    }
+
+    @Test
+    public void testWeakRefsGetCollectedOnPut() throws Exception {
+        WeakReference[] refs;
+
+        refs = enqueueStringsCollectably("foo", "foo", "bar", "bar", "bar", "bar");
+
+        assertEquals(refs.length, fifo.size());
+        assertEquals("foo", fifo.remove());
+        assertEquals(refs.length - 1, fifo.size());
+
+        gcUntilCleared(refs);
+
+        verify(cleanup, times(0)).run();
+        fifo.put("baz");
+        verify(cleanup, times(refs.length - 1)).run();
+        assertEquals("baz", fifo.remove());
+    }
+
+    @Test
+    public void testWeakRefsGetCollectedOnSize() throws Exception {
+        WeakReference[] refs;
+
+        refs = enqueueStringsCollectably("foo", "foo", "bar", "bar", "bar", "bar");
+
+        assertEquals(refs.length, fifo.size());
+        assertEquals("foo", fifo.remove());
+        assertEquals(refs.length - 1, fifo.size());
+
+        gcUntilCleared(refs);
+
+        verify(cleanup, times(0)).run();
+        assertEquals(0, fifo.size());
+        verify(cleanup, times(refs.length - 1)).run();
+    }
+
+    private WeakReference[] enqueueStringsCollectably(String... strings) {
+        WeakReference[] refs = new WeakReference[strings.length];
+        for (int i = 0 ; i < strings.length; i++) {
+            String s = new String(strings[i]);
+            refs[i] = new WeakReference(s, referenceQueue);
+            fifo.put(s);
+        }
+        return refs;
+    }
+
+    public void gcUntilCleared(WeakReference<?>... refs) throws Exception {
+        for (WeakReference<?> ref : refs) {
+            gcUntilCollected(ref);
+            referenceQueue.remove();
+        }
+    }
+
+    private static void gcUntilCollected(WeakReference<?> ref) {
+        while (ref.get() != null) {
+            System.out.print("gc ");
+            System.gc();
+        }
+        System.out.println();
+    }
+}