/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2006-2011 Oracle and/or its affiliates. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can
* obtain a copy of the License at
* https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
* or packager/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at packager/legal/LICENSE.txt.
*
* GPL Classpath Exception:
* Oracle designates this particular file as subject to the "Classpath"
* exception as provided by Oracle in the GPL Version 2 section of the License
* file that accompanied this code.
*
* Modifications:
* If applicable, add the following below the License Header, with the fields
* enclosed by brackets [] replaced by your own identifying information:
* "Portions Copyright [year] [name of copyright owner]"
*
* Contributor(s):
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.naming.impl;
import com.sun.enterprise.naming.util.LogFacade;
import org.glassfish.api.naming.NamingObjectProxy;
import org.jvnet.hk2.component.Habitat;
import org.glassfish.api.admin.ProcessEnvironment;
import org.glassfish.api.admin.ProcessEnvironment.ProcessType;
import javax.naming.spi.ObjectFactory;
import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.Map;
import java.util.HashMap;
import javax.naming.Binding;
import javax.naming.CommunicationException;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NotContextException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import org.omg.CORBA.ORBPackage.InvalidName;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContextHelper;
import javax.rmi.PortableRemoteObject;
import org.glassfish.internal.api.Globals;
import org.glassfish.internal.api.ORBLocator;
import org.glassfish.internal.api.ServerContext;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NamingContextPackage.CannotProceed;
import org.omg.CosNaming.NamingContextPackage.NotFound;
/**
* This context provides access to the app server naming service. This
* is the default Context for GlassFish. Lookups of unqualified names (i.e.
* names not starting with "java:", "corbaname:" etc) are serviced by
* SerialContext. The namespace is implemented in the
* SerialContextProviderImpl object, which is accessed directly in the
* case that the client is collocated with the naming service impl or
* remotely via RMI-IIOP if not collocated.
* <p/>
* <b>NOT THREAD SAFE: mutable instance variables</b>
*/
public class SerialContext implements Context {
// Maximum number of recursive calls to lookup on comm error
// Maximum number of recursive calls to lookup on comm error
private static final int MAX_LEVEL = 5 ;
private static final String JAVA_URL = "java:";
private static final String JAVA_GLOBAL_URL = "java:global/";
// Sets unmanaged SerialContext in test mode to prevent attempts to contact server.
static final String INITIAL_CONTEXT_TEST_MODE = "com.sun.enterprise.naming.TestMode";
private static final Logger _logger = LogFacade.getLogger();
private static final NameParser myParser = new SerialNameParser();
private static final Map<ProviderCacheKey, SerialContextProvider> providerCache =
new HashMap<ProviderCacheKey, SerialContextProvider>();
private static final ThreadLocal<ThreadLocalIC> stickyContext =
new ThreadLocal<ThreadLocalIC>() {
@Override
protected ThreadLocalIC initialValue() {
return new ThreadLocalIC() ;
}
} ;
private Hashtable myEnv = null; // THREAD UNSAFE
private SerialContextProvider provider;
private final String myName;
private final JavaURLContext javaUrlContext;
private Habitat habitat;
private boolean testMode = false;
private ProcessType processType = ProcessType.Server;
private ORB orbFromEnv;
private String targetHost;
private String targetPort;
private ORB orb = null ;
// True if we're running in the server and no orb,host, or port
// properties have been explicitly set in the properties
// Allows special optimized intra-server naming service access
private boolean intraServerLookups;
// Common Class Loader. It is used as a fallback classloader to locate
// GlassFish object factories.
private ClassLoader commonCL;
/** Methods for preserving stickiness. This is a
* solution to store the sticky IC as a thread local variable. This sticky
* IC will be used by all classes that require a context object to do lookup
* (if LB is enabled) SerialContext.lookup() sets a value for the thread
* local variable (stickyContext) before performing th lookup in case LB is
* enabled. If not, the thread local variable is null. At the end of the
* SerialContext.lookup() method, the thread local variable gets set to
* null. So actually speaking, more than being a global variable for the
* entire thread, its global only during the execution of the
* SerialContext.lookup() method. bug 5050591
*
*/
static Context getStickyContext() {
return stickyContext.get().getContext() ;
}
private void grabSticky() {
stickyContext.get().grab( this ) ;
}
private void releaseSticky() {
stickyContext.get().release() ;
}
static void clearSticky() {
stickyContext.get().clear() ;
}
/** Store the sticky context as a threadlocal variable (bug 5050591).
* Count is needed to know how many times the lookup method is being called
* from within the user code's ic.lookup().
* e.g. JMS resource lookups (via ConnectorObjectFactory)
*/
private static class ThreadLocalIC {
private Context ctx = null ;
private int count = 0;
Context getContext() {
return ctx ;
}
void grab( Context context ) {
if (ctx == null) {
ctx = context ;
}
count++ ;
}
void release() {
if (count > 0) {
count-- ;
if (count == 0) {
ctx = null ;
}
} else {
if (_logger.isLoggable(Level.FINE)) {
_logger.log( Level.FINE,
"SerialContext: attempt to release StickyContext "
+ " without grab") ;
}
ctx = null ;
}
}
void clear() {
ctx = null ;
count = 0 ;
}
}
/**
* Constructor for the context. Initializes the object reference to the
* remote provider object.
*/
public SerialContext(String name, Hashtable environment, Habitat h)
throws NamingException {
habitat = h;
myEnv = (environment != null) ? (Hashtable) (environment.clone())
: null;
// TODO REMOVE when property stuff is figured out
myEnv.put("java.naming.factory.url.pkgs",
"com.sun.enterprise.naming");
myEnv.put("java.naming.factory.state",
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl" );
this.myName = name;
if (_logger.isLoggable(Level.FINE))
_logger.fine("SerialContext ==> SerialContext instance created : "
+ this);
if( myEnv.get(INITIAL_CONTEXT_TEST_MODE) != null ) {
testMode = true;
System.out.println("SerialContext in test mode");
}
if( (habitat == null) && !testMode ) {
synchronized(SerialContext.class) {
if( SerialInitContextFactory.getDefaultHabitat() == null ) {
// Bootstrap a hk2 environment.
// TODO This will need to be moved somewhere else. Potentially any
// piece of glassfish code that can be an initial entry point from a
// Java SE client will need to make this happen.
habitat = Globals.getStaticHabitat();
SerialInitContextFactory.setDefaultHabitat(habitat);
} else {
habitat = SerialInitContextFactory.getDefaultHabitat();
}
}
}
if( testMode ) {
processType = ProcessType.Server;
} else {
ProcessEnvironment processEnv = habitat.getComponent(ProcessEnvironment.class);
processType = processEnv.getProcessType();
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"Serial Context initializing with process environment {0}",
processEnv);
}
}
// using these two temp variables allows instance variables
// to be 'final'.
JavaURLContext urlContextTemp = null;
if (myEnv.get(SerialInitContextFactory.IIOP_URL_PROPERTY) != null) {
urlContextTemp = new JavaURLContext(myEnv, this);
} else {
urlContextTemp = new JavaURLContext(myEnv, null);
}
javaUrlContext = urlContextTemp;
orbFromEnv = (ORB) myEnv.get(ORBLocator.JNDI_CORBA_ORB_PROPERTY);
String targetHostFromEnv = (String)myEnv.get(
ORBLocator.OMG_ORB_INIT_HOST_PROPERTY);
String targetPortFromEnv = (String)myEnv.get(
ORBLocator.OMG_ORB_INIT_PORT_PROPERTY);
intraServerLookups = (processType.isServer()) && (orbFromEnv == null) &&
(targetHostFromEnv == null) && (targetPortFromEnv == null);
// Set target host / port from env. If only one of the two is set, fill in the
// other with the default.
if( targetHostFromEnv != null ) {
targetHost = targetHostFromEnv;
if( targetPortFromEnv == null ) {
targetPort = ORBLocator.DEFAULT_ORB_INIT_PORT;
}
}
if( targetPortFromEnv != null ) {
targetPort = targetPortFromEnv;
if( targetHostFromEnv == null ) {
targetHost = ORBLocator.DEFAULT_ORB_INIT_HOST;
}
}
orb = orbFromEnv;
if (habitat != null) { // can happen in test mode
ServerContext sc = habitat.getByContract(ServerContext.class);
if (sc != null) {
commonCL = sc.getCommonClassLoader();
}
}
}
/**
* This constructor takes the component id as an argument. All name
* arguments to operations are prepended by the component id.
*/
public SerialContext(Hashtable env, Habitat habitat) throws NamingException {
this("", env, habitat);
}
private SerialContextProvider getProvider() throws NamingException {
SerialContextProvider returnValue = provider;
if (provider == null) {
try {
if (intraServerLookups) {
returnValue =
ProviderManager.getProviderManager().getLocalProvider();
} else {
returnValue = getRemoteProvider();
}
} catch(Exception e) {
clearSticky() ;
e.printStackTrace();
NamingException ne = new NamingException(
"Unable to acquire SerialContextProvider for " + this);
ne.initCause(e);
throw ne;
}
}
return returnValue;
}
private ORB getORB() {
ORBLocator orbHelper = habitat.getComponent(ORBLocator.class);
if (orb == null) {
orb = orbHelper.getORB() ;
}
return orb ;
}
private ProviderCacheKey getProviderCacheKey() {
final ORB myORB = getORB();
ProviderCacheKey key;
String eplist = null ;
if (myEnv != null) {
eplist = (String)myEnv.get(
SerialInitContextFactory.IIOP_URL_PROPERTY) ;
}
if (eplist != null) {
key = new ProviderCacheKey(eplist) ;
} else if (targetHost == null) {
key = new ProviderCacheKey(myORB) ;
} else {
key = new ProviderCacheKey(targetHost, targetPort);
}
return key ;
}
private void clearProvider() {
ProviderCacheKey key = getProviderCacheKey() ;
synchronized(SerialContext.class) {
providerCache.remove( key ) ;
}
provider = null ;
}
private SerialContextProvider getRemoteProvider() throws Exception {
if (provider == null) {
ProviderCacheKey key = getProviderCacheKey() ;
SerialContextProvider cachedProvider;
synchronized(SerialContext.class) {
cachedProvider = providerCache.get(key);
}
if (cachedProvider == null) {
// Don't hold lock during this call: remote invocation
SerialContextProvider newProvider = key.getNameService() ;
synchronized(SerialContext.class) {
cachedProvider = providerCache.get(key);
if (cachedProvider == null) {
providerCache.put(key, newProvider);
provider = newProvider;
} else {
provider = cachedProvider;
}
}
} else {
provider = cachedProvider;
}
}
return provider;
}
/**
* The getNameInNamespace API is not supported in this context.
*
* @throws NamingException if there is a naming exception.
*/
@Override
public String getNameInNamespace() throws NamingException {
return myName;
}
/**
* method to check if the name to look up starts with "java:"
*/
private boolean isjavaURL(String name) {
return name.startsWith(JAVA_URL) && !name.startsWith(JAVA_GLOBAL_URL) ;
}
/**
* Lookup the specified name in the context. Returns the resolved object.
*
* @return the resolved object.
* @throws NamingException if there is a naming exception.
*/
@Override
public Object lookup(String name) throws NamingException {
return lookup( name, 0 ) ;
}
private Object lookup(String name, int level ) throws NamingException {
// Before any lookup bind any NamedNamingObjectProxy
// Skip if in plain Java SE client
// TODO this should really be moved somewhere else
NamedNamingObjectManager.checkAndLoadProxies(habitat);
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE, "SerialContext ==> lookup( {0})", name);
}
/**
* In case a user is creating an IC with env passed in constructor; env
* specifies endpoints in some form in that case, the sticky IC should
* be stored as a thread local variable.
*
*/
final boolean useSticky = myEnv.get(
SerialInitContextFactory.IIOP_URL_PROPERTY) != null ;
if (useSticky) {
grabSticky() ;
}
try {
if (name.isEmpty()) {
// Asking to look up this context itself. Create and return
// a new instance with its own independent environment.
return (new SerialContext(myName, myEnv, habitat));
}
name = getRelativeName(name);
if (_logger.isLoggable(Level.FINE)) {
_logger.log(Level.FINE,
"SerialContext ==> lookup relative name : {0}", name);
}
if (isjavaURL(name)) {
//it is possible that the object bound in a java url ("java:") is
//reference object.
Object o = javaUrlContext.lookup(name);
if(o instanceof Reference){
o = getObjectInstance(name, o);
}
return o;
} else {
SerialContextProvider prvdr = getProvider() ;
Object obj = prvdr.lookup(name);
if (obj instanceof NamingObjectProxy) {
return ((NamingObjectProxy) obj).create(this);
}
if (obj instanceof Context) {
return new SerialContext(name, myEnv, habitat);
}
Object retObj = getObjectInstance(name, obj);
return retObj;
}
} catch (NamingException nnfe) {
NamingException ne = new NamingException
("Lookup failed for '" + name + "' in " + this);
ne.initCause(nnfe);
throw ne;
} catch (Exception ex) {
// Issue 14732: make this FINE, as a cluster configuration change
// can send us here in a normal retry scenario.
_logger.log(Level.FINE,
"enterprise_naming.serialctx_communication_exception", name);
_logger.log(Level.FINE, "", ex);
final int nextLevel = level + 1 ;
// temp fix for 6320008
// this should be removed once we change the transient NS
// implementation to persistent
if (ex instanceof java.rmi.MarshalException
&& ex.getCause() instanceof org.omg.CORBA.COMM_FAILURE
&& nextLevel < MAX_LEVEL) {
clearProvider();
_logger.fine("Resetting provider to NULL. Will get new obj ref " +
"for provider since previous obj ref was stale...");
return lookup(name, nextLevel );
} else {
CommunicationException ce = new CommunicationException(
"Communication exception for " + this);
ce.initCause(ex);
throw ce;
}
} finally {
if (useSticky) {
releaseSticky();
}
}
}
private Object getObjectInstance(String name, Object obj) throws Exception
{
Object retObj = javax.naming.spi.NamingManager.getObjectInstance(
obj, new CompositeName(name), null, myEnv);
if (retObj == obj) {
// NamingManager.getObjectInstance() returns the same object
// when it can't find the factory class. Since NamingManager
// uses Thread's context class loader to locate factory classes,
// it may not be able to locate the various GlassFish factories
// when lookup is performed outside of a Java EE context like
// inside an OSGi bundle's activator.
// So, let's see if using CommonClassLoader helps or not.
// We will only try with CommonClassLoader when the passed object
// reference has a factory class name set.
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
if (tccl != commonCL) {
Reference ref = getReference(obj);
if (ref != null) {
_logger.logp(Level.FINE, "SerialContext",
"getObjectInstance",
"Trying with CommonClassLoader for name {0} ",
new Object[]{name});
ObjectFactory factory = getObjectFactory(ref, commonCL);
if (factory != null) {
retObj = factory.getObjectInstance(
ref, new CompositeName(name), null, myEnv);
}
if (retObj != obj) {
_logger.logp(Level.FINE, "SerialContext",
"getObjectInstance",
"Found with CommonClassLoader");
}
}
}
}
return retObj;
}
/**
* This method tries to check if the passed object is a Reference or
* Refenciable. If it is a Reference, it just casts it to a Reference and
* returns, else if it is a Referenceable, it tries to get a Reference from
* the Referenceable and returns that, otherwise, it returns null.
*
* @param obj
* @return
* @throws NamingException
*/
private Reference getReference(Object obj) throws NamingException
{
Reference ref = null;
if (obj instanceof Reference) {
ref = (Reference) obj;
} else if (obj instanceof Referenceable) {
ref = ((Referenceable)(obj)).getReference();
}
return ref;
}
/**
* It tries to load the factory class for the given reference using the
* given class loader and return an instance of the same. Returns null
* if it can't load the class.
*
* @param ref
* @param cl
* @return
* @throws IllegalAccessException
* @throws InstantiationException
*/
private ObjectFactory getObjectFactory(Reference ref, ClassLoader cl)
throws IllegalAccessException, InstantiationException
{
String factoryName = ref.getFactoryClassName();
if (factoryName != null) {
try
{
Class c = Class.forName(factoryName, false, cl);
return (ObjectFactory)c.newInstance();
}
catch (ClassNotFoundException e)
{
// ignore only CNFE, all other exceptions are considered errors
}
}
return null;
}
/**
* Lookup the specifed name in the context. Returns the resolved object.
*
* @return the resolved object.
* @throws NamingException if there is a naming exception.
*/
@Override
public Object lookup(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
return lookup(name.toString());
}
/**
* Bind the object to the specified name.
*
* @param name name that the object is being bound to.
* @param obj object that is being bound.
* @throws NamingException if there is a naming exception.
*/
@Override
public void bind(String name, Object obj) throws NamingException {
name = getRelativeName(name);
if (isjavaURL(name)) {
javaUrlContext.bind(name, obj);
} else {
try {
getProvider().bind(name, obj);
} catch (RemoteException ex) {
throw new CommunicationException(ex.toString());
}
}
}
/**
* Bind the object to the specified name.
*
* @param name name that the object is being bound to.
* @param obj object that is being bound.
* @throws NamingException if there is a naming exception.
*/
@Override
public void bind(Name name, Object obj) throws NamingException {
// Flat namespace; no federation; just call string version
bind(name.toString(), obj);
}
/**
* Rebind the object to the specified name.
*
* @param name name that the object is being bound to.
* @param obj object that is being bound.
* @throws NamingException if there is a naming exception.
*/
@Override
public void rebind(String name, Object obj) throws NamingException {
name = getRelativeName(name);
if (isjavaURL(name)) {
javaUrlContext.rebind(name, obj);
} else {
try {
getProvider().rebind(name, obj);
} catch (RemoteException ex) {
throw new CommunicationException(ex.toString());
}
}
}
/**
* Rebind the object to the specified name.
*
* @param name name that the object is being bound to.
* @param obj object that is being bound.
* @throws NamingException if there is a naming exception.
*/
@Override
public void rebind(Name name, Object obj) throws NamingException {
// Flat namespace; no federation; just call string version
rebind(name.toString(), obj);
}
/**
* Unbind the object with the specified name.
*
* @param name that is being unbound.
* @throws NamingException if there is a naming exception.
*/
@Override
public void unbind(String name) throws NamingException {
name = getRelativeName(name);
if (isjavaURL(name)) {
javaUrlContext.unbind(name);
} else {
try {
getProvider().unbind(name);
} catch (RemoteException ex) {
throw new CommunicationException(ex.toString());
}
}
}
/**
* Unbind the object with the specified name.
*
* @param name name that is being unbound.
* @throws NamingException if there is a naming exception.
*/
@Override
public void unbind(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
unbind(name.toString());
}
/**
* Rename the bound object.
*
* @param oldname old name that the object is bound as.
* @param newname new name that the object will be bound as.
* @throws NamingException if there is a naming exception.
*/
@Override
public void rename(String oldname, String newname) throws NamingException {
oldname = getRelativeName(oldname);
newname = getRelativeName(newname);
if (isjavaURL(oldname)) {
javaUrlContext.rename(oldname, newname);
} else {
try {
getProvider().rename(oldname, newname);
} catch (RemoteException ex) {
throw new CommunicationException(ex.toString());
}
}
}
/**
* Rename the bound object.
*
* @param oldname old name that the object is bound as.
* @param newname new name that the object will be bound as.
* @throws NamingException if there is a naming exception.
*/
@Override
public void rename(Name oldname, Name newname) throws NamingException {
// Flat namespace; no federation; just call string version
rename(oldname.toString(), newname.toString());
}
/**
* List the contents of the specified context.
*
* @param name context name.
* @return an enumeration of the contents.
* @throws NamingException if there is a naming exception.
*/
@Override
public NamingEnumeration<NameClassPair> list(String name) throws NamingException {
if (name.isEmpty()) {
// listing this context
try {
Hashtable bindings = getProvider().list(myName);
return new RepNames<NameClassPair>(bindings);
} catch (RemoteException ex) {
throw new CommunicationException(ex.toString());
}
}
name = getRelativeName(name);
if (isjavaURL(name)) {
return javaUrlContext.list(name);
} else {
// Perhaps 'name' names a context
Object target = lookup(name);
if (target instanceof Context) {
return ((Context) target).list("");
}
throw new NotContextException(name + " cannot be listed");
}
}
/**
* List the contents of the specified context.
*
* @param name context name.
* @return an enumeration of the contents.
* @throws NamingException if there is a naming exception.
*/
@Override
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
return list(name.toString());
}
/**
* List the bindings in the specified context.
*
* @param name context name.
* @return an enumeration of the bindings.
* @throws NamingException if there is a naming exception.
*/
@Override
public NamingEnumeration<Binding> listBindings(String name) throws NamingException {
if (name.isEmpty()) {
// listing this context
try {
Hashtable bindings = getProvider().list(myName);
return new RepBindings<Binding>(bindings);
} catch (RemoteException ex) {
CommunicationException ce = new CommunicationException(ex
.toString());
ce.initCause(ex);
throw ce;
}
}
name = getRelativeName(name);
if (isjavaURL(name)) {
return javaUrlContext.listBindings(name);
} else {
// Perhaps 'name' names a context
Object target = lookup(name);
if (target instanceof Context) {
return ((Context) target).listBindings("");
}
throw new NotContextException(name + " cannot be listed");
}
}
/**
* List the bindings in the specified context.
*
* @param name context name.
* @return an enumeration of the bindings.
* @throws NamingException if there is a naming exception.
*/
@Override
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
return listBindings(name.toString());
}
/**
* Destroy the specified subcontext.
*
* @param name name of the subcontext.
* @throws NamingException if there is a naming exception.
*/
@Override
public void destroySubcontext(String name) throws NamingException {
name = getRelativeName(name);
if (isjavaURL(name)) {
javaUrlContext.destroySubcontext(name);
} else {
try {
getProvider().destroySubcontext(name);
} catch (RemoteException e) {
CommunicationException ce = new CommunicationException(e
.toString());
ce.initCause(e);
throw ce;
}
}
}
/**
* Destroy the specified subcontext.
*
* @param name name of the subcontext.
* @throws NamingException if there is a naming exception.
*/
@Override
public void destroySubcontext(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
destroySubcontext(name.toString());
}
/**
* Create the specified subcontext.
*
* @param name name of the subcontext.
* @return the created subcontext.
* @throws NamingException if there is a naming exception.
*/
@Override
public Context createSubcontext(String name) throws NamingException {
Context c = null;
name = getRelativeName(name);
if (isjavaURL(name)) {
return javaUrlContext.createSubcontext(name);
} else {
try {
c = getProvider().createSubcontext(name);
/*
* this simulates the transient context structure on the client
* side. Have to do this - as reference to Transient Context is
* not resolved properly due to rmi
*/
if (c instanceof Context) {
c = new SerialContext(name, myEnv, habitat);
}
} catch (RemoteException e) {
CommunicationException ce = new CommunicationException(e
.toString());
ce.initCause(e);
throw ce;
}
return c;
}
}
/**
* Create the specified subcontext.
*
* @param name name of the subcontext.
* @return the created subcontext.
* @throws NamingException if there is a naming exception.
*/
@Override
public Context createSubcontext(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
return createSubcontext(name.toString());
}
/**
* Links are not treated specially.
*
* @param name name of the link.
* @return the resolved object.
* @throws NamingException if there is a naming exception.
*/
@Override
public Object lookupLink(String name) throws NamingException {
name = getRelativeName(name);
if (isjavaURL(name)) {
return javaUrlContext.lookupLink(name);
} else {
// This flat context does not treat links specially
return lookup(name);
}
}
/**
* Links are not treated specially.
*
* @param name name of the link.
* @return the resolved object.
* @throws NamingException if there is a naming exception.
*/
@Override
public Object lookupLink(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
return lookupLink(name.toString());
}
/**
* Allow access to the name parser object.
*
* @param name JNDI name, is ignored since there is only one Name Parser
* object.
* @return NameParser object
* @throws NamingException
*/
@Override
public NameParser getNameParser(String name) throws NamingException {
return myParser;
}
/**
* Allow access to the name parser object.
*
* @param name JNDI name, is ignored since there is only one Name Parser
* object.
* @return NameParser object
* @throws NamingException
*/
@Override
public NameParser getNameParser(Name name) throws NamingException {
// Flat namespace; no federation; just call string version
return getNameParser(name.toString());
}
@Override
public String composeName(String name, String prefix)
throws NamingException {
Name result = composeName(new CompositeName(name), new CompositeName(
prefix));
return result.toString();
}
@Override
public Name composeName(Name name, Name prefix) throws NamingException {
Name result = (Name) (prefix.clone());
result.addAll(name);
return result;
}
/**
* Add to the environment for the current context.
*
* @throws NamingException if there is a naming exception.
*/
@Override
public Object addToEnvironment(String propName, Object propVal)
throws NamingException {
if (myEnv == null) {
myEnv = new Hashtable(5, 0.75f);
}
return myEnv.put(propName, propVal);
}
/**
* Remove from the environment for the current context.
*
* @throws NamingException if there is a naming exception.
*/
@Override
public Object removeFromEnvironment(String propName) throws NamingException {
if (myEnv == null) {
return null;
}
return myEnv.remove(propName);
}
/**
* Return the environment for the current context.
*
* @throws NamingException if there is a naming exception.
*/
@Override
public Hashtable getEnvironment() throws NamingException {
if (myEnv == null) {
// Must return non-null
myEnv = new Hashtable(3, 0.75f);
}
return myEnv;
}
/**
* Set the environment for the current context to null when close is called.
*
* @throws NamingException if there is a naming exception.
*/
@Override
public void close() throws NamingException {
myEnv = null;
}
private String getRelativeName(String name) {
if (!myName.equals("")) {
name = myName + "/" + name;
}
return name;
}
// Class for enumerating name/class pairs
static class RepNames<T> implements NamingEnumeration<T> {
Hashtable bindings;
Enumeration names;
RepNames(Hashtable bindings) {
this.bindings = bindings;
this.names = bindings.keys();
}
@Override
public boolean hasMoreElements() {
return names.hasMoreElements();
}
@Override
public boolean hasMore() throws NamingException {
return hasMoreElements();
}
@Override
public T nextElement() {
if (names.hasMoreElements()) {
String name = (String) names.nextElement();
String className = bindings.get(name).getClass().getName();
return (T) (new NameClassPair(name, className));
} else {
return null;
}
}
@Override
public T next() throws NamingException {
return nextElement();
}
@Override
public void close() {
//no-op since no steps needed to free up resources
}
}
// Class for enumerating bindings
static class RepBindings<T> implements NamingEnumeration<T> {
Enumeration names;
Hashtable bindings;
RepBindings(Hashtable bindings) {
this.bindings = bindings;
this.names = bindings.keys();
}
@Override
public boolean hasMoreElements() {
return names.hasMoreElements();
}
@Override
public boolean hasMore() throws NamingException {
return hasMoreElements();
}
@Override
public T nextElement() {
if (hasMoreElements()) {
String name = (String) names.nextElement();
return (T) (new Binding(name, bindings.get(name)));
} else {
return null;
}
}
@Override
public T next() throws NamingException {
return nextElement();
}
@Override
public void close() {
//no-op since no steps needed to free up resources
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("SerialContext[");
if(testMode) {
sb.append("( IN TEST MODE ) ");
}
sb.append( "myEnv=" ) ;
sb.append( myEnv ) ;
return sb.toString();
}
private class ProviderCacheKey {
// Key is either orb OR host/port combo.
private ORB localORB = null ;
private String endpoints = null ;
ProviderCacheKey(ORB orb) {
this.localORB = orb;
}
// Host and Port must both be non-null
ProviderCacheKey(String host, String port) {
endpoints = "corbaloc:iiop:1.2@" + host + ":" + port
+ "/NameService" ;
}
ProviderCacheKey( String endpoints ) {
this.endpoints = endpoints ;
}
@Override
public String toString() {
if (localORB == null) {
return "ProviderCacheKey[" + endpoints + "]" ;
} else {
return "ProviderCacheKey[" + localORB + "]" ;
}
}
public SerialContextProvider getNameService() throws InvalidName,
NotFound, CannotProceed,
org.omg.CosNaming.NamingContextPackage.InvalidName {
org.omg.CORBA.Object objref = null;
if (endpoints == null) {
objref = orb.resolve_initial_references( "NameService");
} else {
objref = orb.string_to_object(endpoints) ;
}
final NamingContext nctx = NamingContextHelper.narrow(objref);
final NameComponent[] path =
{ new NameComponent("SerialContextProvider", "") };
final org.omg.CORBA.Object obj = nctx.resolve(path) ;
SerialContextProvider result =
(SerialContextProvider)PortableRemoteObject.narrow( obj,
SerialContextProvider.class );
return result ;
}
@Override
public int hashCode() {
return (orb != null) ? orb.hashCode() : endpoints.hashCode();
}
@Override
public boolean equals(Object other) {
if (other == null) {
return false ;
}
if (!(other instanceof ProviderCacheKey)) {
return false ;
}
ProviderCacheKey otherKey = (ProviderCacheKey) other;
if (localORB != null) {
return localORB == otherKey.localORB ;
} else {
if (endpoints == null) {
return otherKey.endpoints == null ;
}
return endpoints.equals(otherKey.endpoints) ;
}
}
}
}