/** * * Copyright 2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.geronimo.j2ee.deployment; import java.net.URI; import java.util.List; import java.util.Map; import java.util.Set; import java.util.HashMap; import java.util.Iterator; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.naming.Reference; import javax.xml.namespace.QName; import org.apache.geronimo.common.DeploymentException; import org.apache.geronimo.common.UnresolvedReferenceException; import org.apache.geronimo.deployment.DeploymentContext; import org.apache.geronimo.gbean.GBeanData; import org.apache.geronimo.j2ee.j2eeobjectnames.J2eeContext; import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; import org.apache.geronimo.kernel.GBeanNotFoundException; import org.apache.geronimo.kernel.Kernel; import org.apache.geronimo.xbeans.j2ee.MessageDestinationType; /** * @version $Rev$ $Date$ */ public class RefContext { private final EJBReferenceBuilder ejbReferenceBuilder; private final ResourceReferenceBuilder resourceReferenceBuilder; private final ServiceReferenceBuilder serviceReferenceBuilder; private final Kernel kernel; private final Map messageDestinations = new HashMap(); public RefContext(EJBReferenceBuilder ejbReferenceBuilder, ResourceReferenceBuilder resourceReferenceBuilder, ServiceReferenceBuilder serviceReferenceBuilder, Kernel kernel) { assert ejbReferenceBuilder != null: "ejbReferenceBuilder is null"; assert resourceReferenceBuilder != null: "resourceReferenceBuilder is null"; assert serviceReferenceBuilder != null: "serviceReferenceBuilder is null"; this.ejbReferenceBuilder = ejbReferenceBuilder; this.resourceReferenceBuilder = resourceReferenceBuilder; this.serviceReferenceBuilder = serviceReferenceBuilder; this.kernel = kernel; } public static RefContext derivedClientRefContext(RefContext refContext, EJBReferenceBuilder ejbReferenceBuilder, ResourceReferenceBuilder resourceReferenceBuilder, ServiceReferenceBuilder serviceReferenceBuilder) { return new RefContext(refContext, ejbReferenceBuilder, resourceReferenceBuilder, serviceReferenceBuilder); } private RefContext(RefContext refContext, EJBReferenceBuilder ejbReferenceBuilder, ResourceReferenceBuilder resourceReferenceBuilder, ServiceReferenceBuilder serviceReferenceBuilder) { assert ejbReferenceBuilder != null: "ejbReferenceBuilder is null"; assert resourceReferenceBuilder != null: "resourceReferenceBuilder is null"; assert refContext != null: "ejbRefContext is null"; this.ejbReferenceBuilder = ejbReferenceBuilder; this.resourceReferenceBuilder = resourceReferenceBuilder; this.serviceReferenceBuilder = serviceReferenceBuilder; this.kernel = refContext.kernel; } //registration methods public void registerMessageDestionations(String moduleName, Map nameMap) throws DeploymentException { messageDestinations.put(moduleName, nameMap); } //lookup methods public Reference getEJBRemoteRef(String objectName, boolean isSession, String home, String remote) throws DeploymentException { return ejbReferenceBuilder.createEJBRemoteReference(objectName, null, isSession, home, remote); } public Reference getCORBARemoteRef(URI corbaURL, String objectName, ObjectName containerName, String home) throws DeploymentException { return ejbReferenceBuilder.createCORBAReference(corbaURL, objectName, containerName, home); } public Reference getEJBLocalRef(String objectName, boolean isSession, String localHome, String local) throws DeploymentException { return ejbReferenceBuilder.createEJBLocalReference(objectName, null, isSession, localHome, local); } public Object getHandleDelegateReference() throws DeploymentException { return ejbReferenceBuilder.createHandleDelegateReference(); } public Reference getEJBRemoteRef(URI module, String ejbLink, boolean isSession, String home, String remote, NamingContext namingContext) throws DeploymentException { GBeanData containerData = locateEjbInApplication(namingContext, isSession, ejbLink, module); return ejbReferenceBuilder.createEJBRemoteReference(containerData.getName().getCanonicalName(), containerData, isSession, home, remote); } public Reference getEJBLocalRef(URI module, String ejbLink, boolean isSession, String localHome, String local, NamingContext namingContext) throws DeploymentException { GBeanData containerData = locateEjbInApplication(namingContext, isSession, ejbLink, module); return ejbReferenceBuilder.createEJBLocalReference(containerData.getName().getCanonicalName(), containerData, isSession, localHome, local); } public Reference getConnectionFactoryRef(String containerId, Class iface) throws DeploymentException { return resourceReferenceBuilder.createResourceRef(containerId, iface); } public Reference getAdminObjectRef(String containerId, Class iface) throws DeploymentException { return resourceReferenceBuilder.createAdminObjectRef(containerId, iface); } public Object getServiceReference(Class serviceInterface, URI wsdlURI, URI jaxrpcMappingURI, QName serviceQName, Map portComponentRefMap, List handlerInfos, Object serviceRefType, DeploymentContext deploymentContext, Module module, ClassLoader classLoader) throws DeploymentException { return serviceReferenceBuilder.createService(serviceInterface, wsdlURI, jaxrpcMappingURI, serviceQName, portComponentRefMap, handlerInfos, serviceRefType, deploymentContext, module, classLoader); } public String getResourceAdapterContainerId(URI moduleURI, String resourceLink, NamingContext context) throws UnresolvedReferenceException { J2eeContext j2eeContext = context.getJ2eeContext(); ObjectName containerName = locateComponentName(resourceLink, moduleURI, NameFactory.JCA_RESOURCE, NameFactory.JCA_RESOURCE_ADAPTER, j2eeContext, context, "resource adapter"); return containerName.getCanonicalName(); } public String getConnectionFactoryContainerId(URI moduleURI, String resourceLink, String type, NamingContext context) throws UnresolvedReferenceException { J2eeContext j2eeContext = context.getJ2eeContext(); ObjectName containerName = locateComponentName(resourceLink, moduleURI, NameFactory.JCA_RESOURCE, type, j2eeContext, context, "connection factory"); return containerName.getCanonicalName(); } public Object getMessageDestination(String messageDestinationLink) throws DeploymentException { Object destination = null; int pos = messageDestinationLink.indexOf('#'); if (pos > -1) { String targetModule = messageDestinationLink.substring(0, pos); Map destinations = (Map) messageDestinations.get(targetModule); // Hmmm...if we don't find the module then something is wrong in the deployment. if (destinations == null) { StringBuffer sb = new StringBuffer(); for (Iterator mapIterator = messageDestinations.keySet().iterator(); mapIterator.hasNext();) { sb.append((String) mapIterator.next() + "\n"); } throw new DeploymentException("Unknown module " + targetModule + " when processing message destination " + messageDestinationLink + "\nKnown modules in deployable unit are:\n" + sb.toString()); } messageDestinationLink = messageDestinationLink.substring(pos + 1); destination = destinations.get(messageDestinationLink); } else { for (Iterator iterator = messageDestinations.values().iterator(); iterator.hasNext();) { Map destinations = (Map) iterator.next(); Object destinationTest = destinations.get(messageDestinationLink); if (destinationTest != null) { if (destination != null) { throw new DeploymentException("Duplicate message destination " + messageDestinationLink + " accessed from a message-destination-link without a module"); } destination = destinationTest; } } } return destination; } public String getAdminObjectContainerId(URI moduleURI, String resourceLink, NamingContext context) throws DeploymentException { J2eeContext j2eeContext = context.getJ2eeContext(); ObjectName containerName = locateComponentName(resourceLink, moduleURI, NameFactory.JCA_RESOURCE, NameFactory.JCA_ADMIN_OBJECT, j2eeContext, context, "admin object"); return containerName.getCanonicalName(); } public Reference getImplicitEJBRemoteRef(URI module, String refName, boolean isSession, String home, String remote, NamingContext namingContext) throws DeploymentException { return ejbReferenceBuilder.getImplicitEJBRemoteRef(module, refName, isSession, home, remote, namingContext); } public Reference getImplicitEJBLocalRef(URI module, String refName, boolean isSession, String localHome, String local, NamingContext namingContext) throws DeploymentException { return ejbReferenceBuilder.getImplicitEJBLocalRef(module, refName, isSession, localHome, local, namingContext); } //Resource adapter/activationspec support public GBeanData getResourceAdapterGBeanData(ObjectName resourceAdapterModuleName, NamingContext context) throws DeploymentException { GBeanData resourceModuleData = locateComponentData(resourceAdapterModuleName, context); return resourceReferenceBuilder.locateResourceAdapterGBeanData(resourceModuleData); } public GBeanData getActivationSpecInfo(ObjectName resourceAdapterModuleName, String messageListenerInterfaceName, NamingContext context) throws DeploymentException { GBeanData resourceModuleData = locateComponentData(resourceAdapterModuleName, context); return resourceReferenceBuilder.locateActivationSpecInfo(resourceModuleData, messageListenerInterfaceName); } //this relies on finding the resource adapter, not the admin object. public GBeanData getAdminObjectInfo(ObjectName resourceAdapterModuleName, String adminObjectInterfaceName, NamingContext context) throws DeploymentException { GBeanData resourceModuleData = locateComponentData(resourceAdapterModuleName, context); return resourceReferenceBuilder.locateAdminObjectInfo(resourceModuleData, adminObjectInterfaceName); } public GBeanData getConnectionFactoryInfo(ObjectName resourceAdapterModuleName, String connectionFactoryInterfaceName, NamingContext context) throws DeploymentException { GBeanData resourceModuleData = locateComponentData(resourceAdapterModuleName, context); return resourceReferenceBuilder.locateConnectionFactoryInfo(resourceModuleData, connectionFactoryInterfaceName); } public String getMEJBName() throws DeploymentException { ObjectName query = null; try { query = ObjectName.getInstance("*:name=ejb/mgmt/MEJB,*"); } catch (MalformedObjectNameException e) { throw new DeploymentException("We built this name..."); } ObjectName mejbName = locateUniqueNameInKernel(query, "Management EJB"); return mejbName.getCanonicalName(); } public ObjectName locateComponentName(String resourceLink, URI moduleURI, String moduleType, String type, J2eeContext j2eeContext, NamingContext context, String queryType) throws UnresolvedReferenceException { GBeanData match = locateComponent(resourceLink, moduleURI, moduleType, type, j2eeContext, context, queryType); return match.getName(); } public GBeanData locateComponent(String resourceLink, URI moduleURI, String moduleType, String type, J2eeContext j2eeContext, NamingContext context, String queryType) throws UnresolvedReferenceException { GBeanData match = locateComponentInApplication(resourceLink, moduleURI, moduleType, type, j2eeContext, queryType, context, true); if (match == null) { //no matches in current context, look in other modules with J2EEApplication=null return locateGBeanInKernel(resourceLink, type, j2eeContext, queryType); } return match; } public GBeanData locateComponentData(ObjectName name, NamingContext context) throws UnresolvedReferenceException { try { return context.getGBeanInstance(name); } catch (GBeanNotFoundException e) { } try { return kernel.getGBeanData(name); } catch (GBeanNotFoundException e) { throw new UnresolvedReferenceException("GBean name: " + name + " not found in DeploymentContext: " + context.getConfigID() + " or in kernel", false, null); } } private GBeanData locateEjbInApplication(NamingContext namingContext, boolean isSession, String ejbLink, URI module) throws UnresolvedReferenceException { GBeanData gbeanData; J2eeContext j2eeContext = namingContext.getJ2eeContext(); if (isSession) { gbeanData = locateComponentInApplication(ejbLink, module, NameFactory.EJB_MODULE, NameFactory.STATELESS_SESSION_BEAN, j2eeContext, "remote ejb", namingContext, false); if (gbeanData == null) { gbeanData = locateComponentInApplication(ejbLink, module, NameFactory.EJB_MODULE, NameFactory.STATEFUL_SESSION_BEAN, j2eeContext, "remote ejb", namingContext, true); } } else { gbeanData = locateComponentInApplication(ejbLink, module, NameFactory.EJB_MODULE, NameFactory.ENTITY_BEAN, j2eeContext, "remote ejb", namingContext, true); } return gbeanData; } private GBeanData locateComponentInApplication(String resourceLink, URI moduleURI, String moduleType, String type, J2eeContext j2eeContext, String queryType, NamingContext context, boolean requireMatchInExplicitModule) throws UnresolvedReferenceException { GBeanData match = locateComponentInModule(resourceLink, moduleURI, moduleType, type, j2eeContext, queryType, context, requireMatchInExplicitModule); if (match == null) { //if we got this far we resourceLink has no #. look in "any module" in this application match = locateGBeanInContext(null, "*", resourceLink, type, j2eeContext, queryType, context, false); } return match; } private GBeanData locateComponentInModule(String resourceLink, URI moduleURI, String moduleType, String type, J2eeContext j2eeContext, String queryType, NamingContext context, boolean requireMatchInExplicitModule) throws UnresolvedReferenceException { GBeanData match; String name = resourceLink.substring(resourceLink.lastIndexOf('#') + 1); String module = moduleURI == null ? "" : moduleURI.getPath(); if (resourceLink.indexOf('#') > -1) { //presence of # means they explicitly want only gbeans in specified module in this application. module = moduleURI.resolve(resourceLink).getPath(); match = locateGBeanInContext(moduleType, module, name, type, j2eeContext, queryType, context, requireMatchInExplicitModule); } else { //no # means look first in current module in this application //module will be emply string if this is a standalone module if (module.equals("")) { module = "*"; } match = locateGBeanInContext(moduleType, module, name, type, j2eeContext, queryType, context, false); } return match; } private GBeanData locateGBeanInContext(String moduleType, String moduleName, String name, String type, J2eeContext j2eeContext, String queryType, NamingContext context, boolean requireMatch) throws UnresolvedReferenceException { ObjectName query = null; //TODO make sure this is reasonable if (moduleType == null) { moduleName = "*"; } try { query = NameFactory.getComponentNameQuery(null, null, null, moduleType, moduleName, name, type, j2eeContext); } catch (MalformedObjectNameException e1) { throw (UnresolvedReferenceException) new UnresolvedReferenceException("Could not construct " + queryType + " object name query", false, null).initCause(e1); } ObjectName match = locateUniqueNameInContext(context, query); if (match == null) { if (!requireMatch) { return null; } else { throw new UnresolvedReferenceException("Could not resolve reference: module: " + moduleName + ", component name: " + name, false, query.toString()); } } try { GBeanData data = context.getGBeanInstance(match); return data; } catch (GBeanNotFoundException e) { throw new IllegalStateException("BUG! context listed a gbean but could not get its gbeanData: " + match + " gbeans in context:" + context.getGBeanNames()); } } private ObjectName locateUniqueNameInContext(NamingContext context, ObjectName query) throws UnresolvedReferenceException { ObjectName match = null; Set matches = context.listGBeans(query); if (matches.size() > 1) { throw new UnresolvedReferenceException("More than one match for query " + matches, true, query.getCanonicalName()); } if (matches.size() == 1) { match = (ObjectName) matches.iterator().next(); } return match; } private GBeanData locateGBeanInKernel(String name, String type, J2eeContext j2eeContext, String queryType) throws UnresolvedReferenceException { ObjectName query; try { query = NameFactory.getComponentRestrictedQueryName(null, null, name, type, j2eeContext); } catch (MalformedObjectNameException e1) { throw (UnresolvedReferenceException) new UnresolvedReferenceException("Could not construct " + queryType + " object name query", false, null).initCause(e1); } return locateUniqueGBeanData(query, queryType); } private ObjectName locateUniqueNameInKernel(ObjectName query, String type) throws UnresolvedReferenceException { Set names = kernel.listGBeans(query); if (names.size() != 1) { throw new UnresolvedReferenceException(type, names.size() > 1, query.getCanonicalName()); } return (ObjectName) names.iterator().next(); } private GBeanData locateUniqueGBeanData(ObjectName query, String type) throws UnresolvedReferenceException { ObjectName match = locateUniqueNameInKernel(query, type); try { return kernel.getGBeanData(match); } catch (GBeanNotFoundException e) { throw new IllegalStateException("BUG! kernel listed a gbean but could not get its gbeanData: " + match); } } public ObjectName locateUniqueName(NamingContext context, ObjectName query) throws UnresolvedReferenceException { ObjectName match = locateUniqueNameInContext(context, query); if (match == null) { match = locateUniqueNameInKernel(query, "type unknown"); } return match; } }