/*
* 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.util.Vector;
import java.net.MalformedURLException;
import java.net.URL;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.IOException;
import org.omg.CosNaming.*;
import org.omg.CosNaming.NamingContextPackage.*;
import org.omg.CORBA.*;
import com.sun.jndi.toolkit.corba.CorbaUtils;
// Needed for creating default ORB
import java.applet.Applet;
/**
* Provides a bridge to the CosNaming server provided by
* JavaIDL. This class provides the InitialContext from CosNaming.
*
* @author Raj Krishnamurthy
* @author Rosanna Lee
*/
public class CNCtx implements javax.naming.Context {
private final static boolean debug = false;
/*
* Implement one shared ORB among all CNCtx. However, there is a public constructor
* accepting an ORB, so we need the option of using a given ORB.
*/
private static ORB _defaultOrb;
ORB _orb; // used by ExceptionMapper and RMI/IIOP factory
public NamingContext _nc; // public for accessing underlying NamingContext
private synchronized static ORB getDefaultOrb() {
if (_defaultOrb == null) {
_defaultOrb = CorbaUtils.getOrb(null, -1,
new Hashtable<String, java.lang.Object>());
}
return _defaultOrb;
}
private NameComponent[] _name = null;
Hashtable _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.
*/
CNCtx(Hashtable env) throws NamingException {
if (env != null) {
env = (Hashtable) env.clone();
}
_env = 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.
*/
public static ResolveResult createUsingURL(String url, Hashtable env)
throws NamingException {
CNCtx ctx = new CNCtx();
if (env != null) {
env = (Hashtable) env.clone();
}
ctx._env = 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.
*<p>
* _orb is obtained from java.naming.corba.orb if it has been set.
* Otherwise, _orb is created using the host/port from PROVIDER_URL
* (if it contains an "iiop" or "iiopname" URL), or from initialization
* properties specified in env.
*<p>
* _nc is obtained from the IOR stored in PROVIDER_URL if it has been
* set and does not contain an "iiop" or "iiopname" URL. It can be
* a stringified IOR, "corbaloc" URL, "corbaname" URL,
* or a URL (such as file/http/ftp) to a location
* containing a stringified IOR. If PROVIDER_URL has not been
* set in this way, it is obtained from the result of
* ORB.resolve_initial_reference("NameService");
*<p>
* _name is obtained from the "iiop", "iiopname", or "corbaname" URL.
* It is the empty name by default.
*
* @param env Environment The possibly null environment.
* @exception NamingException When an error occurs while initializing the
* ORB or the naming context.
*/
private void initOrbAndRootContext(Hashtable env) throws NamingException {
org.omg.CORBA.ORB inOrb = null;
String ncIor = null;
if (inOrb == null && env != null) {
inOrb = (org.omg.CORBA.ORB) env.get("java.naming.corba.orb");
}
if (inOrb == null)
inOrb = getDefaultOrb(); // will create a default ORB if none exists
// Extract PROVIDER_URL from environment
String provUrl = null;
if (env != null) {
provUrl = (String)env.get(javax.naming.Context.PROVIDER_URL);
}
if (provUrl != null && !isCorbaUrl(provUrl)) {
// Initialize the root naming context by using the IOR supplied
// in the PROVIDER_URL
ncIor = getStringifiedIor(provUrl);
setOrbAndRootContext(inOrb, ncIor);
} else if (provUrl != null) {
// Initialize the root naming context by using the URL supplied
// in the PROVIDER_URL
String insName = initUsingUrl(inOrb, provUrl, env);
// If name supplied in URL, resolve it to a NamingContext
if (insName.length() > 0) {
_name = parser.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);
Vector addrs = parsedUrl.getAddresses();
IiopUrl.Address addr;
NamingException savedException = null;
for (int i = 0; i < addrs.size(); i++) {
addr = (IiopUrl.Address)addrs.elementAt(i);
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.
*/
public NamingEnumeration list(Name name)
throws NamingException {
return 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 String 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.
*/
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 propVal The ORB.
* @return the previous value of this property if any.
*/
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
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 reponsibility.
}
protected void finalize() {
try {
close();
} catch (NamingException e) {
// ignore failures
}
}
}