| /* |
| * Copyright (c) 1997, 2018 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0, which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * This Source Code may also be made available under the following Secondary |
| * Licenses when the conditions for such availability set forth in the |
| * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, |
| * version 2 with the GNU Classpath Exception, which is available at |
| * https://www.gnu.org/software/classpath/license.html. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 |
| */ |
| |
| package com.sun.enterprise.naming.impl; |
| |
| import org.glassfish.api.invocation.ComponentInvocation; |
| import org.glassfish.api.invocation.InvocationManager; |
| import org.glassfish.api.naming.GlassfishNamingManager; |
| import org.glassfish.api.naming.JNDIBinding; |
| import org.glassfish.api.naming.NamingObjectProxy; |
| import org.glassfish.hk2.api.ServiceLocator; |
| import org.glassfish.logging.annotation.LogMessageInfo; |
| |
| import org.jvnet.hk2.annotations.Service; |
| import jakarta.inject.Singleton; |
| import org.omg.CORBA.ORB; |
| |
| import jakarta.inject.Inject; |
| import javax.naming.Binding; |
| import javax.naming.CompositeName; |
| import javax.naming.Context; |
| import javax.naming.InitialContext; |
| import javax.naming.Name; |
| import javax.naming.NameAlreadyBoundException; |
| import javax.naming.NameClassPair; |
| import javax.naming.NameNotFoundException; |
| import javax.naming.NameParser; |
| import javax.naming.NamingEnumeration; |
| import javax.naming.NamingException; |
| import javax.naming.NotContextException; |
| import javax.naming.Reference; |
| import javax.naming.StringRefAddr; |
| import java.rmi.Remote; |
| import java.rmi.RemoteException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Hashtable; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.StringTokenizer; |
| import java.util.logging.Level; |
| |
| import static com.sun.enterprise.naming.util.LogFacade.logger; |
| |
| /** |
| * This is the manager that handles all naming operations including |
| * publishObject as well as binding environment props, resource and ejb |
| * references in the namespace. |
| */ |
| |
| @Service |
| @Singleton |
| public final class GlassfishNamingManagerImpl implements GlassfishNamingManager { |
| @LogMessageInfo(message = "Error during CosNaming.unbind for name {0}: {1}") |
| public static final String ERROR_COSNAMING_UNBIND = "AS-NAMING-00004"; |
| |
| @LogMessageInfo(message = "Naming binding already exists for {0} in namespace {1}") |
| public static final String NAMING_ALREADY_EXISTS = "AS-NAMING-00005"; |
| |
| public static final String IIOPOBJECT_FACTORY = |
| "com.sun.enterprise.naming.util.IIOPObjectFactory"; |
| |
| private static final int JAVA_COMP_LENGTH = "java:comp".length(); |
| private static final int JAVA_MODULE_LENGTH = "java:module".length(); |
| |
| @Inject |
| private ServiceLocator habitat; |
| |
| //@Inject |
| volatile InvocationManager invMgr=null; |
| |
| private InitialContext initialContext; |
| private Context cosContext; |
| |
| private NameParser nameParser = new SerialNameParser(); |
| |
| private Map componentNamespaces; |
| private Map<String, Map> appNamespaces; |
| private Map<AppModuleKey, Map> moduleNamespaces; |
| private Map<String, ComponentIdInfo> componentIdInfo; |
| |
| |
| public GlassfishNamingManagerImpl() throws NamingException { |
| this(new InitialContext()); |
| } |
| |
| //Used only for Junit Testing |
| void setInvocationManager(final InvocationManager invMgr) { |
| this.invMgr = invMgr; |
| } |
| |
| /** |
| * Create the naming manager. Creates a new initial context. |
| */ |
| public GlassfishNamingManagerImpl(InitialContext ic) |
| throws NamingException { |
| initialContext = ic; |
| componentNamespaces = new Hashtable(); |
| appNamespaces = new HashMap<String, Map>(); |
| moduleNamespaces = new HashMap<AppModuleKey, Map>(); |
| componentIdInfo = new HashMap<String, ComponentIdInfo>(); |
| |
| JavaURLContext.setNamingManager(this); |
| } |
| |
| |
| /** |
| * Get the initial naming context. |
| */ |
| public Context getInitialContext() { |
| return initialContext; |
| } |
| |
| |
| public NameParser getNameParser() { |
| return nameParser; |
| } |
| |
| |
| public Remote initializeRemoteNamingSupport(ORB orb) throws NamingException { |
| Remote remoteProvider; |
| try { |
| // Now that we have an ORB, initialize the CosNaming service |
| // and set it on the server's naming service. |
| Hashtable cosNamingEnv = new Hashtable(); |
| cosNamingEnv.put("java.naming.factory.initial", "org.glassfish.jndi.cosnaming.CNCtxFactory"); |
| cosNamingEnv.put("java.naming.corba.orb", orb); |
| cosContext = new InitialContext(cosNamingEnv); |
| ProviderManager pm = ProviderManager.getProviderManager(); |
| |
| // Initialize RemoteSerialProvider. This allows access to the naming |
| // service from clients. |
| remoteProvider = pm.initRemoteProvider(orb); |
| } catch(RemoteException re) { |
| NamingException ne = new NamingException("Exception during remote naming initialization"); |
| ne.initCause(ne); |
| throw ne; |
| } |
| |
| return remoteProvider; |
| } |
| |
| private Context getCosContext() { |
| return cosContext; |
| } |
| |
| /** |
| * Publish a name in the naming service. |
| * |
| * @param name Name that the object is bound as. |
| * @param obj Object that needs to be bound. |
| * @param rebind flag |
| * @throws javax.naming.NamingException if there is a naming exception. |
| */ |
| public void publishObject(String name, Object obj, boolean rebind) |
| throws NamingException { |
| Name nameobj = new CompositeName(name); |
| publishObject(nameobj, obj, rebind); |
| } |
| |
| /** |
| * Publish a name in the naming service. |
| * |
| * @param name Name that the object is bound as. |
| * @param obj Object that needs to be bound. |
| * @param rebind flag |
| * @throws javax.naming.NamingException if there is a naming exception. |
| */ |
| public void publishObject(Name name, Object obj, boolean rebind) |
| throws NamingException { |
| if (rebind) { |
| initialContext.rebind(name, obj); |
| } else { |
| initialContext.bind(name, obj); |
| } |
| } |
| |
| |
| public void publishCosNamingObject(String name, Object obj, boolean rebind) |
| throws NamingException { |
| |
| |
| Name nameObj = new CompositeName(name); |
| |
| // Create any COS naming sub-contexts in name |
| // that don't already exist. |
| createSubContexts(nameObj, getCosContext()); |
| |
| if (rebind) { |
| getCosContext().rebind(name, obj); |
| } else { |
| getCosContext().bind(name, obj); |
| } |
| |
| // Bind a reference to it in the SerialContext using |
| // the same name. This is needed to allow standalone clients |
| // to lookup the object using the same JNDI name. |
| // It is also used from bindObjects while populating ejb-refs in |
| // the java:comp namespace. |
| Object serialObj = new Reference("reference", |
| new StringRefAddr("url", name), |
| IIOPOBJECT_FACTORY, null); |
| |
| publishObject(name, serialObj, rebind); |
| |
| } |
| |
| public void unpublishObject(String name) |
| throws NamingException { |
| |
| |
| initialContext.unbind(name); |
| } |
| |
| /** |
| * Remove an object from the naming service. |
| * |
| * @param name Name that the object is bound as. |
| * @throws Exception |
| */ |
| public void unpublishCosNamingObject(String name) |
| throws NamingException { |
| try { |
| getCosContext().unbind(name); |
| } catch(NamingException cne) { |
| logger.log(Level.WARNING, ERROR_COSNAMING_UNBIND, new Object[] {name, cne}); |
| } |
| initialContext.unbind(name); |
| } |
| |
| |
| /** |
| * Remove an object from the naming service. |
| * |
| * @param name Name that the object is bound as. |
| * @throws Exception |
| */ |
| public void unpublishObject(Name name) throws NamingException { |
| this.unpublishObject(name.toString()); |
| } |
| |
| /** |
| * Create any sub-contexts in name that don't already exist. |
| * |
| * @param name Name containing sub-contexts to create |
| * @param rootCtx in which sub-contexts should be created |
| * @throws Exception |
| */ |
| private void createSubContexts(Name name, Context rootCtx) throws NamingException { |
| int numSubContexts = name.size() - 1; |
| Context currentCtx = rootCtx; |
| |
| for (int subCtxIndex = 0; subCtxIndex < numSubContexts; subCtxIndex++) { |
| String subCtxName = name.get(subCtxIndex); |
| try { |
| |
| Object obj = currentCtx.lookup(subCtxName); |
| |
| if (obj == null) { |
| // Doesn't exist so create it. |
| currentCtx = currentCtx.createSubcontext(subCtxName); |
| } else if (obj instanceof Context) { |
| // OK -- no need to create it. |
| currentCtx = (Context) obj; |
| } else { |
| // Context name clashes with existing object. |
| throw new NameAlreadyBoundException(subCtxName); |
| } |
| } |
| catch (NameNotFoundException e) { |
| // Doesn't exist so create it. |
| currentCtx = currentCtx.createSubcontext(subCtxName); |
| } |
| } // End for -- each sub-context |
| } |
| |
| private Map getComponentNamespace(String componentId) |
| throws NamingException { |
| // Note: HashMap is not synchronized. The namespace is populated |
| // at deployment time by a single thread, and then on there are |
| // no structural modifications (i.e. no keys added/removed). |
| // So the namespace doesnt need to be synchronized. |
| Map namespace = (Map) componentNamespaces.get(componentId); |
| if (namespace == null) { |
| namespace = new HashMap(); |
| componentNamespaces.put(componentId, namespace); |
| |
| // put entries for java:, java:comp and java:comp/env |
| JavaURLContext jc = new JavaURLContext("java:", null); |
| namespace.put("java:", jc); |
| namespace.put("java:/", jc); |
| JavaURLContext jcc = new JavaURLContext("java:comp", null); |
| |
| namespace.put("java:comp", jcc); |
| namespace.put("java:comp/", jcc); |
| JavaURLContext jccEnv = new JavaURLContext("java:comp/env", null); |
| namespace.put("java:comp/env", jccEnv); |
| namespace.put("java:comp/env/", jccEnv); |
| } |
| |
| return namespace; |
| } |
| |
| private Map getModuleNamespace(AppModuleKey appModuleKey) |
| throws NamingException { |
| |
| if( (appModuleKey.getAppName() == null) || |
| (appModuleKey.getModuleName() == null) ) { |
| throw new NamingException("Invalid appModuleKey " + appModuleKey); |
| } |
| |
| // Note: HashMap is not synchronized. The namespace is populated |
| // at deployment time by a single thread, and then on there are |
| // no structural modifications (i.e. no keys added/removed). |
| // So the namespace doesnt need to be synchronized. |
| Map namespace = moduleNamespaces.get(appModuleKey); |
| if (namespace == null) { |
| namespace = new Hashtable(); |
| moduleNamespaces.put(appModuleKey, namespace); |
| |
| // put entries for java:, java:comp and java:comp/env |
| JavaURLContext jc = new JavaURLContext("java:", null); |
| namespace.put("java:", jc); |
| namespace.put("java:/", jc); |
| |
| JavaURLContext jMod = new JavaURLContext("java:module", null); |
| namespace.put("java:module", jMod); |
| namespace.put("java:module/", jMod); |
| JavaURLContext jModEnv = new JavaURLContext("java:module/env", null); |
| namespace.put("java:module/env", jModEnv); |
| namespace.put("java:module/env/", jModEnv); |
| |
| } |
| |
| return namespace; |
| } |
| |
| private Object lookupFromNamespace(String name, Map namespace, Hashtable env) throws NamingException { |
| Object o = namespace.get(name); |
| if (o == null) { |
| throw new NameNotFoundException("No object bound to name " + name); |
| } else { |
| if (o instanceof NamingObjectProxy) { |
| NamingObjectProxy namingProxy = (NamingObjectProxy) o; |
| InitialContext ic = initialContext; |
| if(env != null){ |
| ic = new InitialContext(env); |
| } |
| o = namingProxy.create(ic); |
| } else if (o instanceof Reference) { |
| try { |
| o = getObjectInstance(name, o, env); |
| } catch (Exception e) { |
| if (logger.isLoggable(Level.FINEST)) { |
| logger.log(Level.FINEST, "Unable to get Object instance from Reference for name [" + name + "]. " + |
| "Hence returning the Reference object ", e); |
| } |
| } |
| } |
| return o; |
| } |
| } |
| |
| /** |
| * @inheritDoc |
| */ |
| public Object lookupFromAppNamespace(String appName, String name, Hashtable env) throws NamingException { |
| Map namespace = getAppNamespace(appName); |
| return lookupFromNamespace(name, namespace, env); |
| } |
| |
| /** |
| * @inheritDoc |
| */ |
| public Object lookupFromModuleNamespace(String appName, String moduleName, String name, Hashtable env) |
| throws NamingException { |
| AppModuleKey appModuleKey = new AppModuleKey(appName, moduleName); |
| Map namespace = getModuleNamespace(appModuleKey); |
| return lookupFromNamespace(name, namespace, env); |
| } |
| |
| private Object getObjectInstance(String name, Object obj, Hashtable env) throws Exception { |
| |
| if(env == null){ |
| env = new Hashtable(); |
| } |
| return javax.naming.spi.NamingManager.getObjectInstance(obj, new CompositeName(name), null, env); |
| } |
| |
| private Map getAppNamespace(String appName) |
| throws NamingException { |
| |
| if( appName == null ) { |
| throw new NamingException("Null appName"); |
| } |
| |
| // Note: HashMap is not synchronized. The namespace is populated |
| // at deployment time by a single thread, and then on there are |
| // no structural modifications (i.e. no keys added/removed). |
| // So the namespace doesnt need to be synchronized. |
| Map namespace = appNamespaces.get(appName); |
| if (namespace == null) { |
| namespace = new Hashtable(); |
| appNamespaces.put(appName, namespace); |
| |
| // put entries for java:, java:comp and java:comp/env |
| JavaURLContext jc = new JavaURLContext("java:", null); |
| namespace.put("java:", jc); |
| namespace.put("java:/", jc); |
| |
| JavaURLContext jApp = new JavaURLContext("java:app", null); |
| namespace.put("java:app", jApp); |
| namespace.put("java:app/", jApp); |
| JavaURLContext jAppEnv = new JavaURLContext("java:app/env", null); |
| namespace.put("java:app/env", jAppEnv); |
| namespace.put("java:app/env/", jAppEnv); |
| |
| } |
| |
| return namespace; |
| } |
| |
| |
| private Map getNamespace(String componentId, String logicalJndiName) throws NamingException { |
| |
| ComponentIdInfo info = componentIdInfo.get(componentId); |
| |
| return (info != null) ? getNamespace(info.appName, info.moduleName, componentId, logicalJndiName) : |
| getComponentNamespace(componentId); |
| } |
| |
| private Map getNamespace(String appName, String moduleName, |
| String componentId, String logicalJndiName) throws NamingException { |
| Map namespace; |
| if( logicalJndiName.startsWith("java:comp") ) { |
| namespace = getComponentNamespace(componentId); |
| } else if ( logicalJndiName.startsWith("java:module")) { |
| namespace = getModuleNamespace(new AppModuleKey(appName, moduleName)); |
| } else if ( logicalJndiName.startsWith("java:app")) { |
| namespace = getAppNamespace(appName); |
| } else { |
| // return component namespace |
| namespace = getComponentNamespace(componentId); |
| } |
| |
| return namespace; |
| } |
| |
| /** |
| * This method binds them in a java:namespace. |
| */ |
| |
| private void bindToNamespace(Map namespace, String logicalJndiName, Object value) |
| throws NamingException { |
| if (logger.isLoggable(Level.FINE)) { |
| logger.log(Level.FINE, "naming.bind Binding name:{0}", logicalJndiName); |
| } |
| |
| if (namespace.put(logicalJndiName, value) != null) { |
| logger.log(Level.WARNING, NAMING_ALREADY_EXISTS, new Object[]{logicalJndiName, namespace.toString()}); |
| } |
| |
| bindIntermediateContexts(namespace, logicalJndiName); |
| } |
| |
| private boolean existsInNamespace(Map namespace, String logicalJndiName) { |
| |
| return namespace.containsKey(logicalJndiName); |
| |
| } |
| |
| /** |
| * This method enumerates the env properties, ejb and resource references |
| * etc for a J2EE component and binds them in the component's java:comp |
| * namespace. |
| */ |
| public void bindToComponentNamespace(String appName, String moduleName, |
| String componentId, boolean treatComponentAsModule, |
| Collection<? extends JNDIBinding> bindings) |
| throws NamingException { |
| |
| // These are null in rare cases, e.g. default web app. |
| if( (appName != null) && (moduleName != null) ) { |
| |
| ComponentIdInfo info = new ComponentIdInfo(); |
| info.appName = appName; |
| info.moduleName = moduleName; |
| info.componentId = componentId; |
| info.treatComponentAsModule = treatComponentAsModule; |
| |
| componentIdInfo.put(componentId, info); |
| } |
| |
| for (JNDIBinding binding : bindings) { |
| |
| String logicalJndiName = binding.getName(); |
| |
| Map namespace = null; |
| |
| if( treatComponentAsModule && logicalJndiName.startsWith("java:comp")) { |
| logicalJndiName = logicalCompJndiNameToModule(logicalJndiName); |
| } |
| |
| if ( logicalJndiName.startsWith("java:comp")) { |
| |
| namespace = getComponentNamespace(componentId); |
| |
| |
| } else if ( logicalJndiName.startsWith("java:module")) { |
| |
| namespace = getModuleNamespace(new AppModuleKey(appName, moduleName)); |
| |
| } else if ( logicalJndiName.startsWith("java:app")) { |
| |
| namespace = getAppNamespace(appName); |
| } |
| |
| if( namespace != null ) { |
| if( !existsInNamespace(namespace, logicalJndiName)) { |
| bindToNamespace(namespace, logicalJndiName, binding.getValue()); |
| } |
| } |
| } |
| } |
| |
| private String logicalCompJndiNameToModule(String logicalCompName) { |
| String tail = logicalCompName.substring(JAVA_COMP_LENGTH); |
| return "java:module" + tail; |
| } |
| |
| private String logicalModuleJndiNameToComp(String logicalModuleName) { |
| String tail = logicalModuleName.substring(JAVA_MODULE_LENGTH); |
| return "java:comp" + tail; |
| } |
| |
| |
| /** |
| * @inheritDoc |
| */ |
| public void bindToModuleNamespace(String appName, String moduleName, Collection<? extends JNDIBinding> bindings) |
| throws NamingException { |
| AppModuleKey appModuleKey = new AppModuleKey(appName, moduleName); |
| Map namespace = getModuleNamespace(appModuleKey); |
| for (JNDIBinding binding : bindings) { |
| String logicalJndiName = binding.getName(); |
| if ( logicalJndiName.startsWith("java:module")) { |
| bindToNamespace(namespace, binding.getName(), binding.getValue()); |
| } |
| } |
| } |
| |
| /** |
| * @inheritDoc |
| */ |
| public void bindToAppNamespace(String appName, Collection<? extends JNDIBinding> bindings) |
| throws NamingException { |
| Map namespace = getAppNamespace(appName); |
| for (JNDIBinding binding : bindings) { |
| String logicalJndiName = binding.getName(); |
| if ( logicalJndiName.startsWith("java:app")) { |
| bindToNamespace(namespace, binding.getName(), binding.getValue()); |
| } |
| } |
| } |
| |
| private void bindIntermediateContexts(Map namespace, String name) |
| throws NamingException { |
| // for each component of name, put an entry into namespace |
| String partialName; |
| if( name.startsWith("java:comp/") ) { |
| partialName = "java:comp"; |
| } else if( name.startsWith("java:module/")) { |
| partialName = "java:module"; |
| } else if( name.startsWith("java:app/")) { |
| partialName = "java:app"; |
| } else { |
| throw new NamingException("Invalid environment namespace name : " + name); |
| } |
| |
| name = name.substring((partialName + "/").length()); |
| StringTokenizer toks = new StringTokenizer(name, "/", false); |
| StringBuilder sb=new StringBuilder(); |
| sb.append(partialName); |
| while (toks.hasMoreTokens()) { |
| String tok = toks.nextToken(); |
| sb.append("/").append(tok); |
| partialName = sb.toString(); |
| if (namespace.get(partialName) == null) { |
| namespace.put(partialName, new JavaURLContext(partialName, null)); |
| } |
| } |
| } |
| |
| |
| /** |
| * This method enumerates the env properties, ejb and resource references |
| * and unbinds them from the java:comp namespace. |
| */ |
| public void unbindComponentObjects(String componentId) throws NamingException { |
| componentNamespaces.remove(componentId); // remove local namespace cache |
| componentIdInfo.remove(componentId); |
| } |
| |
| public void unbindAppObjects(String appName) throws NamingException { |
| |
| appNamespaces.remove(appName); |
| Iterator moduleEntries = moduleNamespaces.entrySet().iterator(); |
| while( moduleEntries.hasNext() ) { |
| Map.Entry entry = (Map.Entry) moduleEntries.next(); |
| |
| if( ((AppModuleKey) entry.getKey()).getAppName().equals(appName)) { |
| moduleEntries.remove(); |
| } |
| } |
| } |
| |
| /** |
| * @inheritDoc |
| */ |
| public void unbindAppObject(String appName, String name) throws NamingException { |
| Map<String, Map> namespaces = appNamespaces.get(appName); |
| if(namespaces != null){ |
| namespaces.remove(name); |
| } |
| } |
| |
| /** |
| * @inheritDoc |
| */ |
| public void unbindModuleObject(String appName, String moduleName, String name) throws NamingException { |
| AppModuleKey appModuleKey = new AppModuleKey(appName, moduleName); |
| Map<String, Map> namespaces = moduleNamespaces.get(appModuleKey); |
| if(namespaces != null){ |
| namespaces.remove(name); |
| } |
| } |
| |
| /** |
| * Recreate a context for java:comp/env or one of its sub-contexts given the |
| * context name. |
| */ |
| public Context restoreJavaCompEnvContext(String contextName) |
| throws NamingException { |
| if (!contextName.startsWith("java:")) { |
| throw new NamingException("Invalid context name [" + contextName |
| + "]. Name must start with java:"); |
| } |
| |
| return new JavaURLContext(contextName, null); |
| } |
| |
| public Object lookup(String name) throws NamingException { |
| return lookup(name, (SerialContext)null); |
| } |
| |
| /** |
| * This method is called from SerialContext class. The serialContext |
| * instance that was created by the appclient's Main class is passed so that |
| * stickiness is preserved. Called from javaURLContext.lookup, for java:comp |
| * names. |
| */ |
| public Object lookup(String name, SerialContext serialContext) |
| throws NamingException { |
| Context ic; |
| |
| if (serialContext != null) { |
| ic = serialContext; |
| } else { |
| ic = initialContext; |
| } |
| |
| // initialContext is used as ic in case of PE while |
| // serialContext is used as ic in case of EE/SE |
| |
| // Get the component id and namespace to lookup |
| String componentId = getComponentId(); |
| return lookup(componentId, name, ic); |
| } |
| |
| /** |
| * Lookup object for a particular componentId and name. |
| */ |
| public Object lookup(String componentId, String name) throws NamingException { |
| |
| return lookup(componentId, name, initialContext); |
| |
| } |
| |
| private Object lookup(String componentId, String name, Context ctx) throws NamingException { |
| ComponentIdInfo info = componentIdInfo.get(componentId); |
| String logicalJndiName = name; |
| boolean replaceName = (info != null) && (info.treatComponentAsModule) |
| && name.startsWith("java:comp"); |
| if( replaceName ) { |
| logicalJndiName = logicalCompJndiNameToModule(name); |
| } |
| |
| Map namespace = getNamespace(componentId, logicalJndiName); |
| |
| Object obj = namespace.get(logicalJndiName); |
| |
| if (obj == null) |
| throw new NameNotFoundException("No object bound to name " + name); |
| |
| if (obj instanceof NamingObjectProxy) { |
| NamingObjectProxy namingProxy = (NamingObjectProxy) obj; |
| obj = namingProxy.create(ctx); |
| } else if( obj instanceof Context ) { |
| // Need to preserve the original prefix so that further operations |
| // on the context maintain the correct external view. In the case |
| // of a replaced java:comp, create a new equivalent javaURLContext |
| // and return that. |
| if( replaceName ) { |
| obj = new JavaURLContext(name, null); |
| } |
| |
| if (obj instanceof JavaURLContext) { |
| if (ctx instanceof SerialContext) { |
| obj = new JavaURLContext( (JavaURLContext)obj, |
| (SerialContext)ctx ) ; |
| } else { |
| obj = new JavaURLContext( (JavaURLContext)obj, null ) ; |
| } |
| } |
| } |
| |
| return obj; |
| } |
| |
| |
| public NamingEnumeration<NameClassPair> list(String name) throws NamingException { |
| ArrayList list = listNames(name); |
| return new BindingsIterator<NameClassPair>(this, list.iterator(), true); |
| } |
| |
| public NamingEnumeration<Binding> listBindings(String name) throws NamingException { |
| ArrayList list = listNames(name); |
| return new BindingsIterator<Binding>(this, list.iterator(), false); |
| } |
| |
| private ArrayList listNames(String name) throws NamingException { |
| // Get the component id and namespace to lookup |
| String componentId = getComponentId(); |
| |
| ComponentIdInfo info = componentIdInfo.get(componentId); |
| String logicalJndiName = name; |
| |
| boolean replaceName = (info != null) && (info.treatComponentAsModule) |
| && name.startsWith("java:comp"); |
| if( replaceName ) { |
| logicalJndiName = logicalCompJndiNameToModule(name); |
| } |
| |
| Map namespace = getNamespace(componentId, logicalJndiName); |
| |
| Object obj = namespace.get(logicalJndiName); |
| |
| if (obj == null) |
| throw new NameNotFoundException("No object bound to name " + name); |
| |
| if (!(obj instanceof JavaURLContext)) |
| throw new NotContextException(name + " cannot be listed"); |
| |
| // This iterates over all names in entire component namespace, |
| // so its a little inefficient. The alternative is to store |
| // a list of bindings in each javaURLContext instance. |
| ArrayList list = new ArrayList(); |
| Iterator itr = namespace.keySet().iterator(); |
| if (!logicalJndiName.endsWith("/")) |
| logicalJndiName = logicalJndiName + "/"; |
| while (itr.hasNext()) { |
| String key = (String) itr.next(); |
| // Check if key begins with name and has only 1 component extra |
| // (i.e. no more slashes) |
| // Make sure keys reflect the original prefix in the case of comp->module |
| // replacement |
| // The search string itself is excluded from the returned list |
| if (key.startsWith(logicalJndiName) && |
| key.indexOf('/', logicalJndiName.length()) == -1 && |
| !key.equals(logicalJndiName)) { |
| String toAdd = replaceName ? logicalModuleJndiNameToComp(key) : key; |
| list.add(toAdd); |
| } |
| } |
| return list; |
| } |
| |
| /** |
| * Get the component id from the Invocation Manager. |
| * |
| * @return the component id as a string. |
| */ |
| private String getComponentId() throws NamingException { |
| String id; |
| |
| ComponentInvocation ci; |
| if (invMgr==null) { |
| ci= habitat.<InvocationManager>getService(InvocationManager.class).getCurrentInvocation(); |
| } else { |
| ci= invMgr.getCurrentInvocation(); |
| } |
| |
| if (ci == null) { |
| throw new NamingException("Invocation exception: Got null ComponentInvocation "); |
| } |
| |
| try { |
| id = ci.getComponentId(); |
| if (id == null) { |
| throw new NamingException("Invocation exception: ComponentId is null"); |
| } |
| } catch (Throwable th) { |
| NamingException ine = new NamingException("Invocation exception: " + th); |
| ine.initCause(th); |
| throw ine; |
| } |
| |
| return id; |
| } |
| |
| private static class AppModuleKey { |
| |
| private String app; |
| private String module; |
| |
| public AppModuleKey(String appName, String moduleName) { |
| |
| app = appName; |
| module = moduleName; |
| |
| } |
| |
| public boolean equals(Object o) { |
| boolean equal = false; |
| if( (o != null) && (o instanceof AppModuleKey) ) { |
| AppModuleKey other = (AppModuleKey) o; |
| if( app.equals(other.app) && module.equals(other.module) ) { |
| equal = true; |
| } |
| } |
| return equal; |
| } |
| |
| public int hashCode() { |
| return app.hashCode(); |
| } |
| |
| public String getAppName() { return app; } |
| public String getModuleName() { return module; } |
| |
| public String toString() |
| { return "appName = " + app + " , module = " + module; } |
| } |
| |
| private static class ComponentIdInfo { |
| |
| String appName; |
| String moduleName; |
| String componentId; |
| boolean treatComponentAsModule; |
| |
| public String toString() |
| { return "appName = " + appName + " , module = " + moduleName + |
| " , componentId = " + componentId |
| + ", treatComponentAsModule = " + treatComponentAsModule; } |
| } |
| |
| private static class BindingsIterator<T> implements NamingEnumeration<T> { |
| private GlassfishNamingManagerImpl nm; |
| private Iterator names; |
| private boolean producesNamesOnly; |
| |
| BindingsIterator(GlassfishNamingManagerImpl nm, Iterator names, boolean producesNamesOnly) { |
| this.nm = nm; |
| this.names = names; |
| this.producesNamesOnly = producesNamesOnly; |
| } |
| |
| @Override |
| public boolean hasMoreElements() { |
| return names.hasNext(); |
| } |
| |
| @Override |
| public boolean hasMore() throws NamingException { |
| return hasMoreElements(); |
| } |
| |
| @Override |
| public T nextElement() { |
| if (names.hasNext()) { |
| try { |
| String name = (String) names.next(); |
| Object obj = nm.lookup(name); |
| return producesNamesOnly ? |
| (T) (new NameClassPair(name, getClass().getName())) : |
| (T) (new Binding(name, obj)); |
| } catch (RuntimeException ex) { |
| throw ex; |
| } catch (Exception ex) { |
| throw new RuntimeException(ex); |
| } |
| } 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 |
| } |
| } |
| } |