changeset 820:9205e980062a jdk-9+150

8164907: Eliminate dependency on java.naming/com.sun.jndi.toolkit.url Reviewed-by: chegar, rriggs
author prappo
date Mon, 19 Dec 2016 16:01:24 +0000
parents 56d764f5b735
children 78dcbb7f8a36 cc3e1333a56a
files src/java.corba/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtx.java src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtxFactory.java src/java.corba/share/classes/com/sun/jndi/cosnaming/CNNameParser.java src/java.corba/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java src/java.corba/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java src/java.corba/share/classes/com/sun/jndi/cosnaming/IiopUrl.java src/java.corba/share/classes/com/sun/jndi/cosnaming/OrbReuseTracker.java src/java.corba/share/classes/com/sun/jndi/cosnaming/RemoteToCorba.java src/java.corba/share/classes/com/sun/jndi/cosnaming/jndiprovider.properties src/java.corba/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java src/java.corba/share/classes/com/sun/jndi/url/corbaname/corbanameURLContextFactory.java src/java.corba/share/classes/com/sun/jndi/url/iiop/GenericURLContext.java src/java.corba/share/classes/com/sun/jndi/url/iiop/iiopURLContext.java src/java.corba/share/classes/com/sun/jndi/url/iiop/iiopURLContextFactory.java src/java.corba/share/classes/com/sun/jndi/url/iiopname/iiopnameURLContextFactory.java
diffstat 16 files changed, 3716 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.*;
+import javax.naming.spi.NamingManager;
+
+import java.util.NoSuchElementException;
+import java.util.Hashtable;
+
+import org.omg.CosNaming.*;
+
+/**
+  * Implements the JNDI NamingEnumeration interface for COS
+  * Naming. Gets hold of a list of bindings from the COS Naming Server
+  * and allows the client to iterate through them.
+  *
+  * @author Raj Krishnamurthy
+  * @author Rosanna Lee
+  */
+
+final class CNBindingEnumeration
+        implements NamingEnumeration<javax.naming.Binding> {
+
+    private static final int DEFAULT_BATCHSIZE = 100;
+    private BindingListHolder _bindingList; // list of bindings
+    private BindingIterator _bindingIter;   // iterator for getting list of bindings
+    private int counter;                    // pointer in _bindingList
+    private int batchsize = DEFAULT_BATCHSIZE;  // how many to ask for each time
+    private CNCtx _ctx;                     // ctx to list
+    private Hashtable<?,?> _env;            // environment for getObjectInstance
+    private boolean more = false;           // iterator done?
+    private boolean isLookedUpCtx = false;  // iterating on a context beneath this context ?
+
+    /**
+     * Creates a CNBindingEnumeration object.
+     * @param ctx Context to enumerate
+     */
+    CNBindingEnumeration(CNCtx ctx, boolean isLookedUpCtx, Hashtable<?,?> env) {
+        // Get batch size to use
+        String batch = (env != null ?
+            (String)env.get(javax.naming.Context.BATCHSIZE) : null);
+        if (batch != null) {
+            try {
+                batchsize = Integer.parseInt(batch);
+            } catch (NumberFormatException e) {
+                throw new IllegalArgumentException("Batch size not numeric: " + batch);
+            }
+        }
+        _ctx = ctx;
+        _ctx.incEnumCount();
+        this.isLookedUpCtx = isLookedUpCtx;
+        _env = env;
+        _bindingList = new BindingListHolder();
+        BindingIteratorHolder _bindingIterH = new BindingIteratorHolder();
+
+        // Perform listing and request that bindings be returned in _bindingIter
+        // Upon return,_bindingList returns a zero length list
+        _ctx._nc.list(0, _bindingList, _bindingIterH);
+
+        _bindingIter = _bindingIterH.value;
+
+        // Get first batch using _bindingIter
+        if (_bindingIter != null) {
+            more = _bindingIter.next_n(batchsize, _bindingList);
+        } else {
+            more = false;
+        }
+        counter = 0;
+    }
+
+    /**
+     * Returns the next binding in the list.
+     * @exception NamingException any naming exception.
+     */
+
+    public javax.naming.Binding next() throws NamingException {
+        if (more && counter >= _bindingList.value.length) {
+            getMore();
+        }
+        if (more && counter < _bindingList.value.length) {
+            org.omg.CosNaming.Binding bndg = _bindingList.value[counter];
+            counter++;
+            return mapBinding(bndg);
+        } else {
+            throw new NoSuchElementException();
+        }
+    }
+
+
+    /**
+    * Returns true or false depending on whether there are more bindings.
+    * @return boolean value
+    */
+
+    public boolean hasMore() throws NamingException {
+        // If there's more, check whether current bindingList has been exhausted,
+        // and if so, try to get more.
+        // If no more, just say so.
+        return more ? (counter < _bindingList.value.length || getMore()) : false;
+    }
+
+    /**
+     * Returns true or false depending on whether there are more bindings.
+     * Need to define this to satisfy the Enumeration api requirement.
+     * @return boolean value
+     */
+
+    public boolean hasMoreElements() {
+        try {
+            return hasMore();
+        } catch (NamingException e) {
+            return false;
+        }
+    }
+
+    /**
+    * Returns the next binding in the list.
+    * @exception NoSuchElementException Thrown when the end of the
+    * list is reached.
+    */
+
+    public javax.naming.Binding nextElement() {
+        try {
+            return next();
+        } catch (NamingException ne) {
+            throw new NoSuchElementException();
+        }
+    }
+
+    public void close() throws NamingException {
+        more = false;
+        if (_bindingIter != null) {
+            _bindingIter.destroy();
+            _bindingIter = null;
+        }
+        if (_ctx != null) {
+            _ctx.decEnumCount();
+
+            /**
+             * context was obtained by CNCtx, the user doesn't have a handle to
+             * it, close it as we are done enumerating through the context
+             */
+            if (isLookedUpCtx) {
+                _ctx.close();
+            }
+            _ctx = null;
+        }
+    }
+
+    protected void finalize() {
+        try {
+            close();
+        } catch (NamingException e) {
+            // ignore failures
+        }
+    }
+
+    /**
+     * Get the next batch using _bindingIter. Update the 'more' field.
+     */
+    private boolean getMore() throws NamingException {
+        try {
+            more = _bindingIter.next_n(batchsize, _bindingList);
+            counter = 0; // reset
+        } catch (Exception e) {
+            more = false;
+            NamingException ne = new NamingException(
+                "Problem getting binding list");
+            ne.setRootCause(e);
+            throw ne;
+        }
+        return more;
+    }
+
+    /**
+    * Constructs a JNDI Binding object from the COS Naming binding
+    * object.
+    * @exception NameNotFound No objects under the name.
+    * @exception CannotProceed Unable to obtain a continuation context
+    * @exception InvalidName Name not understood.
+    * @exception NamingException One of the above.
+    */
+
+    private javax.naming.Binding mapBinding(org.omg.CosNaming.Binding bndg)
+                throws NamingException {
+        java.lang.Object obj = _ctx.callResolve(bndg.binding_name);
+
+        Name cname = CNNameParser.cosNameToName(bndg.binding_name);
+
+        try {
+            obj = NamingManager.getObjectInstance(obj, cname, _ctx, _env);
+        } catch (NamingException e) {
+            throw e;
+        } catch (Exception e) {
+            NamingException ne = new NamingException(
+                        "problem generating object using object factory");
+            ne.setRootCause(e);
+            throw ne;
+        }
+
+        // Use cname.toString() instead of bindingName because the name
+        // in the binding should be a composite name
+        String cnameStr = cname.toString();
+        javax.naming.Binding jbndg = new javax.naming.Binding(cnameStr, obj);
+
+        NameComponent[] comps = _ctx.makeFullName(bndg.binding_name);
+        String fullName = CNNameParser.cosNameToInsString(comps);
+        jbndg.setNameInNamespace(fullName);
+        return jbndg;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtx.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,1158 @@
+/*
+ * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.*;
+import javax.naming.spi.NamingManager;
+import javax.naming.spi.ResolveResult;
+
+import java.util.Hashtable;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import org.omg.CosNaming.*;
+import org.omg.CosNaming.NamingContextPackage.*;
+import org.omg.CORBA.*;
+
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
+// Needed for creating default ORB
+import java.applet.Applet;
+
+/**
+  * Provides a bridge to the CosNaming server provided by
+  * JavaIDL. This class provides the InitialContext from CosNaming.
+  *
+  * @author Raj Krishnamurthy
+  * @author Rosanna Lee
+  */
+
+public class CNCtx implements javax.naming.Context {
+
+    private final static boolean debug = false;
+
+    /*
+     * Implement one shared ORB among all CNCtx.  However, there is a public constructor
+     * accepting an ORB, so we need the option of using a given ORB.
+     */
+    private static ORB _defaultOrb;
+    ORB _orb;                   // used by ExceptionMapper and RMI/IIOP factory
+    public NamingContext _nc;   // public for accessing underlying NamingContext
+
+    private synchronized static ORB getDefaultOrb() {
+        if (_defaultOrb == null) {
+            _defaultOrb = CorbaUtils.getOrb(null, -1,
+               new Hashtable<String, java.lang.Object>());
+        }
+        return _defaultOrb;
+    }
+
+    private NameComponent[] _name = null;
+
+    Hashtable<String, java.lang.Object> _env; // used by ExceptionMapper
+    static final CNNameParser parser = new CNNameParser();
+
+    private static final String FED_PROP = "com.sun.jndi.cosnaming.federation";
+    boolean federation = false;
+
+    // Reference counter for tracking _orb references
+    OrbReuseTracker orbTracker = null;
+    int enumCount;
+    boolean isCloseCalled = false;
+
+    /**
+      * Create a CNCtx object. Gets the initial naming
+      * reference for the COS Naming Service from the ORB.
+      * The ORB can be passed in via the java.naming.corba.orb property
+      * or be created using properties in the environment properties.
+      * @param env Environment properties for initializing name service.
+      * @exception NamingException Cannot initialize ORB or naming context.
+      */
+    @SuppressWarnings("unchecked")
+    CNCtx(Hashtable<?,?> env) throws NamingException {
+        if (env != null) {
+            env = (Hashtable<?,?>)env.clone();
+        }
+        _env = (Hashtable<String, java.lang.Object>)env;
+        federation = "true".equals(env != null ? env.get(FED_PROP) : null);
+        initOrbAndRootContext(env);
+    }
+
+    private CNCtx() {
+    }
+
+    /**
+     * This method is used by the iiop and iiopname URL Context factories.
+     */
+    @SuppressWarnings("unchecked")
+    public static ResolveResult createUsingURL(String url, Hashtable<?,?> env)
+    throws NamingException {
+        CNCtx ctx = new CNCtx();
+        if (env != null) {
+            env = (Hashtable<?,?>) env.clone();
+        }
+        ctx._env = (Hashtable<String, java.lang.Object>)env;
+        String rest = ctx.initUsingUrl(
+            env != null ?
+                (org.omg.CORBA.ORB) env.get("java.naming.corba.orb")
+                : null,
+            url, env);
+
+        // rest is the INS name
+        // Return the parsed form to prevent subsequent lookup
+        // from parsing the string as a composite name
+        // The caller should be aware that a toString() of the name,
+        // which came from the environment will yield its INS syntax,
+        // rather than a composite syntax
+        return new ResolveResult(ctx, parser.parse(rest));
+    }
+
+    /**
+      * Creates a CNCtx object which supports the javax.naming
+      * apis given a COS Naming Context object.
+      * @param orb The ORB used by this context
+      * @param tracker The ORB reuse tracker for tracking references to the
+      *  orb object
+      * @param nctx The COS NamingContext object associated with this context
+      * @param name The name of this context relative to the root
+      */
+
+    CNCtx(ORB orb, OrbReuseTracker tracker, NamingContext nctx,
+          Hashtable<String, java.lang.Object> env, NameComponent[]name)
+        throws NamingException {
+            if (orb == null || nctx == null)
+                throw new ConfigurationException(
+                    "Must supply ORB or NamingContext");
+            if (orb != null) {
+                _orb = orb;
+            } else {
+                _orb = getDefaultOrb();
+            }
+            _nc = nctx;
+            _env = env;
+            _name = name;
+            federation = "true".equals(env != null ? env.get(FED_PROP) : null);
+    }
+
+    NameComponent[] makeFullName(NameComponent[] child) {
+        if (_name == null || _name.length == 0) {
+            return child;
+        }
+        NameComponent[] answer = new NameComponent[_name.length+child.length];
+
+        // parent
+        System.arraycopy(_name, 0, answer, 0, _name.length);
+
+        // child
+        System.arraycopy(child, 0, answer, _name.length, child.length);
+        return answer;
+    }
+
+
+    public String getNameInNamespace() throws NamingException {
+        if (_name == null || _name.length == 0) {
+            return "";
+        }
+        return CNNameParser.cosNameToInsString(_name);
+    }
+
+    /**
+     * These are the URL schemes that need to be processed.
+     * IOR and corbaloc URLs can be passed directly to ORB.string_to_object()
+     */
+    private static boolean isCorbaUrl(String url) {
+        return url.startsWith("iiop://")
+            || url.startsWith("iiopname://")
+            || url.startsWith("corbaname:")
+            ;
+    }
+
+    /**
+      * Initializes the COS Naming Service.
+      * This method initializes the three instance fields:
+      * _nc : The root naming context.
+      * _orb: The ORB to use for connecting RMI/IIOP stubs and for
+      *       getting the naming context (_nc) if one was not specified
+      *       explicitly via PROVIDER_URL.
+      * _name: The name of the root naming context.
+      *<p>
+      * _orb is obtained from java.naming.corba.orb if it has been set.
+      * Otherwise, _orb is created using the host/port from PROVIDER_URL
+      * (if it contains an "iiop" or "iiopname" URL), or from initialization
+      * properties specified in env.
+      *<p>
+      * _nc is obtained from the IOR stored in PROVIDER_URL if it has been
+      * set and does not contain an "iiop" or "iiopname" URL. It can be
+      * a stringified IOR, "corbaloc" URL, "corbaname" URL,
+      * or a URL (such as file/http/ftp) to a location
+      * containing a stringified IOR. If PROVIDER_URL has not been
+      * set in this way, it is obtained from the result of
+      *     ORB.resolve_initial_reference("NameService");
+      *<p>
+      * _name is obtained from the "iiop", "iiopname", or "corbaname" URL.
+      * It is the empty name by default.
+      *
+      * @param env Environment The possibly null environment.
+      * @exception NamingException When an error occurs while initializing the
+      * ORB or the naming context.
+      */
+    private void initOrbAndRootContext(Hashtable<?,?> env) throws NamingException {
+        org.omg.CORBA.ORB inOrb = null;
+        String ncIor = null;
+
+        if (inOrb == null && env != null) {
+            inOrb = (org.omg.CORBA.ORB) env.get("java.naming.corba.orb");
+        }
+
+        if (inOrb == null)
+            inOrb = getDefaultOrb(); // will create a default ORB if none exists
+
+        // Extract PROVIDER_URL from environment
+        String provUrl = null;
+        if (env != null) {
+            provUrl = (String)env.get(javax.naming.Context.PROVIDER_URL);
+        }
+
+        if (provUrl != null && !isCorbaUrl(provUrl)) {
+            // Initialize the root naming context by using the IOR supplied
+            // in the PROVIDER_URL
+            ncIor = getStringifiedIor(provUrl);
+            setOrbAndRootContext(inOrb, ncIor);
+        } else if (provUrl != null) {
+            // Initialize the root naming context by using the URL supplied
+            // in the PROVIDER_URL
+            String insName = initUsingUrl(inOrb, provUrl, env);
+
+            // If name supplied in URL, resolve it to a NamingContext
+            if (insName.length() > 0) {
+                _name = CNNameParser.nameToCosName(parser.parse(insName));
+                try {
+                    org.omg.CORBA.Object obj = _nc.resolve(_name);
+                    _nc = NamingContextHelper.narrow(obj);
+                    if (_nc == null) {
+                        throw new ConfigurationException(insName +
+                            " does not name a NamingContext");
+                    }
+                } catch (org.omg.CORBA.BAD_PARAM e) {
+                    throw new ConfigurationException(insName +
+                        " does not name a NamingContext");
+                } catch (Exception e) {
+                    throw ExceptionMapper.mapException(e, this, _name);
+                }
+            }
+        } else {
+            // No PROVIDER_URL supplied; initialize using defaults
+            if (debug) {
+                System.err.println("Getting default ORB: " + inOrb + env);
+            }
+            setOrbAndRootContext(inOrb, (String)null);
+        }
+    }
+
+
+    private String initUsingUrl(ORB orb, String url, Hashtable<?,?> env)
+        throws NamingException {
+        if (url.startsWith("iiop://") || url.startsWith("iiopname://")) {
+            return initUsingIiopUrl(orb, url, env);
+        } else {
+            return initUsingCorbanameUrl(orb, url, env);
+        }
+    }
+
+    /**
+     * Handles "iiop" and "iiopname" URLs (INS 98-10-11)
+     */
+    private String initUsingIiopUrl(ORB defOrb, String url, Hashtable<?,?> env)
+        throws NamingException {
+
+        if (defOrb == null)
+            defOrb = getDefaultOrb();
+
+        try {
+            IiopUrl parsedUrl = new IiopUrl(url);
+
+            NamingException savedException = null;
+
+            for (IiopUrl.Address addr : parsedUrl.getAddresses()) {
+
+                try {
+                    try {
+                        String tmpUrl = "corbaloc:iiop:" + addr.host
+                            + ":" + addr.port + "/NameService";
+                        if (debug) {
+                            System.err.println("Using url: " + tmpUrl);
+                        }
+                        org.omg.CORBA.Object rootCtx =
+                            defOrb.string_to_object(tmpUrl);
+                        setOrbAndRootContext(defOrb, rootCtx);
+                        return parsedUrl.getStringName();
+                    } catch (Exception e) {} // keep going
+
+                    // Get ORB
+                    if (debug) {
+                        System.err.println("Getting ORB for " + addr.host
+                            + " and port " + addr.port);
+                    }
+
+                    // Assign to fields
+                    setOrbAndRootContext(defOrb, (String)null);
+                    return parsedUrl.getStringName();
+
+                } catch (NamingException ne) {
+                    savedException = ne;
+                }
+            }
+            if (savedException != null) {
+                throw savedException;
+            } else {
+                throw new ConfigurationException("Problem with URL: " + url);
+            }
+        } catch (MalformedURLException e) {
+            throw new ConfigurationException(e.getMessage());
+        }
+    }
+
+    /**
+     * Initializes using "corbaname" URL (INS 99-12-03)
+     */
+    private String initUsingCorbanameUrl(ORB orb, String url, Hashtable<?,?> env)
+        throws NamingException {
+
+        if (orb == null)
+                orb = getDefaultOrb();
+
+        try {
+            CorbanameUrl parsedUrl = new CorbanameUrl(url);
+
+            String corbaloc = parsedUrl.getLocation();
+            String cosName = parsedUrl.getStringName();
+
+            setOrbAndRootContext(orb, corbaloc);
+
+            return parsedUrl.getStringName();
+        } catch (MalformedURLException e) {
+            throw new ConfigurationException(e.getMessage());
+        }
+    }
+
+    private void setOrbAndRootContext(ORB orb, String ncIor)
+        throws NamingException {
+        _orb = orb;
+        try {
+            org.omg.CORBA.Object ncRef;
+            if (ncIor != null) {
+                if (debug) {
+                    System.err.println("Passing to string_to_object: " + ncIor);
+                }
+                ncRef = _orb.string_to_object(ncIor);
+            } else {
+                ncRef = _orb.resolve_initial_references("NameService");
+            }
+            if (debug) {
+                System.err.println("Naming Context Ref: " + ncRef);
+            }
+            _nc = NamingContextHelper.narrow(ncRef);
+            if (_nc == null) {
+                if (ncIor != null) {
+                    throw new ConfigurationException(
+                        "Cannot convert IOR to a NamingContext: " + ncIor);
+                } else {
+                    throw new ConfigurationException(
+"ORB.resolve_initial_references(\"NameService\") does not return a NamingContext");
+                }
+            }
+        } catch (org.omg.CORBA.ORBPackage.InvalidName in) {
+            NamingException ne =
+                new ConfigurationException(
+"COS Name Service not registered with ORB under the name 'NameService'");
+            ne.setRootCause(in);
+            throw ne;
+        } catch (org.omg.CORBA.COMM_FAILURE e) {
+            NamingException ne =
+                new CommunicationException("Cannot connect to ORB");
+            ne.setRootCause(e);
+            throw ne;
+        } catch (org.omg.CORBA.BAD_PARAM e) {
+            NamingException ne = new ConfigurationException(
+                "Invalid URL or IOR: " + ncIor);
+            ne.setRootCause(e);
+            throw ne;
+        } catch (org.omg.CORBA.INV_OBJREF e) {
+            NamingException ne = new ConfigurationException(
+                "Invalid object reference: " + ncIor);
+            ne.setRootCause(e);
+            throw ne;
+        }
+    }
+
+    private void setOrbAndRootContext(ORB orb, org.omg.CORBA.Object ncRef)
+        throws NamingException {
+        _orb = orb;
+        try {
+            _nc = NamingContextHelper.narrow(ncRef);
+            if (_nc == null) {
+                throw new ConfigurationException(
+                    "Cannot convert object reference to NamingContext: " + ncRef);
+            }
+        } catch (org.omg.CORBA.COMM_FAILURE e) {
+            NamingException ne =
+                new CommunicationException("Cannot connect to ORB");
+            ne.setRootCause(e);
+            throw ne;
+        }
+    }
+
+    private String getStringifiedIor(String url) throws NamingException {
+        if (url.startsWith("IOR:") || url.startsWith("corbaloc:")) {
+            return url;
+        } else {
+            InputStream in = null;
+            try {
+                URL u = new URL(url);
+                in = u.openStream();
+                if (in != null) {
+                    BufferedReader bufin =
+                        new BufferedReader(new InputStreamReader(in, "8859_1"));
+                    String str;
+                    while ((str = bufin.readLine()) != null) {
+                        if (str.startsWith("IOR:")) {
+                            return str;
+                        }
+                    }
+                }
+            } catch (IOException e) {
+                NamingException ne =
+                    new ConfigurationException("Invalid URL: " + url);
+                ne.setRootCause(e);
+                throw ne;
+            } finally {
+                try {
+                    if (in != null) {
+                        in.close();
+                    }
+                } catch (IOException e) {
+                    NamingException ne =
+                        new ConfigurationException("Invalid URL: " + url);
+                    ne.setRootCause(e);
+                    throw ne;
+                }
+            }
+            throw new ConfigurationException(url + " does not contain an IOR");
+        }
+    }
+
+
+    /**
+      * Does the job of calling the COS Naming API,
+      * resolve, and performs the exception mapping. If the resolved
+      * object is a COS Naming Context (sub-context), then this function
+      * returns a new JNDI naming context object.
+      * @param path the NameComponent[] object.
+      * @exception NotFound No objects under the name.
+      * @exception CannotProceed Unable to obtain a continuation context
+      * @exception InvalidName Name not understood.
+      * @return Resolved object returned by the COS Name Server.
+      */
+    java.lang.Object callResolve(NameComponent[] path)
+        throws NamingException {
+            try {
+                org.omg.CORBA.Object obj = _nc.resolve(path);
+                try {
+                    NamingContext nc =
+                        NamingContextHelper.narrow(obj);
+                    if (nc != null) {
+                        return new CNCtx(_orb, orbTracker, nc, _env,
+                                        makeFullName(path));
+                    } else {
+                        return obj;
+                    }
+                } catch (org.omg.CORBA.SystemException e) {
+                    return obj;
+                }
+            } catch (Exception e) {
+                throw ExceptionMapper.mapException(e, this, path);
+            }
+    }
+
+    /**
+      * Converts the "String" name into a CompositeName
+      * returns the object resolved by the COS Naming api,
+      * resolve. Returns the current context if the name is empty.
+      * Returns either an org.omg.CORBA.Object or javax.naming.Context object.
+      * @param name string used to resolve the object.
+      * @exception NamingException See callResolve.
+      * @return the resolved object
+      */
+    public java.lang.Object lookup(String name) throws NamingException {
+        if (debug) {
+            System.out.println("Looking up: " + name);
+        }
+        return lookup(new CompositeName(name));
+    }
+
+    /**
+      * Converts the "Name" name into a NameComponent[] object and
+      * returns the object resolved by the COS Naming api,
+      * resolve. Returns the current context if the name is empty.
+      * Returns either an org.omg.CORBA.Object or javax.naming.Context object.
+      * @param name JNDI Name used to resolve the object.
+      * @exception NamingException See callResolve.
+      * @return the resolved object
+      */
+    public java.lang.Object lookup(Name name)
+        throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            if (name.size() == 0 )
+                return this; // %%% should clone() so that env can be changed
+            NameComponent[] path = CNNameParser.nameToCosName(name);
+
+            try {
+                java.lang.Object answer = callResolve(path);
+
+                try {
+                    return NamingManager.getObjectInstance(answer, name, this, _env);
+                } catch (NamingException e) {
+                    throw e;
+                } catch (Exception e) {
+                    NamingException ne = new NamingException(
+                        "problem generating object using object factory");
+                    ne.setRootCause(e);
+                    throw ne;
+                }
+            } catch (CannotProceedException cpe) {
+                javax.naming.Context cctx = getContinuationContext(cpe);
+                return cctx.lookup(cpe.getRemainingName());
+            }
+    }
+
+    /**
+      * Performs bind or rebind in the context depending on whether the
+      * flag rebind is set. The only objects allowed to be bound are of
+      * types org.omg.CORBA.Object, org.omg.CosNaming.NamingContext.
+      * You can use a state factory to turn other objects (such as
+      * Remote) into these acceptable forms.
+      *
+      * Uses the COS Naming apis bind/rebind or
+      * bind_context/rebind_context.
+      * @param pth NameComponent[] object
+      * @param obj Object to be bound.
+      * @param rebind perform rebind ? if true performs a rebind.
+      * @exception NotFound No objects under the name.
+      * @exception CannotProceed Unable to obtain a continuation context
+      * @exception AlreadyBound An object is already bound to this name.
+      */
+    private void callBindOrRebind(NameComponent[] pth, Name name,
+        java.lang.Object obj, boolean rebind) throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            try {
+                // Call state factories to convert
+                obj = NamingManager.getStateToBind(obj, name, this, _env);
+
+                if (obj instanceof CNCtx) {
+                    // Use naming context object reference
+                    obj = ((CNCtx)obj)._nc;
+                }
+
+                if ( obj instanceof org.omg.CosNaming.NamingContext) {
+                    NamingContext nobj =
+                        NamingContextHelper.narrow((org.omg.CORBA.Object)obj);
+                    if (rebind)
+                        _nc.rebind_context(pth,nobj);
+                    else
+                        _nc.bind_context(pth,nobj);
+
+                } else if (obj instanceof org.omg.CORBA.Object) {
+                    if (rebind)
+                        _nc.rebind(pth,(org.omg.CORBA.Object)obj);
+                    else
+                        _nc.bind(pth,(org.omg.CORBA.Object)obj);
+                }
+                else
+                    throw new IllegalArgumentException(
+                "Only instances of org.omg.CORBA.Object can be bound");
+            } catch (BAD_PARAM e) {
+                // probably narrow() failed?
+                NamingException ne = new NotContextException(name.toString());
+                ne.setRootCause(e);
+                throw ne;
+            } catch (Exception e) {
+                throw ExceptionMapper.mapException(e, this, pth);
+            }
+    }
+
+    /**
+      * Converts the "Name" name into a NameComponent[] object and
+      * performs the bind operation. Uses callBindOrRebind. Throws an
+      * invalid name exception if the name is empty. We need a name to
+      * bind the object even when we work within the current context.
+      * @param name JNDI Name object
+      * @param obj Object to be bound.
+      * @exception NamingException See callBindOrRebind
+      */
+    public  void bind(Name name, java.lang.Object obj)
+        throws NamingException {
+            if (name.size() == 0 ) {
+                throw new InvalidNameException("Name is empty");
+            }
+
+            if (debug) {
+                System.out.println("Bind: " + name);
+            }
+            NameComponent[] path = CNNameParser.nameToCosName(name);
+
+            try {
+                callBindOrRebind(path, name, obj, false);
+            } catch (CannotProceedException e) {
+                javax.naming.Context cctx = getContinuationContext(e);
+                cctx.bind(e.getRemainingName(), obj);
+            }
+    }
+
+    static private javax.naming.Context
+        getContinuationContext(CannotProceedException cpe)
+        throws NamingException {
+        try {
+            return NamingManager.getContinuationContext(cpe);
+        } catch (CannotProceedException e) {
+            java.lang.Object resObj = e.getResolvedObj();
+            if (resObj instanceof Reference) {
+                Reference ref = (Reference)resObj;
+                RefAddr addr = ref.get("nns");
+                if (addr.getContent() instanceof javax.naming.Context) {
+                    NamingException ne = new NameNotFoundException(
+                        "No object reference bound for specified name");
+                    ne.setRootCause(cpe.getRootCause());
+                    ne.setRemainingName(cpe.getRemainingName());
+                    throw ne;
+                }
+            }
+            throw e;
+        }
+    }
+
+    /**
+      * Converts the "String" name into a CompositeName object and
+      * performs the bind operation. Uses callBindOrRebind. Throws an
+      * invalid name exception if the name is empty.
+      * @param name string
+      * @param obj Object to be bound.
+      * @exception NamingException See callBindOrRebind
+      */
+    public void bind(String name, java.lang.Object obj) throws NamingException {
+        bind(new CompositeName(name), obj);
+    }
+
+    /**
+      * Converts the "Name" name into a NameComponent[] object and
+      * performs the rebind operation. Uses callBindOrRebind. Throws an
+      * invalid name exception if the name is empty. We must have a name
+      * to rebind the object to even if we are working within the current
+      * context.
+      * @param name string
+      * @param obj Object to be bound.
+      * @exception NamingException See callBindOrRebind
+      */
+    public  void rebind(Name name, java.lang.Object obj)
+        throws NamingException {
+            if (name.size() == 0 ) {
+                throw new InvalidNameException("Name is empty");
+            }
+            NameComponent[] path = CNNameParser.nameToCosName(name);
+            try {
+                callBindOrRebind(path, name, obj, true);
+            } catch (CannotProceedException e) {
+                javax.naming.Context cctx = getContinuationContext(e);
+                cctx.rebind(e.getRemainingName(), obj);
+            }
+    }
+
+    /**
+      * Converts the "String" name into a CompositeName object and
+      * performs the rebind operation. Uses callBindOrRebind. Throws an
+      * invalid name exception if the name is an empty string.
+      * @param name string
+      * @param obj Object to be bound.
+      * @exception NamingException See callBindOrRebind
+      */
+    public  void rebind(String name, java.lang.Object obj)
+        throws NamingException {
+            rebind(new CompositeName(name), obj);
+    }
+
+    /**
+      * Calls the unbind api of COS Naming and uses the exception mapper
+      * class  to map the exceptions
+      * @param path NameComponent[] object
+      * @exception NotFound No objects under the name. If leaf
+      * is not found, that's OK according to the JNDI spec
+      * @exception CannotProceed Unable to obtain a continuation context
+      * @exception InvalidName Name not understood.
+      */
+    private void callUnbind(NameComponent[] path) throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            try {
+                _nc.unbind(path);
+            } catch (NotFound e) {
+                // If leaf is the one missing, return success
+                // as per JNDI spec
+
+                if (leafNotFound(e, path[path.length-1])) {
+                    // do nothing
+                } else {
+                    throw ExceptionMapper.mapException(e, this, path);
+                }
+            } catch (Exception e) {
+                throw ExceptionMapper.mapException(e, this, path);
+            }
+    }
+
+    private boolean leafNotFound(NotFound e, NameComponent leaf) {
+
+        // This test is not foolproof because some name servers
+        // always just return one component in rest_of_name
+        // so you might not be able to tell whether that is
+        // the leaf (e.g. aa/aa/aa, which one is missing?)
+
+        NameComponent rest;
+        return e.why.value() == NotFoundReason._missing_node &&
+            e.rest_of_name.length == 1 &&
+            (rest=e.rest_of_name[0]).id.equals(leaf.id) &&
+            (rest.kind == leaf.kind ||
+             (rest.kind != null && rest.kind.equals(leaf.kind)));
+    }
+
+    /**
+      * Converts the "String" name into a CompositeName object and
+      * performs the unbind operation. Uses callUnbind. If the name is
+      * empty, throws an invalid name exception. Do we unbind the
+      * current context (JNDI spec says work with the current context if
+      * the name is empty) ?
+      * @param name string
+      * @exception NamingException See callUnbind
+      */
+    public  void unbind(String name) throws NamingException {
+        unbind(new CompositeName(name));
+    }
+
+    /**
+      * Converts the "Name" name into a NameComponent[] object and
+      * performs the unbind operation. Uses callUnbind. Throws an
+      * invalid name exception if the name is empty.
+      * @param name string
+      * @exception NamingException See callUnbind
+      */
+    public  void unbind(Name name)
+        throws NamingException {
+            if (name.size() == 0 )
+                throw new InvalidNameException("Name is empty");
+            NameComponent[] path = CNNameParser.nameToCosName(name);
+            try {
+                callUnbind(path);
+            } catch (CannotProceedException e) {
+                javax.naming.Context cctx = getContinuationContext(e);
+                cctx.unbind(e.getRemainingName());
+            }
+    }
+
+    /**
+      * Renames an object. Since COS Naming does not support a rename
+      * api, this method unbinds the object with the "oldName" and
+      * creates a new binding.
+      * @param oldName string, existing name for the binding.
+      * @param newName string, name used to replace.
+      * @exception NamingException See bind
+      */
+    public  void rename(String oldName,String newName)
+        throws NamingException {
+            rename(new CompositeName(oldName), new CompositeName(newName));
+    }
+
+    /**
+      * Renames an object. Since COS Naming does not support a rename
+      * api, this method unbinds the object with the "oldName" and
+      * creates a new binding.
+      * @param oldName JNDI Name, existing name for the binding.
+      * @param newName JNDI Name, name used to replace.
+      * @exception NamingException See bind
+      */
+    public  void rename(Name oldName,Name newName)
+        throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            if (oldName.size() == 0 || newName.size() == 0)
+                throw new InvalidNameException("One or both names empty");
+            java.lang.Object obj = lookup(oldName);
+            bind(newName,obj);
+            unbind(oldName);
+    }
+
+    /**
+      * Returns a NameClassEnumeration object which has a list of name
+      * class pairs. Lists the current context if the name is empty.
+      * @param name string
+      * @exception NamingException All exceptions thrown by lookup
+      * with a non-null argument
+      * @return a list of name-class objects as a NameClassEnumeration.
+      */
+    public  NamingEnumeration<NameClassPair> list(String name) throws NamingException {
+            return list(new CompositeName(name));
+    }
+
+    /**
+      * Returns a NameClassEnumeration object which has a list of name
+      * class pairs. Lists the current context if the name is empty.
+      * @param name JNDI Name
+      * @exception NamingException All exceptions thrown by lookup
+      * @return a list of name-class objects as a NameClassEnumeration.
+      */
+    @SuppressWarnings("unchecked")
+    public  NamingEnumeration<NameClassPair> list(Name name)
+        throws NamingException {
+            return (NamingEnumeration)listBindings(name);
+    }
+
+    /**
+      * Returns a BindingEnumeration object which has a list of name
+      * object pairs. Lists the current context if the name is empty.
+      * @param name string
+      * @exception NamingException all exceptions returned by lookup
+      * @return a list of bindings as a BindingEnumeration.
+      */
+    public  NamingEnumeration<javax.naming.Binding> listBindings(String name)
+        throws NamingException {
+            return listBindings(new CompositeName(name));
+    }
+
+    /**
+      * Returns a BindingEnumeration object which has a list of name
+      * class pairs. Lists the current context if the name is empty.
+      * @param name JNDI Name
+      * @exception NamingException all exceptions returned by lookup.
+      * @return a list of bindings as a BindingEnumeration.
+      */
+    public  NamingEnumeration<javax.naming.Binding> listBindings(Name name)
+        throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            if (name.size() > 0) {
+                try {
+                    java.lang.Object obj = lookup(name);
+                    if (obj instanceof CNCtx) {
+                        return new CNBindingEnumeration(
+                                        (CNCtx) obj, true, _env);
+                    } else {
+                        throw new NotContextException(name.toString());
+                    }
+                } catch (NamingException ne) {
+                    throw ne;
+                } catch (BAD_PARAM e) {
+                    NamingException ne =
+                        new NotContextException(name.toString());
+                    ne.setRootCause(e);
+                    throw ne;
+                }
+            }
+            return new CNBindingEnumeration(this, false, _env);
+    }
+
+    /**
+      * Calls the destroy on the COS Naming Server
+      * @param nc The NamingContext object to use.
+      * @exception NotEmpty when the context is not empty and cannot be destroyed.
+      */
+    private void callDestroy(NamingContext nc)
+        throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            try {
+                nc.destroy();
+            } catch (Exception e) {
+                throw ExceptionMapper.mapException(e, this, null);
+            }
+    }
+
+    /**
+      * Uses the callDestroy function to destroy the context. If name is
+      * empty destroys the current context.
+      * @param name string
+      * @exception OperationNotSupportedException when list is invoked
+      * with a non-null argument
+      */
+    public  void destroySubcontext(String name) throws NamingException {
+        destroySubcontext(new CompositeName(name));
+    }
+
+    /**
+      * Uses the callDestroy function to destroy the context. Destroys
+      * the current context if name is empty.
+      * @param name JNDI Name
+      * @exception OperationNotSupportedException when list is invoked
+      * with a non-null argument
+      */
+    public  void destroySubcontext(Name name)
+        throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            NamingContext the_nc = _nc;
+            NameComponent[] path = CNNameParser.nameToCosName(name);
+            if ( name.size() > 0) {
+                try {
+                    javax.naming.Context ctx =
+                        (javax.naming.Context) callResolve(path);
+                    CNCtx cnc = (CNCtx)ctx;
+                    the_nc = cnc._nc;
+                    cnc.close(); //remove the reference to the context
+                } catch (ClassCastException e) {
+                    throw new NotContextException(name.toString());
+                } catch (CannotProceedException e) {
+                    javax.naming.Context cctx = getContinuationContext(e);
+                    cctx.destroySubcontext(e.getRemainingName());
+                    return;
+                } catch (NameNotFoundException e) {
+                    // If leaf is the one missing, return success
+                    // as per JNDI spec
+
+                    if (e.getRootCause() instanceof NotFound &&
+                        leafNotFound((NotFound)e.getRootCause(),
+                            path[path.length-1])) {
+                        return; // leaf missing OK
+                    }
+                    throw e;
+                } catch (NamingException e) {
+                    throw e;
+                }
+            }
+            callDestroy(the_nc);
+            callUnbind(path);
+    }
+
+    /**
+      * Calls the bind_new_context COS naming api to create a new subcontext.
+      * @param path NameComponent[] object
+      * @exception NotFound No objects under the name.
+      * @exception CannotProceed Unable to obtain a continuation context
+      * @exception InvalidName Name not understood.
+      * @exception AlreadyBound An object is already bound to this name.
+      * @return the new context object.
+      */
+    private javax.naming.Context callBindNewContext(NameComponent[] path)
+        throws NamingException {
+            if (_nc == null)
+                throw new ConfigurationException(
+                    "Context does not have a corresponding NamingContext");
+            try {
+                NamingContext nctx = _nc.bind_new_context(path);
+                return new CNCtx(_orb, orbTracker, nctx, _env,
+                                        makeFullName(path));
+            } catch (Exception e) {
+                throw ExceptionMapper.mapException(e, this, path);
+            }
+    }
+
+    /**
+      * Uses the callBindNewContext convenience function to create a new
+      * context. Throws an invalid name exception if the name is empty.
+      * @param name string
+      * @exception NamingException See callBindNewContext
+      * @return the new context object.
+      */
+    public  javax.naming.Context createSubcontext(String name)
+        throws NamingException {
+            return createSubcontext(new CompositeName(name));
+    }
+
+    /**
+      * Uses the callBindNewContext convenience function to create a new
+      * context. Throws an invalid name exception if the name is empty.
+      * @param name string
+      * @exception NamingException See callBindNewContext
+      * @return the new context object.
+      */
+    public  javax.naming.Context createSubcontext(Name name)
+        throws NamingException {
+            if (name.size() == 0 )
+                throw new InvalidNameException("Name is empty");
+            NameComponent[] path = CNNameParser.nameToCosName(name);
+            try {
+                return callBindNewContext(path);
+            } catch (CannotProceedException e) {
+                javax.naming.Context cctx = getContinuationContext(e);
+                return cctx.createSubcontext(e.getRemainingName());
+            }
+    }
+
+    /**
+      * Is mapped to resolve in the COS Naming api.
+      * @param name string
+      * @exception NamingException See lookup.
+      * @return the resolved object.
+      */
+    public  java.lang.Object lookupLink(String name) throws NamingException {
+            return lookupLink(new CompositeName(name));
+    }
+
+    /**
+      * Is mapped to resolve in the COS Naming api.
+      * @param name string
+      * @exception NamingException See lookup.
+      * @return the resolved object.
+      */
+    public  java.lang.Object lookupLink(Name name) throws NamingException {
+            return lookup(name);
+    }
+
+    /**
+      * Allow access to the name parser object.
+      * @param name JNDI name, is ignored since there is only one Name
+      * Parser object.
+      * @exception NamingException --
+      * @return NameParser object
+      */
+    public  NameParser getNameParser(String name) throws NamingException {
+        return parser;
+    }
+
+    /**
+      * Allow access to the name parser object.
+      * @param name JNDI name, is ignored since there is only one Name
+      * Parser object.
+      * @exception NamingException --
+      * @return NameParser object
+      */
+    public  NameParser getNameParser(Name name) throws NamingException {
+        return parser;
+    }
+
+    /**
+      * Returns the current environment.
+      * @return Environment.
+      */
+    @SuppressWarnings("unchecked")
+    public  Hashtable<String, java.lang.Object> getEnvironment() throws NamingException {
+        if (_env == null) {
+            return new Hashtable<>(5, 0.75f);
+        } else {
+            return (Hashtable<String, java.lang.Object>)_env.clone();
+        }
+    }
+
+    public String composeName(String name, String prefix) throws NamingException {
+        return composeName(new CompositeName(name),
+            new CompositeName(prefix)).toString();
+    }
+
+    public Name composeName(Name name, Name prefix) throws NamingException {
+        Name result = (Name)prefix.clone();
+        return result.addAll(name);
+    }
+
+    /**
+      * Adds to the environment for the current context.
+      * Record change but do not reinitialize ORB.
+      *
+      * @param propName The property name.
+      * @param propValue The ORB.
+      * @return the previous value of this property if any.
+      */
+    @SuppressWarnings("unchecked")
+    public java.lang.Object addToEnvironment(String propName,
+        java.lang.Object propValue)
+        throws NamingException {
+            if (_env == null) {
+                _env = new Hashtable<>(7, 0.75f);
+            } else {
+                // copy-on-write
+                _env = (Hashtable<String, java.lang.Object>)_env.clone();
+            }
+
+            return _env.put(propName, propValue);
+    }
+
+    // Record change but do not reinitialize ORB
+    @SuppressWarnings("unchecked")
+    public java.lang.Object removeFromEnvironment(String propName)
+        throws NamingException {
+            if (_env != null  && _env.get(propName) != null) {
+                // copy-on-write
+                _env = (Hashtable<String, java.lang.Object>)_env.clone();
+                return _env.remove(propName);
+            }
+            return null;
+    }
+
+    synchronized public void incEnumCount() {
+        enumCount++;
+        if (debug) {
+            System.out.println("incEnumCount, new count:" + enumCount);
+        }
+    }
+
+    synchronized public void decEnumCount()
+            throws NamingException {
+        enumCount--;
+        if (debug) {
+            System.out.println("decEnumCount, new count:" + enumCount +
+                        "    isCloseCalled:" + isCloseCalled);
+        }
+        if ((enumCount == 0) && isCloseCalled) {
+            close();
+        }
+    }
+
+    synchronized public void close() throws NamingException {
+
+        if (enumCount > 0) {
+            isCloseCalled = true;
+            return;
+        }
+
+        // Never destroy an orb in CNCtx.
+        // The orb we have is either the shared/default orb, or one passed in to a constructor
+        // from elsewhere, so that orb is somebody else's responsibility.
+    }
+
+    protected void finalize() {
+        try {
+            close();
+        } catch (NamingException e) {
+            // ignore failures
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtxFactory.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.*;
+
+import java.util.Hashtable;
+
+/**
+  * Implements the JNDI SPI InitialContextFactory interface used to
+  * create  the InitialContext objects.
+  *
+  * @author Raj Krishnamurthy
+  */
+
+public class CNCtxFactory implements InitialContextFactory {
+
+  /**
+    * Creates the InitialContext object. Properties parameter should
+    * should contain the ORB object for the value jndi.corba.orb.
+    * @param env Properties object
+    */
+
+  public Context getInitialContext(Hashtable<?,?> env) throws NamingException {
+      return new CNCtx(env);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/CNNameParser.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,500 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.*;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.omg.CosNaming.NameComponent;
+
+/**
+  * Parsing routines for NameParser as well as COS Naming stringified names.
+  * This is used by CNCtx to create a NameComponent[] object and vice versa.
+  * It follows Section 4.5 of Interoperable Naming Service (INS) 98-10-11.
+  * In summary, the stringified form is a left-to-right, forward-slash
+  * separated name. id and kinds are separated by '.'. backslash is the
+  * escape character.
+  *
+  * @author Rosanna Lee
+  */
+
+final public class CNNameParser implements NameParser {
+
+    private static final Properties mySyntax = new Properties();
+    private static final char kindSeparator = '.';
+    private static final char compSeparator = '/';
+    private static final char escapeChar = '\\';
+    static {
+        mySyntax.put("jndi.syntax.direction", "left_to_right");
+        mySyntax.put("jndi.syntax.separator", ""+compSeparator);
+        mySyntax.put("jndi.syntax.escape", ""+escapeChar);
+    };
+
+  /**
+    * Constructs a new name parser for parsing names in INS syntax.
+    */
+    public CNNameParser() {
+    }
+
+  /**
+    * Returns a CompoundName given a string in INS syntax.
+    * @param name The non-null string representation of the name.
+    * @return a non-null CompoundName
+    */
+    public Name parse(String name) throws NamingException {
+        Vector<String> comps = insStringToStringifiedComps(name);
+        return new CNCompoundName(comps.elements());
+    }
+
+    /**
+     * Creates a NameComponent[] from a Name structure.
+     * Used by CNCtx to convert the input Name arg into a NameComponent[].
+     * @param a CompoundName or a CompositeName;
+     * each component must be the stringified form of a NameComponent.
+     */
+    static NameComponent[] nameToCosName(Name name)
+        throws InvalidNameException {
+            int len = name.size();
+            if (len == 0) {
+                return new NameComponent[0];
+            }
+
+            NameComponent[] answer = new NameComponent[len];
+            for (int i = 0; i < len; i++) {
+                answer[i] = parseComponent(name.get(i));
+            }
+            return answer;
+    }
+
+    /**
+     * Returns the INS stringified form of a NameComponent[].
+     * Used by CNCtx.getNameInNamespace(), CNCompoundName.toString().
+     */
+    static String cosNameToInsString(NameComponent[] cname) {
+      StringBuilder str = new StringBuilder();
+      for ( int i = 0; i < cname.length; i++) {
+          if ( i > 0) {
+              str.append(compSeparator);
+          }
+          str.append(stringifyComponent(cname[i]));
+      }
+      return str.toString();
+    }
+
+    /**
+     * Creates a CompositeName from a NameComponent[].
+     * Used by ExceptionMapper and CNBindingEnumeration to convert
+     * a NameComponent[] into a composite name.
+     */
+    static Name cosNameToName(NameComponent[] cname) {
+        Name nm = new CompositeName();
+        for ( int i = 0; cname != null && i < cname.length; i++) {
+            try {
+                nm.add(stringifyComponent(cname[i]));
+            } catch (InvalidNameException e) {
+                // ignore
+            }
+        }
+        return nm;
+    }
+
+    /**
+     * Converts an INS-syntax string name into a Vector in which
+     * each element of the vector contains a stringified form of
+     * a NameComponent.
+     */
+    private static Vector<String> insStringToStringifiedComps(String str)
+        throws InvalidNameException {
+
+        int len = str.length();
+        Vector<String> components = new Vector<>(10);
+        char[] id = new char[len];
+        char[] kind = new char[len];
+        int idCount, kindCount;
+        boolean idMode;
+        for (int i = 0; i < len; ) {
+            idCount = kindCount = 0; // reset for new component
+            idMode = true;           // always start off parsing id
+            while (i < len) {
+                if (str.charAt(i) == compSeparator) {
+                    break;
+
+                } else if (str.charAt(i) == escapeChar) {
+                    if (i + 1 >= len) {
+                        throw new InvalidNameException(str +
+                            ": unescaped \\ at end of component");
+                    } else if (isMeta(str.charAt(i+1))) {
+                        ++i; // skip escape and let meta through
+                        if (idMode) {
+                            id[idCount++] = str.charAt(i++);
+                        } else {
+                            kind[kindCount++] = str.charAt(i++);
+                        }
+                    } else {
+                        throw new InvalidNameException(str +
+                            ": invalid character being escaped");
+                    }
+
+                } else if (idMode && str.charAt(i) == kindSeparator) {
+                    // just look for the first kindSeparator
+                    ++i; // skip kind separator
+                    idMode = false;
+
+                } else {
+                    if (idMode) {
+                        id[idCount++] = str.charAt(i++);
+                    } else {
+                        kind[kindCount++] = str.charAt(i++);
+                    }
+                }
+            }
+            components.addElement(stringifyComponent(
+                new NameComponent(new String(id, 0, idCount),
+                    new String(kind, 0, kindCount))));
+
+            if (i < len) {
+                ++i; // skip separator
+            }
+        }
+
+        return components;
+    }
+
+    /**
+     * Return a NameComponent given its stringified form.
+     */
+    private static NameComponent parseComponent(String compStr)
+    throws InvalidNameException {
+        NameComponent comp = new NameComponent();
+        int kindSep = -1;
+        int len = compStr.length();
+
+        int j = 0;
+        char[] newStr = new char[len];
+        boolean escaped = false;
+
+        // Find the kind separator
+        for (int i = 0; i < len && kindSep < 0; i++) {
+            if (escaped) {
+                newStr[j++] = compStr.charAt(i);
+                escaped = false;
+            } else if (compStr.charAt(i) == escapeChar) {
+                if (i + 1 >= len) {
+                    throw new InvalidNameException(compStr +
+                            ": unescaped \\ at end of component");
+                } else if (isMeta(compStr.charAt(i+1))) {
+                    escaped = true;
+                } else {
+                    throw new InvalidNameException(compStr +
+                        ": invalid character being escaped");
+                }
+            } else if (compStr.charAt(i) == kindSeparator) {
+                kindSep = i;
+            } else {
+                newStr[j++] = compStr.charAt(i);
+            }
+        }
+
+        // Set id
+        comp.id = new String(newStr, 0, j);
+
+        // Set kind
+        if (kindSep < 0) {
+            comp.kind = "";  // no kind separator
+        } else {
+            // unescape kind
+            j = 0;
+            escaped = false;
+            for (int i = kindSep+1; i < len; i++) {
+                if (escaped) {
+                    newStr[j++] = compStr.charAt(i);
+                    escaped = false;
+                } else if (compStr.charAt(i) == escapeChar) {
+                    if (i + 1 >= len) {
+                        throw new InvalidNameException(compStr +
+                            ": unescaped \\ at end of component");
+                    } else if (isMeta(compStr.charAt(i+1))) {
+                        escaped = true;
+                    } else {
+                        throw new InvalidNameException(compStr +
+                            ": invalid character being escaped");
+                    }
+                } else {
+                    newStr[j++] = compStr.charAt(i);
+                }
+            }
+            comp.kind = new String(newStr, 0, j);
+        }
+        return comp;
+    }
+
+    private static String stringifyComponent(NameComponent comp) {
+        StringBuilder one = new StringBuilder(escape(comp.id));
+        if (comp.kind != null && !comp.kind.equals("")) {
+            one.append(kindSeparator).append(escape(comp.kind));
+        }
+        if (one.length() == 0) {
+            return ""+kindSeparator;  // if neither id nor kind specified
+        } else {
+            return one.toString();
+        }
+    }
+
+    /**
+     * Returns a string with '.', '\', '/' escaped. Used when
+     * stringifying the name into its INS stringified form.
+     */
+    private static String escape(String str) {
+        if (str.indexOf(kindSeparator) < 0 &&
+            str.indexOf(compSeparator) < 0 &&
+            str.indexOf(escapeChar) < 0) {
+            return str;                         // no meta characters to escape
+        } else {
+            int len = str.length();
+            int j = 0;
+            char[] newStr = new char[len+len];
+            for (int i = 0; i < len; i++) {
+                if (isMeta(str.charAt(i))) {
+                    newStr[j++] = escapeChar;   // escape meta character
+                }
+                newStr[j++] = str.charAt(i);
+            }
+            return new String(newStr, 0, j);
+        }
+    }
+
+    /**
+     * In INS, there are three meta characters: '.', '/' and '\'.
+     */
+    private static boolean isMeta(char ch) {
+        switch (ch) {
+        case kindSeparator:
+        case compSeparator:
+        case escapeChar:
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * An implementation of CompoundName that bypasses the parsing
+     * and stringifying code of the default CompoundName.
+     */
+    static final class CNCompoundName extends CompoundName {
+        CNCompoundName(Enumeration<String> enum_) {
+            super(enum_, CNNameParser.mySyntax);
+        }
+
+        public Object clone() {
+            return new CNCompoundName(getAll());
+        }
+
+        public Name getPrefix(int posn) {
+            Enumeration<String> comps = super.getPrefix(posn).getAll();
+            return new CNCompoundName(comps);
+        }
+
+        public Name getSuffix(int posn) {
+            Enumeration<String> comps = super.getSuffix(posn).getAll();
+            return new CNCompoundName(comps);
+        }
+
+        public String toString() {
+            try {
+                // Convert Name to NameComponent[] then stringify
+                return cosNameToInsString(nameToCosName(this));
+            } catch (InvalidNameException e) {
+                return super.toString();
+            }
+        }
+
+        private static final long serialVersionUID = -6599252802678482317L;
+    }
+
+// for testing only
+/*
+    private static void print(String input) {
+        try {
+            System.out.println("\n >>>>>> input: " + input);
+
+            System.out.println("--Compound Name: ");
+            NameParser parser = new CNNameParser();
+            Name name = parser.parse(input);
+            for (int i = 0; i < name.size(); i++) {
+                System.out.println("\t" + i + ": " + name.get(i));
+                NameComponent cp = parseComponent(name.get(i));
+                System.out.println("\t\t" + "id: " + cp.id + ";kind: " + cp.kind);
+            }
+            System.out.println("\t" + name.toString());
+
+            System.out.println("--Composite Name: ");
+            Name composite = new CompositeName(input);
+            for (int i = 0; i < composite.size(); i++) {
+                System.out.println("\t" + i+": " + composite.get(i));
+            }
+            System.out.println("\t" + composite.toString());
+
+            System.out.println("--Composite To NameComponent");
+            NameComponent[] names = nameToCosName(composite);
+            for (int i = 0; i < composite.size(); i++) {
+                System.out.println("\t" + i+": id: " + names[i].id + "; kind: " + names[i].kind);
+            }
+            System.out.println("\t" + cosNameToInsString(names));
+        } catch (NamingException e) {
+            System.out.println(e);
+        }
+    }
+
+    private static void checkName(Name name, String[] comps) throws Exception {
+        if (name.size() != comps.length) {
+            throw new Exception(
+                "test failed; incorrect component count in " + name + "; " +
+                "expecting " + comps.length + " got " + name.size());
+        }
+        for (int i = 0; i < name.size(); i++) {
+            if (!comps[i].equals(name.get(i))) {
+                throw new Exception (
+                    "test failed; invalid component in " + name + "; " +
+                    "expecting '" + comps[i] + "' got '" + name.get(i) + "'");
+            }
+        }
+    }
+
+    private static void checkCompound(NameParser parser,
+        String input, String[] comps) throws Exception {
+        checkName(parser.parse(input), comps);
+    }
+
+    private static void checkComposite(String input, String[] comps)
+    throws Exception {
+        checkName(new CompositeName(input), comps);
+    }
+
+    private static String[] compounds = {
+        "a/b/c",
+        "a.b/c.d",
+        "a",
+        ".",
+        "a.",
+        "c.d",
+        ".e",
+        "a/x\\/y\\/z/b",
+        "a\\.b.c\\.d/e.f",
+        "a/b\\\\/c",
+        "x\\\\.y",
+        "x\\.y",
+        "x.\\\\y",
+        "x.y\\\\",
+        "\\\\x.y",
+        "a.b\\.c/d"
+    };
+    private static String[][] compoundComps = {
+        {"a", "b", "c"},
+        {"a.b", "c.d"},
+        {"a"},
+        {"."},
+        {"a"},
+        {"c.d"},
+        {".e"},
+        {"a", "x\\/y\\/z", "b"},
+        {"a\\.b.c\\.d", "e.f"},
+        {"a", "b\\\\", "c"},
+        {"x\\\\.y"},
+        {"x\\.y"},
+        {"x.\\\\y"},
+        {"x.y\\\\"},
+        {"\\\\x.y"},
+        {"a.b\\.c", "d"},
+    };
+
+    private static String[] composites = {
+        "a/b/c",
+        "a.b/c.d",
+        "a",
+        ".",
+        "a.",
+        "c.d",
+        ".e",
+        "a/x\\\\\\/y\\\\\\/z/b",
+        "a\\\\.b.c\\\\.d/e.f",
+        "a/b\\\\\\\\/c",
+        "x\\\\\\.y",
+        "x\\\\.y",
+        "x.\\\\\\\\y",
+        "x.y\\\\\\\\",
+        "\\\\\\\\x.y"
+    };
+
+    private static String[][] compositeComps = {
+        {"a", "b", "c"},
+        {"a.b", "c.d"},
+        {"a"},
+        {"."},
+        {"a."},  // unlike compound, kind sep is not consumed
+        {"c.d"},
+        {".e"},
+        {"a", "x\\/y\\/z", "b"},
+        {"a\\.b.c\\.d", "e.f"},
+        {"a", "b\\\\", "c"},
+        {"x\\\\.y"},
+        {"x\\.y"},
+        {"x.\\\\y"},
+        {"x.y\\\\"},
+        {"\\\\x.y"}
+    };
+
+    public static void main(String[] args) throws Exception {
+        if (args.length > 0) {
+            for (int i = 0; i < args.length; i++) {
+                print(args[0]);
+            }
+        } else {
+            print("x\\\\.y");
+            print("x\\.y");
+            print("x.\\\\y");
+            print("x.y\\\\");
+            print("\\\\x.y");
+        }
+
+        NameParser parser = new com.sun.jndi.cosnaming.CNNameParser();
+        for (int i = 0; i < compounds.length; i++) {
+            checkCompound(parser, compounds[i], compoundComps[i]);
+        }
+        for (int i = 0; i < composites.length; i++) {
+            checkComposite(composites[i], compositeComps[i]);
+        }
+
+        System.out.println("hardwire");
+        NameComponent[] foo = new NameComponent[1];
+        foo[0] = new NameComponent("foo\\", "bar");
+
+        System.out.println(cosNameToInsString(foo));
+        System.out.println(cosNameToName(foo));
+    }
+*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+
+import java.net.MalformedURLException;
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
+/**
+ * Extract components of a "corbaname" URL.
+ *
+ * The format of an corbaname URL is defined in INS 99-12-03 as follows.
+ * <pre>{@code
+ * corbaname url = "corbaname:" <corbaloc_obj> ["#" <string_name>]
+ * corbaloc_obj  = <obj_addr_list> ["/" <key_string>]
+ * obj_addr_list = as defined in a corbaloc URL
+ * key_string    = as defined in a corbaloc URL
+ * string_name   = stringified COS name | empty_string
+ * }</pre>
+ * Characters in {@code <string_name>} are escaped as follows.
+ * US-ASCII alphanumeric characters are not escaped. Any characters outside
+ * of this range are escaped except for the following:
+ * <pre>{@code
+ *        ; / : ? @ & = + $ , - _ . ! ~ * ; ( )
+ * }</pre>
+ * Escaped characters is escaped by using a % followed by its 2 hexadecimal
+ * numbers representing the octet.
+ * <p>
+ * The corbaname URL is parsed into two parts: a corbaloc URL and a COS name.
+ * The corbaloc URL is constructed by concatenation {@code "corbaloc:"} with
+ * {@code <corbaloc_obj>}.
+ * The COS name is {@code <string_name>} with the escaped characters resolved.
+ * <p>
+ * A corbaname URL is resolved by:
+ * <ol>
+ * <li>Construct a corbaloc URL by concatenating {@code "corbaloc:"} and {@code <corbaloc_obj>}.
+ * <li>Resolve the corbaloc URL to a NamingContext by using
+ * <pre>{@code
+ *     nctx = ORB.string_to_object(corbalocUrl);
+ * }</pre>
+ * <li>Resolve {@code <string_name>} in the NamingContext.
+ * </ol>
+ *
+ * @author Rosanna Lee
+ */
+
+public final class CorbanameUrl {
+    private String stringName;
+    private String location;
+
+    /**
+     * Returns a possibly empty but non-null string that is the "string_name"
+     * portion of the URL.
+     */
+    public String getStringName() {
+        return stringName;
+    }
+
+    public Name getCosName() throws NamingException {
+        return CNCtx.parser.parse(stringName);
+    }
+
+    public String getLocation() {
+        return "corbaloc:" + location;
+    }
+
+    public CorbanameUrl(String url) throws MalformedURLException {
+
+        if (!url.startsWith("corbaname:")) {
+            throw new MalformedURLException("Invalid corbaname URL: " + url);
+        }
+
+        int addrStart = 10;  // "corbaname:"
+
+        int addrEnd = url.indexOf('#', addrStart);
+        if (addrEnd < 0) {
+            addrEnd = url.length();
+            stringName = "";
+        } else {
+            stringName = CorbaUtils.decode(url.substring(addrEnd+1));
+        }
+        location = url.substring(addrStart, addrEnd);
+
+        int keyStart = location.indexOf('/');
+        if (keyStart >= 0) {
+            // Has key string
+            if (keyStart == (location.length() -1)) {
+                location += "NameService";
+            }
+        } else {
+            location += "/NameService";
+        }
+    }
+/*
+    // for testing only
+    public static void main(String[] args) {
+        try {
+            CorbanameUrl url = new CorbanameUrl(args[0]);
+
+            System.out.println("location: " + url.getLocation());
+            System.out.println("string name: " + url.getStringName());
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        }
+    }
+*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.*;
+import javax.naming.directory.*;
+import javax.naming.spi.*;
+
+import org.omg.CosNaming.*;
+import org.omg.CosNaming.NamingContextPackage.*;
+import org.omg.CORBA.*;
+
+/**
+  * A convenience class to map the COS Naming exceptions to the JNDI exceptions.
+  * @author Raj Krishnamurthy
+  */
+
+public final class ExceptionMapper {
+    private ExceptionMapper() {} // ensure no instance
+    private static final boolean debug = false;
+
+    public static final NamingException mapException(Exception e,
+        CNCtx ctx, NameComponent[] inputName) throws NamingException {
+        if (e instanceof NamingException) {
+            return (NamingException)e;
+        }
+
+        if (e instanceof RuntimeException) {
+            throw (RuntimeException)e;
+        }
+
+        NamingException ne;
+        if (e instanceof NotFound) {
+            if (ctx.federation) {
+                return tryFed((NotFound)e, ctx, inputName);
+
+            } else {
+                ne = new NameNotFoundException();
+            }
+
+        } else if (e instanceof CannotProceed) {
+
+            ne = new CannotProceedException();
+            NamingContext nc = ((CannotProceed) e).cxt;
+            NameComponent[] rest = ((CannotProceed) e).rest_of_name;
+
+            // %%% We assume that rest returns *all* unprocessed components.
+            // Don't' know if that is a good assumption, given
+            // NotFound doesn't set rest as expected. -RL
+            if (inputName != null && (inputName.length > rest.length)) {
+                NameComponent[] resolvedName =
+                    new NameComponent[inputName.length - rest.length];
+                System.arraycopy(inputName, 0, resolvedName, 0, resolvedName.length);
+                // Wrap resolved NamingContext inside a CNCtx
+                // Guess that its name (which is relative to ctx)
+                // is the part of inputName minus rest_of_name
+                ne.setResolvedObj(new CNCtx(ctx._orb, ctx.orbTracker, nc,
+                                                ctx._env,
+                    ctx.makeFullName(resolvedName)));
+            } else {
+                ne.setResolvedObj(ctx);
+            }
+
+            ne.setRemainingName(CNNameParser.cosNameToName(rest));
+
+        } else if (e instanceof InvalidName) {
+            ne = new InvalidNameException();
+        } else if (e instanceof AlreadyBound) {
+            ne = new NameAlreadyBoundException();
+        } else if (e instanceof NotEmpty) {
+            ne = new ContextNotEmptyException();
+        } else {
+            ne = new NamingException("Unknown reasons");
+        }
+
+        ne.setRootCause(e);
+        return ne;
+    }
+
+    private static final NamingException tryFed(NotFound e, CNCtx ctx,
+        NameComponent[] inputName) throws NamingException {
+        NameComponent[] rest = e.rest_of_name;
+
+        if (debug) {
+            System.out.println(e.why.value());
+            System.out.println(rest.length);
+        }
+
+        // %%% Using 1.2 & 1.3 Sun's tnameserv, 'rest' contains only the first
+        // component that failed, not *rest* as advertized. This is useless
+        // because what if you have something like aa/aa/aa/aa/aa.
+        // If one of those is not found, you get "aa" as 'rest'.
+        if (rest.length == 1 && inputName != null) {
+            // Check that we're not talking to 1.2/1.3 Sun tnameserv
+            NameComponent lastIn = inputName[inputName.length-1];
+            if (rest[0].id.equals(lastIn.id) &&
+                rest[0].kind != null &&
+                rest[0].kind.equals(lastIn.kind)) {
+                // Might be legit
+                ;
+            } else {
+                // Due to 1.2/1.3 bug that always returns single-item 'rest'
+                NamingException ne = new NameNotFoundException();
+                ne.setRemainingName(CNNameParser.cosNameToName(rest));
+                ne.setRootCause(e);
+                throw ne;
+            }
+        }
+        // Fixed in 1.4; perform calculations based on correct (1.4) behavior
+
+        // Calculate the components of the name that has been resolved
+        NameComponent[] resolvedName = null;
+        int len = 0;
+        if (inputName != null && (inputName.length >= rest.length)) {
+
+            if (e.why == NotFoundReason.not_context) {
+                // First component of rest is found but not a context; keep it
+                // as part of resolved name
+                len = inputName.length - (rest.length - 1);
+
+                // Remove resolved component from rest
+                if (rest.length == 1) {
+                    // No more remaining
+                    rest = null;
+                } else {
+                    NameComponent[] tmp = new NameComponent[rest.length-1];
+                    System.arraycopy(rest, 1, tmp, 0, tmp.length);
+                    rest = tmp;
+                }
+            } else {
+                len = inputName.length - rest.length;
+            }
+
+            if (len > 0) {
+                resolvedName = new NameComponent[len];
+                System.arraycopy(inputName, 0, resolvedName, 0, len);
+            }
+        }
+
+        // Create CPE and set common fields
+        CannotProceedException cpe = new CannotProceedException();
+        cpe.setRootCause(e);
+        if (rest != null && rest.length > 0) {
+            cpe.setRemainingName(CNNameParser.cosNameToName(rest));
+        }
+        cpe.setEnvironment(ctx._env);
+
+        if (debug) {
+            System.out.println("rest of name: " + cpe.getRemainingName());
+        }
+
+        // Lookup resolved name to get resolved object
+        final java.lang.Object resolvedObj =
+            (resolvedName != null) ? ctx.callResolve(resolvedName) : ctx;
+
+        if (resolvedObj instanceof javax.naming.Context) {
+            // obj is a context and child is not found
+            // try getting its nns dynamically by constructing
+            // a Reference containing obj.
+            RefAddr addr = new RefAddr("nns") {
+                public java.lang.Object getContent() {
+                    return resolvedObj;
+                }
+                private static final long serialVersionUID =
+                    669984699392133792L;
+            };
+            Reference ref = new Reference("java.lang.Object", addr);
+
+            // Resolved name has trailing slash to indicate nns
+            CompositeName cname = new CompositeName();
+            cname.add(""); // add trailing slash
+
+            cpe.setResolvedObj(ref);
+            cpe.setAltName(cname);
+            cpe.setAltNameCtx((javax.naming.Context)resolvedObj);
+
+            return cpe;
+        } else {
+            // Not a context, use object factory to transform object.
+
+            Name cname = CNNameParser.cosNameToName(resolvedName);
+            java.lang.Object resolvedObj2;
+            try {
+                resolvedObj2 = NamingManager.getObjectInstance(resolvedObj,
+                    cname, ctx, ctx._env);
+            } catch (NamingException ge) {
+                throw ge;
+            } catch (Exception ge) {
+                NamingException ne = new NamingException(
+                    "problem generating object using object factory");
+                ne.setRootCause(ge);
+                throw ne;
+            }
+
+            // If a context, continue operation with context
+            if (resolvedObj2 instanceof javax.naming.Context) {
+                cpe.setResolvedObj(resolvedObj2);
+            } else {
+                // Add trailing slash
+                cname.add("");
+                cpe.setAltName(cname);
+
+                // Create nns reference
+                final java.lang.Object rf2 = resolvedObj2;
+                RefAddr addr = new RefAddr("nns") {
+                    public java.lang.Object getContent() {
+                        return rf2;
+                    }
+                    private static final long serialVersionUID =
+                        -785132553978269772L;
+                };
+                Reference ref = new Reference("java.lang.Object", addr);
+                cpe.setResolvedObj(ref);
+                cpe.setAltNameCtx(ctx);
+            }
+            return cpe;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/IiopUrl.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+
+import java.net.MalformedURLException;
+import java.util.Vector;
+import java.util.StringTokenizer;
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
+/**
+ * Extract components of an "iiop" or "iiopname" URL.
+ *
+ * The format of an iiopname URL is defined in INS 98-10-11 as follows:
+ *
+ * <pre>
+ * iiopname url = "iiopname://" [addr_list]["/" string_name]
+ * addr_list    = [address ","]* address
+ * address      = [version host [":" port]]
+ * host         = DNS style host name | IP address
+ * version      = major "." minor "@" | empty_string
+ * port         = number
+ * major        = number
+ * minor        = number
+ * string_name  = stringified name | empty_string
+ * </pre>
+ *
+ * The default port is 9999. The default version is "1.0"
+ * US-ASCII alphanumeric characters are not escaped. Any characters outside
+ * of this range are escaped except for the following:
+ * <pre>{@code
+ * ; / : ? : @ & = + $ , - _ . ! ~ *  ' ( )
+ * }</pre>
+ * Escaped characters is escaped by using a % followed by its 2 hexadecimal
+ * numbers representing the octet.
+ *
+ * For backward compatibility,  the "iiop" URL as defined in INS 97-6-6
+ * is also supported:
+ * <pre>{@code
+ * iiop url     = "iiop://" [host [":" port]] ["/" string_name]
+ * }</pre>
+ * The default port is 900.
+ *
+ * @author Rosanna Lee
+ */
+
+public final class IiopUrl {
+    static final private int DEFAULT_IIOPNAME_PORT = 9999;
+    static final private int DEFAULT_IIOP_PORT = 900;
+    static final private String DEFAULT_HOST = "localhost";
+    private Vector<Address> addresses;
+    private String stringName;
+
+    public static class Address {
+        public int port = -1;
+        public int major, minor;
+        public String host;
+
+        public Address(String hostPortVers, boolean oldFormat)
+            throws MalformedURLException {
+            // [version host [":" port]]
+            int start;
+
+            // Parse version
+            int at;
+            if (oldFormat || (at = hostPortVers.indexOf('@')) < 0) {
+                major = 1;
+                minor = 0;
+                start = 0;     // start at the beginning
+            } else {
+                int dot = hostPortVers.indexOf('.');
+                if (dot < 0) {
+                    throw new MalformedURLException(
+                        "invalid version: " + hostPortVers);
+                }
+                try {
+                    major = Integer.parseInt(hostPortVers.substring(0, dot));
+                    minor = Integer.parseInt(hostPortVers.substring(dot+1, at));
+                } catch (NumberFormatException e) {
+                    throw new MalformedURLException(
+                        "Nonnumeric version: " + hostPortVers);
+                }
+                start = at + 1;  // skip '@' sign
+            }
+
+            // Parse host and port
+            int slash = hostPortVers.indexOf('/', start);
+            if (slash < 0) {
+                slash = hostPortVers.length();
+            }
+            if (hostPortVers.startsWith("[", start)) {  // at IPv6 literal
+                int brac = hostPortVers.indexOf(']', start + 1);
+                if (brac < 0 || brac > slash) {
+                    throw new IllegalArgumentException(
+                        "IiopURL: name is an Invalid URL: " + hostPortVers);
+                }
+
+                // include brackets
+                host = hostPortVers.substring(start, brac + 1);
+                start = brac + 1;
+            } else {      // at hostname or IPv4
+                int colon = hostPortVers.indexOf(':', start);
+                int hostEnd = (colon < 0 || colon > slash)
+                    ? slash
+                    : colon;
+                if (start < hostEnd) {
+                    host = hostPortVers.substring(start, hostEnd);
+                }
+                start = hostEnd;   // skip past host
+            }
+            if ((start + 1 < slash)) {
+                if ( hostPortVers.startsWith(":", start)) { // parse port
+                    start++;    // skip past ":"
+                    port = Integer.parseInt(hostPortVers.
+                                            substring(start, slash));
+                } else {
+                    throw new IllegalArgumentException(
+                        "IiopURL: name is an Invalid URL: " + hostPortVers);
+                }
+            }
+            start = slash;
+            if ("".equals(host) || host == null) {
+                host = DEFAULT_HOST ;
+            }
+            if (port == -1) {
+                port = (oldFormat ? DEFAULT_IIOP_PORT :
+                                DEFAULT_IIOPNAME_PORT);
+            }
+        }
+    }
+
+    public Vector<Address> getAddresses() {
+        return addresses;
+    }
+
+    /**
+     * Returns a possibly empty but non-null string that is the "string_name"
+     * portion of the URL.
+     */
+    public String getStringName() {
+        return stringName;
+    }
+
+    public Name getCosName() throws NamingException {
+        return CNCtx.parser.parse(stringName);
+    }
+
+    public IiopUrl(String url) throws MalformedURLException {
+        int addrStart;
+        boolean oldFormat;
+
+        if (url.startsWith("iiopname://")) {
+            oldFormat = false;
+            addrStart = 11;
+        } else if (url.startsWith("iiop://")) {
+            oldFormat = true;
+            addrStart = 7;
+        } else {
+            throw new MalformedURLException("Invalid iiop/iiopname URL: " + url);
+        }
+        int addrEnd = url.indexOf('/', addrStart);
+        if (addrEnd < 0) {
+            addrEnd = url.length();
+            stringName = "";
+        } else {
+            stringName = CorbaUtils.decode(url.substring(addrEnd+1));
+        }
+        addresses = new Vector<>(3);
+        if (oldFormat) {
+            // Only one host:port part, not multiple
+            addresses.addElement(
+                new Address(url.substring(addrStart, addrEnd), oldFormat));
+        } else {
+            StringTokenizer tokens =
+                new StringTokenizer(url.substring(addrStart, addrEnd), ",");
+            while (tokens.hasMoreTokens()) {
+                addresses.addElement(new Address(tokens.nextToken(), oldFormat));
+            }
+            if (addresses.size() == 0) {
+                addresses.addElement(new Address("", oldFormat));
+            }
+        }
+    }
+
+    // for testing only
+    /*public static void main(String[] args) {
+        try {
+            IiopUrl url = new IiopUrl(args[0]);
+            Vector addrs = url.getAddresses();
+            String name = url.getStringName();
+
+            for (int i = 0; i < addrs.size(); i++) {
+                Address addr = (Address)addrs.elementAt(i);
+                System.out.println("host: " + addr.host);
+                System.out.println("port: " + addr.port);
+                System.out.println("version: " + addr.major + " " + addr.minor);
+            }
+            System.out.println("name: " + name);
+        } catch (MalformedURLException e) {
+            e.printStackTrace();
+        }
+    } */
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/OrbReuseTracker.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import org.omg.CORBA.ORB;
+
+/**
+ * This class keeps track of references to the shared ORB object
+ * and destroys it when no more references are made to the ORB
+ * object. This object is created for each ORB object that CNCtx
+ * creates.
+ */
+class OrbReuseTracker {
+
+    int referenceCnt;
+    ORB orb;
+
+    private static final boolean debug = false;
+
+    OrbReuseTracker(ORB orb) {
+        this.orb = orb;
+        referenceCnt++;
+        if (debug) {
+             System.out.println("New OrbReuseTracker created");
+        }
+    }
+
+    synchronized void incRefCount() {
+        referenceCnt++;
+        if (debug) {
+             System.out.println("Increment orb ref count to:" + referenceCnt);
+        }
+    }
+
+    synchronized void decRefCount() {
+        referenceCnt--;
+        if (debug) {
+             System.out.println("Decrement orb ref count to:" + referenceCnt);
+        }
+        if ((referenceCnt == 0)) {
+            if (debug) {
+                System.out.println("Destroying the ORB");
+            }
+            orb.destroy();
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/RemoteToCorba.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.cosnaming;
+
+import javax.naming.*;
+import javax.naming.spi.StateFactory;
+import java.util.Hashtable;
+
+import org.omg.CORBA.ORB;
+
+import java.rmi.Remote;
+import java.rmi.server.ExportException;
+
+import com.sun.jndi.toolkit.corba.CorbaUtils;  // for RMI-IIOP
+
+/**
+  * StateFactory that turns java.rmi.Remote objects to org.omg.CORBA.Object.
+  *
+  * @author Rosanna Lee
+  */
+
+public class RemoteToCorba implements StateFactory {
+    public RemoteToCorba() {
+    }
+
+    /**
+     * Returns the CORBA object for a Remote object.
+     * If input is not a Remote object, or if Remote object uses JRMP, return null.
+     * If the RMI-IIOP library is not available, throw ConfigurationException.
+     *
+     * @param orig The object to turn into a CORBA object. If not Remote,
+     *             or if is a JRMP stub or impl, return null.
+     * @param name Ignored
+     * @param ctx The non-null CNCtx whose ORB to use.
+     * @param env Ignored
+     * @return The CORBA object for {@code orig} or null.
+     * @exception ConfigurationException If the CORBA object cannot be obtained
+     *    due to configuration problems, for instance, if RMI-IIOP not available.
+     * @exception NamingException If some other problem prevented a CORBA
+     *    object from being obtained from the Remote object.
+     */
+    public Object getStateToBind(Object orig, Name name, Context ctx,
+        Hashtable<?,?> env) throws NamingException {
+        if (orig instanceof org.omg.CORBA.Object) {
+            // Already a CORBA object, just use it
+            return null;
+        }
+
+        if (orig instanceof Remote) {
+            // Turn remote object into org.omg.CORBA.Object
+            // Returns null if JRMP; let next factory try
+            // CNCtx will eventually throw IllegalArgumentException if
+            // no CORBA object gotten
+            return CorbaUtils.remoteToCorba((Remote)orig, ((CNCtx)ctx)._orb);
+        }
+        return null; // pass and let next state factory try
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/cosnaming/jndiprovider.properties	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,4 @@
+# Provider resource file for the COS Naming service provider.
+
+# State factory to turn java.rmi.Remote into org.omg.CORBA.Object.
+java.naming.factory.state=com.sun.jndi.cosnaming.RemoteToCorba
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.toolkit.corba;
+
+// Needed for RMI/IIOP
+import java.rmi.Remote;
+
+import java.rmi.RemoteException;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.Enumeration;
+import java.applet.Applet;
+
+import org.omg.CORBA.ORB;
+
+import javax.naming.Context;
+import javax.naming.ConfigurationException;
+import javax.rmi.CORBA.Stub;
+import javax.rmi.PortableRemoteObject;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URLDecoder;
+
+/**
+  * Contains utilities for performing CORBA-related tasks:
+  * 1. Get the org.omg.CORBA.Object for a java.rmi.Remote object.
+  * 2. Create an ORB to use for a given host/port, and environment properties.
+  *    ...
+  *
+  * @author Simon Nash
+  * @author Bryan Atsatt
+  */
+
+public class CorbaUtils {
+    /**
+      * Returns the CORBA object reference associated with a Remote
+      * object by using the javax.rmi.CORBA package.
+      *<p>
+      * This method effective does the following:
+      * <blockquote><pre>
+      * java.lang.Object stub;
+      * try {
+      *     stub = PortableRemoteObject.toStub(remoteObj);
+      * } catch (Exception e) {
+      *     throw new ConfigurationException("Object not exported or not found");
+      * }
+      * if (!(stub instanceof javax.rmi.CORBA.Stub)) {
+      *     return null; // JRMP impl or JRMP stub
+      * }
+      * try {
+      *     ((javax.rmi.CORBA.Stub)stub).connect(orb);  // try to connect IIOP stub
+      * } catch (RemoteException e) {
+      *     // ignore 'already connected' error
+      * }
+      * return (javax.rmi.CORBA.Stub)stub;
+      * </pre></blockquote>
+      *
+      * @param remoteObj The non-null remote object for
+      * @param orb       The non-null ORB to connect the remote object to
+      * @return The CORBA Object for remoteObj; null if {@code remoteObj}
+      *                 is a JRMP implementation or JRMP stub.
+      * @exception ConfigurationException The CORBA Object cannot be obtained
+      *         because of configuration problems.
+      */
+    public static org.omg.CORBA.Object remoteToCorba(Remote remoteObj, ORB orb)
+        throws ConfigurationException {
+
+// First, get remoteObj's stub
+
+            // javax.rmi.CORBA.Stub stub = PortableRemoteObject.toStub(remoteObj);
+
+            Remote stub;
+
+            try {
+                stub = PortableRemoteObject.toStub(remoteObj);
+            } catch (Throwable t) {
+                ConfigurationException ce = new ConfigurationException(
+    "Problem with PortableRemoteObject.toStub(); object not exported or stub not found");
+                ce.setRootCause(t);
+                throw ce;
+            }
+
+// Next, make sure that the stub is javax.rmi.CORBA.Stub
+
+            if (!(stub instanceof Stub)) {
+                return null;  // JRMP implementation or JRMP stub
+            }
+
+// Next, make sure that the stub is connected
+            try {
+                ((Stub) stub).connect(orb);
+            } catch (RemoteException e) {
+                // ignore RemoteException because stub might have already
+                // been connected
+            } catch (Throwable t) {
+                ConfigurationException ce = new ConfigurationException(
+                        "Problem invoking javax.rmi.CORBA.Stub.connect()");
+                ce.setRootCause(t);
+                throw ce;
+            }
+// Finally, return stub
+            return (org.omg.CORBA.Object)stub;
+    }
+
+    /**
+     * Get ORB using given server and port number, and properties from environment.
+     *
+     * @param server Possibly null server; if null means use default;
+     *               For applet, it is the applet host; for app, it is localhost.
+     * @param port   Port number, -1 means default port
+     * @param env    Possibly null environment. Contains environment properties.
+     *               Could contain ORB itself; or applet used for initializing ORB.
+     *               Use all String properties from env for initializing ORB
+     * @return A non-null ORB.
+     */
+    public static ORB getOrb(String server, int port, Hashtable<?,?> env) {
+        // See if we can get info from environment
+        Properties orbProp;
+
+        // Extract any org.omg.CORBA properties from environment
+        if (env != null) {
+            if (env instanceof Properties) {
+                // Already a Properties, just clone
+                orbProp = (Properties) env.clone();
+            } else {
+                // Get all String properties
+                Enumeration<?> envProp;
+                orbProp = new Properties();
+                for (envProp = env.keys(); envProp.hasMoreElements();) {
+                    String key = (String)envProp.nextElement();
+                    Object val = env.get(key);
+                    if (val instanceof String) {
+                        orbProp.put(key, val);
+                    }
+                }
+            }
+        } else {
+            orbProp = new Properties();
+        }
+
+        if (server != null) {
+            orbProp.put("org.omg.CORBA.ORBInitialHost", server);
+        }
+        if (port >= 0) {
+            orbProp.put("org.omg.CORBA.ORBInitialPort", ""+port);
+        }
+
+        // Get Applet from environment
+        if (env != null) {
+            @SuppressWarnings("deprecation")
+            Applet applet = (Applet) env.get(Context.APPLET);
+            if (applet != null) {
+            // Create ORBs using applet and orbProp
+                return ORB.init(applet, orbProp);
+            }
+        }
+
+        return ORB.init(new String[0], orbProp);
+    }
+
+    /**
+     * Decode a URI string (according to RFC 2396).
+     */
+    public static final String decode(String s) throws MalformedURLException {
+        try {
+            return decode(s, "8859_1");
+        } catch (UnsupportedEncodingException e) {
+            // ISO-Latin-1 should always be available?
+            throw new MalformedURLException("ISO-Latin-1 decoder unavailable");
+        }
+    }
+
+    /**
+     * Decode a URI string (according to RFC 2396).
+     *
+     * Three-character sequences '%xy', where 'xy' is the two-digit
+     * hexadecimal representation of the lower 8-bits of a character,
+     * are decoded into the character itself.
+     *
+     * The string is subsequently converted using the specified encoding
+     */
+    public static final String decode(String s, String enc)
+            throws MalformedURLException, UnsupportedEncodingException {
+        try {
+            return URLDecoder.decode(s, enc);
+        } catch (IllegalArgumentException iae) {
+            MalformedURLException mue = new MalformedURLException("Invalid URI encoding: " + s);
+            mue.initCause(iae);
+            throw mue;
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/url/corbaname/corbanameURLContextFactory.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.url.corbaname;
+
+import com.sun.jndi.url.iiop.iiopURLContextFactory;
+
+/**
+ * A corbaname URL context factory.
+ * It just uses the iiop URL context factory but is needed here
+ * so that NamingManager.getURLContext() will find it.
+ *
+ * @author Rosanna Lee
+ */
+final public class corbanameURLContextFactory extends iiopURLContextFactory {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/url/iiop/GenericURLContext.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,537 @@
+/*
+ * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.url.iiop;
+
+import com.sun.jndi.toolkit.corba.CorbaUtils;
+
+import javax.naming.*;
+import javax.naming.spi.ResolveResult;
+import javax.naming.spi.NamingManager;
+
+import java.util.Hashtable;
+import java.net.MalformedURLException;
+
+/**
+ * This abstract class is a generic URL context that accepts as the
+ * name argument either a string URL or a Name whose first component
+ * is a URL. It resolves the URL to a target context and then continues
+ * the operation using the remaining name in the target context as if
+ * the first component names a junction.
+ *
+ * A subclass must define getRootURLContext()
+ * to process the URL into head/tail pieces. If it wants to control how
+ * URL strings are parsed and compared for the rename() operation, then
+ * it should override getNonRootURLSuffixes() and urlEquals().
+ *
+ * @author Scott Seligman
+ * @author Rosanna Lee
+ */
+abstract public class GenericURLContext implements Context {
+    protected Hashtable<String, Object> myEnv = null;
+
+    @SuppressWarnings("unchecked") // Expect Hashtable<String, Object>
+    public GenericURLContext(Hashtable<?,?> env) {
+        // context that is not tied to any specific URL
+        myEnv =
+                (Hashtable<String, Object>)(env == null ? null : env.clone());
+    }
+
+    public void close() throws NamingException {
+        myEnv = null;
+    }
+
+    public String getNameInNamespace() throws NamingException {
+        return ""; // %%% check this out: A URL context's name is ""
+    }
+
+    /**
+     * Resolves 'name' into a target context with remaining name.
+     * For example, with a JNDI URL "jndi://dnsname/rest_name",
+     * this method resolves "jndi://dnsname/" to a target context,
+     * and returns the target context with "rest_name".
+     * The definition of "root URL" and how much of the URL to
+     * consume is implementation specific.
+     * If rename() is supported for a particular URL scheme,
+     * getRootURLContext(), getURLPrefix(), and getURLSuffix()
+     * must be in sync wrt how URLs are parsed and returned.
+     */
+    abstract protected ResolveResult getRootURLContext(String url,
+                                                       Hashtable<?,?> env) throws NamingException;
+
+    /**
+     * Returns the suffix of the url. The result should be identical to
+     * that of calling getRootURLContext().getRemainingName(), but
+     * without the overhead of doing anything with the prefix like
+     * creating a context.
+     *<p>
+     * This method returns a Name instead of a String because to give
+     * the provider an opportunity to return a Name (for example,
+     * for weakly separated naming systems like COS naming).
+     *<p>
+     * The default implementation uses skips 'prefix', calls
+     * CorbaUtils.decode() on it, and returns the result as a single component
+     * CompositeName.
+     * Subclass should override if this is not appropriate.
+     * This method is used only by rename().
+     * If rename() is supported for a particular URL scheme,
+     * getRootURLContext(), getURLPrefix(), and getURLSuffix()
+     * must be in sync wrt how URLs are parsed and returned.
+     *<p>
+     * For many URL schemes, this method is very similar to URL.getFile(),
+     * except getFile() will return a leading slash in the
+     * 2nd, 3rd, and 4th cases. For schemes like "ldap" and "iiop",
+     * the leading slash must be skipped before the name is an acceptable
+     * format for operation by the Context methods. For schemes that treat the
+     * leading slash as significant (such as "file"),
+     * the subclass must override getURLSuffix() to get the correct behavior.
+     * Remember, the behavior must match getRootURLContext().
+     *
+     * <pre>{@code
+     * URL                                     Suffix
+     * foo://host:port                         <empty string>
+     * foo://host:port/rest/of/name            rest/of/name
+     * foo:///rest/of/name                     rest/of/name
+     * foo:/rest/of/name                       rest/of/name
+     * foo:rest/of/name                        rest/of/name
+     * }</pre>
+     */
+    protected Name getURLSuffix(String prefix, String url) throws NamingException {
+        String suffix = url.substring(prefix.length());
+        if (suffix.length() == 0) {
+            return new CompositeName();
+        }
+
+        if (suffix.charAt(0) == '/') {
+            suffix = suffix.substring(1); // skip leading slash
+        }
+
+        try {
+            return new CompositeName().add(CorbaUtils.decode(suffix));
+        } catch (MalformedURLException e) {
+            throw new InvalidNameException(e.getMessage());
+        }
+    }
+
+    /**
+     * Finds the prefix of a URL.
+     * Default implementation looks for slashes and then extracts
+     * prefixes using String.substring().
+     * Subclass should override if this is not appropriate.
+     * This method is used only by rename().
+     * If rename() is supported for a particular URL scheme,
+     * getRootURLContext(), getURLPrefix(), and getURLSuffix()
+     * must be in sync wrt how URLs are parsed and returned.
+     *<p>
+     * URL                                     Prefix
+     * foo://host:port                         foo://host:port
+     * foo://host:port/rest/of/name            foo://host:port
+     * foo:///rest/of/name                     foo://
+     * foo:/rest/of/name                       foo:
+     * foo:rest/of/name                        foo:
+     */
+    protected String getURLPrefix(String url) throws NamingException {
+        int start = url.indexOf(':');
+
+        if (start < 0) {
+            throw new OperationNotSupportedException("Invalid URL: " + url);
+        }
+        ++start; // skip ':'
+
+        if (url.startsWith("//", start)) {
+            start += 2;  // skip double slash
+
+            // find last slash
+            int posn = url.indexOf('/', start);
+            if (posn >= 0) {
+                start = posn;
+            } else {
+                start = url.length();  // rest of URL
+            }
+        }
+
+        // else 0 or 1 initial slashes; start is unchanged
+        return url.substring(0, start);
+    }
+
+    /**
+     * Determines whether two URLs are the same.
+     * Default implementation uses String.equals().
+     * Subclass should override if this is not appropriate.
+     * This method is used by rename().
+     */
+    protected boolean urlEquals(String url1, String url2) {
+        return url1.equals(url2);
+    }
+
+    /**
+     * Gets the context in which to continue the operation. This method
+     * is called when this context is asked to process a multicomponent
+     * Name in which the first component is a URL.
+     * Treat the first component like a junction: resolve it and then use
+     * NamingManager.getContinuationContext() to get the target context in
+     * which to operate on the remainder of the name (n.getSuffix(1)).
+     */
+    protected Context getContinuationContext(Name n) throws NamingException {
+        Object obj = lookup(n.get(0));
+        CannotProceedException cpe = new CannotProceedException();
+        cpe.setResolvedObj(obj);
+        cpe.setEnvironment(myEnv);
+        return NamingManager.getContinuationContext(cpe);
+    }
+
+    public Object lookup(String name) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            return ctx.lookup(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public Object lookup(Name name) throws NamingException {
+        if (name.size() == 1) {
+            return lookup(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                return ctx.lookup(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public void bind(String name, Object obj) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            ctx.bind(res.getRemainingName(), obj);
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public void bind(Name name, Object obj) throws NamingException {
+        if (name.size() == 1) {
+            bind(name.get(0), obj);
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                ctx.bind(name.getSuffix(1), obj);
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public void rebind(String name, Object obj) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            ctx.rebind(res.getRemainingName(), obj);
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public void rebind(Name name, Object obj) throws NamingException {
+        if (name.size() == 1) {
+            rebind(name.get(0), obj);
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                ctx.rebind(name.getSuffix(1), obj);
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public void unbind(String name) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            ctx.unbind(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public void unbind(Name name) throws NamingException {
+        if (name.size() == 1) {
+            unbind(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                ctx.unbind(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public void rename(String oldName, String newName) throws NamingException {
+        String oldPrefix = getURLPrefix(oldName);
+        String newPrefix = getURLPrefix(newName);
+        if (!urlEquals(oldPrefix, newPrefix)) {
+            throw new OperationNotSupportedException(
+                    "Renaming using different URL prefixes not supported : " +
+                            oldName + " " + newName);
+        }
+
+        ResolveResult res = getRootURLContext(oldName, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            ctx.rename(res.getRemainingName(), getURLSuffix(newPrefix, newName));
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public void rename(Name name, Name newName) throws NamingException {
+        if (name.size() == 1) {
+            if (newName.size() != 1) {
+                throw new OperationNotSupportedException(
+                        "Renaming to a Name with more components not supported: " + newName);
+            }
+            rename(name.get(0), newName.get(0));
+        } else {
+            // > 1 component with 1st one being URL
+            // URLs must be identical; cannot deal with diff URLs
+            if (!urlEquals(name.get(0), newName.get(0))) {
+                throw new OperationNotSupportedException(
+                        "Renaming using different URLs as first components not supported: " +
+                                name + " " + newName);
+            }
+
+            Context ctx = getContinuationContext(name);
+            try {
+                ctx.rename(name.getSuffix(1), newName.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public NamingEnumeration<NameClassPair> list(String name)   throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            return ctx.list(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
+        if (name.size() == 1) {
+            return list(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                return ctx.list(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public NamingEnumeration<Binding> listBindings(String name)
+            throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            return ctx.listBindings(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
+        if (name.size() == 1) {
+            return listBindings(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                return ctx.listBindings(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public void destroySubcontext(String name) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            ctx.destroySubcontext(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public void destroySubcontext(Name name) throws NamingException {
+        if (name.size() == 1) {
+            destroySubcontext(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                ctx.destroySubcontext(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public Context createSubcontext(String name) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            return ctx.createSubcontext(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public Context createSubcontext(Name name) throws NamingException {
+        if (name.size() == 1) {
+            return createSubcontext(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                return ctx.createSubcontext(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public Object lookupLink(String name) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            return ctx.lookupLink(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public Object lookupLink(Name name) throws NamingException {
+        if (name.size() == 1) {
+            return lookupLink(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                return ctx.lookupLink(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public NameParser getNameParser(String name) throws NamingException {
+        ResolveResult res = getRootURLContext(name, myEnv);
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            return ctx.getNameParser(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    public NameParser getNameParser(Name name) throws NamingException {
+        if (name.size() == 1) {
+            return getNameParser(name.get(0));
+        } else {
+            Context ctx = getContinuationContext(name);
+            try {
+                return ctx.getNameParser(name.getSuffix(1));
+            } finally {
+                ctx.close();
+            }
+        }
+    }
+
+    public String composeName(String name, String prefix)
+            throws NamingException {
+        if (prefix.equals("")) {
+            return name;
+        } else if (name.equals("")) {
+            return prefix;
+        } else {
+            return (prefix + "/" + name);
+        }
+    }
+
+    public Name composeName(Name name, Name prefix) throws NamingException {
+        Name result = (Name)prefix.clone();
+        result.addAll(name);
+        return result;
+    }
+
+    public Object removeFromEnvironment(String propName)
+            throws NamingException {
+        if (myEnv == null) {
+            return null;
+        }
+        return myEnv.remove(propName);
+    }
+
+    public Object addToEnvironment(String propName, Object propVal)
+            throws NamingException {
+        if (myEnv == null) {
+            myEnv = new Hashtable<String, Object>(11, 0.75f);
+        }
+        return myEnv.put(propName, propVal);
+    }
+
+    @SuppressWarnings("unchecked") // clone()
+    public Hashtable<String, Object> getEnvironment() throws NamingException {
+        if (myEnv == null) {
+            return new Hashtable<>(5, 0.75f);
+        } else {
+            return (Hashtable<String, Object>)myEnv.clone();
+        }
+    }
+
+/*
+// To test, declare getURLPrefix and getURLSuffix static.
+
+    public static void main(String[] args) throws Exception {
+        String[] tests = {"file://host:port",
+                          "file:///rest/of/name",
+                          "file://host:port/rest/of/name",
+                          "file:/rest/of/name",
+                          "file:rest/of/name"};
+        for (int i = 0; i < tests.length; i++) {
+            String pre = getURLPrefix(tests[i]);
+            System.out.println(pre);
+            System.out.println(getURLSuffix(pre, tests[i]));
+        }
+    }
+*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/url/iiop/iiopURLContext.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.url.iiop;
+
+import javax.naming.spi.ResolveResult;
+import javax.naming.*;
+import java.util.Hashtable;
+import java.net.MalformedURLException;
+
+import com.sun.jndi.cosnaming.IiopUrl;
+import com.sun.jndi.cosnaming.CorbanameUrl;
+
+/**
+ * An IIOP URL context.
+ *
+ * @author Rosanna Lee
+ */
+
+public class iiopURLContext
+        extends GenericURLContext {
+
+    iiopURLContext(Hashtable<?,?> env) {
+        super(env);
+    }
+
+    /**
+      * Resolves 'name' into a target context with remaining name.
+      * It only resolves the hostname/port number. The remaining name
+      * contains the rest of the name found in the URL.
+      *
+      * For example, with a iiop URL "iiop://localhost:900/rest/of/name",
+      * this method resolves "iiop://localhost:900/" to the "NameService"
+      * context on for the ORB at 'localhost' on port 900,
+      * and returns as the remaining name "rest/of/name".
+      */
+    protected ResolveResult getRootURLContext(String name, Hashtable<?,?> env)
+    throws NamingException {
+        return iiopURLContextFactory.getUsingURLIgnoreRest(name, env);
+    }
+
+    /**
+     * Return the suffix of an "iiop", "iiopname", or "corbaname" url.
+     * prefix parameter is ignored.
+     */
+    protected Name getURLSuffix(String prefix, String url)
+        throws NamingException {
+        try {
+            if (url.startsWith("iiop://") || url.startsWith("iiopname://")) {
+                IiopUrl parsedUrl = new IiopUrl(url);
+                return parsedUrl.getCosName();
+            } else if (url.startsWith("corbaname:")) {
+                CorbanameUrl parsedUrl = new CorbanameUrl(url);
+                return parsedUrl.getCosName();
+            } else {
+                throw new MalformedURLException("Not a valid URL: " + url);
+            }
+        } catch (MalformedURLException e) {
+            throw new InvalidNameException(e.getMessage());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/url/iiop/iiopURLContextFactory.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.url.iiop;
+
+import javax.naming.*;
+import javax.naming.spi.*;
+
+import java.util.Hashtable;
+
+import com.sun.jndi.cosnaming.CNCtx;
+
+/**
+ * An IIOP URL context factory.
+ *
+ * @author Rosanna Lee
+ */
+
+public class iiopURLContextFactory implements ObjectFactory {
+
+    public Object getObjectInstance(Object urlInfo, Name name, Context nameCtx,
+                                    Hashtable<?,?> env) throws Exception {
+
+//System.out.println("iiopURLContextFactory " + urlInfo);
+        if (urlInfo == null) {
+            return new iiopURLContext(env);
+        }
+        if (urlInfo instanceof String) {
+            return getUsingURL((String)urlInfo, env);
+        } else if (urlInfo instanceof String[]) {
+            return getUsingURLs((String[])urlInfo, env);
+        } else {
+            throw (new IllegalArgumentException(
+                    "iiopURLContextFactory.getObjectInstance: " +
+                    "argument must be a URL String or array of URLs"));
+        }
+    }
+
+    /**
+      * Resolves 'name' into a target context with remaining name.
+      * It only resolves the hostname/port number. The remaining name
+      * contains the rest of the name found in the URL.
+      *
+      * For example, with a iiop URL "iiop://localhost:900/rest/of/name",
+      * this method resolves "iiop://localhost:900/" to the "NameService"
+      * context on for the ORB at 'localhost' on port 900,
+      * and returns as the remaining name "rest/of/name".
+      */
+    static ResolveResult getUsingURLIgnoreRest(String url, Hashtable<?,?> env)
+        throws NamingException {
+        return CNCtx.createUsingURL(url, env);
+    }
+
+    private static Object getUsingURL(String url, Hashtable<?,?> env)
+        throws NamingException {
+        ResolveResult res = getUsingURLIgnoreRest(url, env);
+
+        Context ctx = (Context)res.getResolvedObj();
+        try {
+            return ctx.lookup(res.getRemainingName());
+        } finally {
+            ctx.close();
+        }
+    }
+
+    private static Object getUsingURLs(String[] urls, Hashtable<?,?> env) {
+        for (int i = 0; i < urls.length; i++) {
+            String url = urls[i];
+            try {
+                Object obj = getUsingURL(url, env);
+                if (obj != null) {
+                    return obj;
+                }
+            } catch (NamingException e) {
+            }
+        }
+        return null;    // %%% exception??
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.corba/share/classes/com/sun/jndi/url/iiopname/iiopnameURLContextFactory.java	Mon Dec 19 16:01:24 2016 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package com.sun.jndi.url.iiopname;
+
+import com.sun.jndi.url.iiop.iiopURLContextFactory;
+
+/**
+ * An iiopname URL context factory.
+ * It just uses the iiop URL context factory but is needed here
+ * so that NamingManager.getURLContext() will find it.
+ *
+ * @author Rosanna Lee
+ */
+final public class iiopnameURLContextFactory extends iiopURLContextFactory {
+}