# HG changeset patch # User prappo # Date 1482163284 0 # Node ID 9205e980062a5c4530b51021c6e274025f4ccbdf # Parent 56d764f5b735313ba1689bd28039c0982b3c1ff9 8164907: Eliminate dependency on java.naming/com.sun.jndi.toolkit.url Reviewed-by: chegar, rriggs diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/CNBindingEnumeration.java --- /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 { + + 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; + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtx.java --- /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()); + } + return _defaultOrb; + } + + private NameComponent[] _name = null; + + Hashtable _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)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)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 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. + *

+ * _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. + *

+ * _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"); + *

+ * _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 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 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 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 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 getEnvironment() throws NamingException { + if (_env == null) { + return new Hashtable<>(5, 0.75f); + } else { + return (Hashtable)_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)_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)_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 + } + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/CNCtxFactory.java --- /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); + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/CNNameParser.java --- /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 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 insStringToStringifiedComps(String str) + throws InvalidNameException { + + int len = str.length(); + Vector 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 enum_) { + super(enum_, CNNameParser.mySyntax); + } + + public Object clone() { + return new CNCompoundName(getAll()); + } + + public Name getPrefix(int posn) { + Enumeration comps = super.getPrefix(posn).getAll(); + return new CNCompoundName(comps); + } + + public Name getSuffix(int posn) { + Enumeration 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)); + } +*/ +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/CorbanameUrl.java --- /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. + *

{@code
+ * corbaname url = "corbaname:"  ["#" ]
+ * corbaloc_obj  =  ["/" ]
+ * obj_addr_list = as defined in a corbaloc URL
+ * key_string    = as defined in a corbaloc URL
+ * string_name   = stringified COS name | empty_string
+ * }
+ * Characters in {@code } are escaped as follows. + * US-ASCII alphanumeric characters are not escaped. Any characters outside + * of this range are escaped except for the following: + *
{@code
+ *        ; / : ? @ & = + $ , - _ . ! ~ * ; ( )
+ * }
+ * Escaped characters is escaped by using a % followed by its 2 hexadecimal + * numbers representing the octet. + *

+ * 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 }. + * The COS name is {@code } with the escaped characters resolved. + *

+ * A corbaname URL is resolved by: + *

    + *
  1. Construct a corbaloc URL by concatenating {@code "corbaloc:"} and {@code }. + *
  2. Resolve the corbaloc URL to a NamingContext by using + *
    {@code
    + *     nctx = ORB.string_to_object(corbalocUrl);
    + * }
    + *
  3. Resolve {@code } in the NamingContext. + *
+ * + * @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(); + } + } +*/ +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/ExceptionMapper.java --- /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; + } + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/IiopUrl.java --- /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: + * + *
+ * 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
+ * 
+ * + * 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: + *
{@code
+ * ; / : ? : @ & = + $ , - _ . ! ~ *  ' ( )
+ * }
+ * 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: + *
{@code
+ * iiop url     = "iiop://" [host [":" port]] ["/" string_name]
+ * }
+ * 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
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
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(); + } + } */ +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/OrbReuseTracker.java --- /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(); + } + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/RemoteToCorba.java --- /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 + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/cosnaming/jndiprovider.properties --- /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 diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/toolkit/corba/CorbaUtils.java --- /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. + *

+ * This method effective does the following: + *

+      * 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;
+      * 
+ * + * @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; + } + } + +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/url/corbaname/corbanameURLContextFactory.java --- /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 { +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/url/iiop/GenericURLContext.java --- /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 myEnv = null; + + @SuppressWarnings("unchecked") // Expect Hashtable + public GenericURLContext(Hashtable env) { + // context that is not tied to any specific URL + myEnv = + (Hashtable)(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. + *

+ * 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). + *

+ * 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. + *

+ * 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(). + * + *

{@code
+     * URL                                     Suffix
+     * foo://host:port                         
+     * 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
+     * }
+ */ + 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. + *

+ * 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 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 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 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 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(11, 0.75f); + } + return myEnv.put(propName, propVal); + } + + @SuppressWarnings("unchecked") // clone() + public Hashtable getEnvironment() throws NamingException { + if (myEnv == null) { + return new Hashtable<>(5, 0.75f); + } else { + return (Hashtable)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])); + } + } +*/ +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/url/iiop/iiopURLContext.java --- /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()); + } + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/url/iiop/iiopURLContextFactory.java --- /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?? + } +} diff -r 56d764f5b735 -r 9205e980062a src/java.corba/share/classes/com/sun/jndi/url/iiopname/iiopnameURLContextFactory.java --- /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 { +}