/* * JBoss, Home of Professional Open Source. * Copyright 2009, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.switchboard.mc.deployer; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.jboss.beans.metadata.api.annotations.Inject; import org.jboss.beans.metadata.plugins.AbstractInjectionValueMetaData; import org.jboss.beans.metadata.plugins.builder.BeanMetaDataBuilderFactory; import org.jboss.beans.metadata.spi.BeanMetaData; import org.jboss.beans.metadata.spi.DemandMetaData; import org.jboss.beans.metadata.spi.DependencyMetaData; import org.jboss.beans.metadata.spi.SupplyMetaData; import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder; import org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer; import org.jboss.deployers.structure.spi.DeploymentUnit; import org.jboss.logging.Logger; import org.jboss.metadata.ejb.jboss.JBossMetaData; import org.jboss.metadata.javaee.spec.Environment; import org.jboss.metadata.web.jboss.JBossWebMetaData; import org.jboss.reloaded.naming.deployers.javaee.JavaEEComponentInformer; import org.jboss.reloaded.naming.spi.JavaEEComponent; import org.jboss.reloaded.naming.spi.JavaEEModule; import org.jboss.switchboard.jbmeta.javaee.environment.BeanManagerReference; import org.jboss.switchboard.jbmeta.javaee.environment.JndiEnvironmentMetadata; import org.jboss.switchboard.jbmeta.javaee.environment.ORBReference; import org.jboss.switchboard.jbmeta.javaee.environment.TransactionSynchronizationRegistryReference; import org.jboss.switchboard.jbmeta.javaee.environment.UserTransactionReference; import org.jboss.switchboard.jbmeta.javaee.environment.ValidatorFactoryReference; import org.jboss.switchboard.jbmeta.javaee.environment.ValidatorReference; import org.jboss.switchboard.mc.JndiEnvironmentProcessor; import org.jboss.switchboard.mc.SwitchBoardImpl; import org.jboss.switchboard.spi.Barrier; import org.jboss.switchboard.spi.EnvironmentEntryType; import org.jboss.switchboard.spi.JndiEnvironment; import org.jboss.switchboard.spi.Resource; import org.jboss.switchboard.spi.ResourceProvider; /** * AbstractENCOperatorDeployer * * @author Jaikiran Pai * @version $Revision: $ */ public abstract class AbstractSwitchBoardDeployer extends AbstractRealDeployer { /** Logger */ private static Logger logger = Logger.getLogger(AbstractSwitchBoardDeployer.class); protected JavaEEComponentInformer informer; protected JndiEnvironmentProcessor jndiEnvProcessor; public AbstractSwitchBoardDeployer(JavaEEComponentInformer informer) { this.informer = informer; //setInputs(informer.getRequiredAttachments()); setOutput(BeanMetaData.class); addOutput(Barrier.class); } @Inject public void setJNDIEnvironmentProcessor(JndiEnvironmentProcessor processor) { this.jndiEnvProcessor = processor; } protected String getApplicationName(DeploymentUnit deploymentUnit) { return informer.getApplicationName(deploymentUnit); } protected String getComponentName(DeploymentUnit deploymentUnit) { return informer.getComponentName(deploymentUnit); } protected String getModuleName(DeploymentUnit deploymentUnit) { return informer.getModuleName(deploymentUnit); } protected void process(DeploymentUnit unit, Collection<Environment> environments) { Map<String, Resource> resources = new HashMap<String, Resource>(); // create resources out of the environments if (environments != null) { for (Environment env : environments) { if (env == null) { continue; } JndiEnvironment jndiEnv = new JndiEnvironmentMetadata(env); this.addJavaComponentEntries(jndiEnv); resources.putAll(this.jndiEnvProcessor.process(unit, jndiEnv)); } } // A SwitchBoard Barrier might already exist for the unit. For example, // for EJBs and servlets deployed in a single .war (component), there will be // a ENCOperator which might have been created and added when processing JBossMetaData (for EJBs) // and now we might be processing JBossWebMetaData (for servlets), which both share the same // (JavaEE)component. Barrier barrier = unit.getAttachment(Barrier.class); if (barrier == null) { // create a new one and attach it to unit SwitchBoardImpl switchBoard = new SwitchBoardImpl(this.getSwitchBoardMCBeanName(unit), resources, unit); this.attachBarrier(unit, switchBoard); BeanMetaData switchBoardBMD = this.createSwitchBoardBMD(unit, switchBoard); this.attachSwitchBoardBMD(unit, switchBoardBMD); } else { // HACK! // TODO: Think about a better way of doing this (maybe making available the methods in Barrier) if (barrier instanceof SwitchBoardImpl) { SwitchBoardImpl switchboard = (SwitchBoardImpl) barrier; switchboard.addENCBinding(resources); // recreate and attach SwitchBoard BMD, since the // new Resource binding might have additional dependencies BeanMetaData switchBoardBMD = this.createSwitchBoardBMD(unit, switchboard); this.attachSwitchBoardBMD(unit, switchBoardBMD); } } } /** * Add additional {@link EnvironmentEntryType environment entries}, to the {@link JndiEnvironment}, * which are expected to be bound in java:comp of the component. * <p> * Typically, these entries that go into java:comp, unlike the entries that go into java:comp/env, * are <i>not</i> driven by deployment descriptors or annotation in the user deployments. For example, * the spec mandates that the following resources be made available in the java:comp of an component: * <ul> * <li>ORB (at java:comp/ORB)</li> * <li>UserTransaction (at java:comp/UserTransaction)</li> * <li>TransactionSynchronizationRegistry (at java:comp/TransactionSynchronizationRegistry)</li> * <li>BeanManager (at java:comp/BeanManager)</li> * <li>Validator (at java:comp/Validator)</li> * <li>ValidatorFactory (at java:comp/ValidatorFactory)</li> * </ul> * This method add these {@link EnvironmentEntryType environment entries} to the {@link JndiEnvironment}, * so that the corresponding {@link ResourceProvider}s can then pick these up and provide the appropriate * {@link Resource}s. * * </p> * @param jndiEnv */ protected void addJavaComponentEntries(JndiEnvironment jndiEnv) { // for java:comp/ORB jndiEnv.addEntry(new ORBReference()); // for java:comp/UserTransaction jndiEnv.addEntry(new UserTransactionReference()); // for java:comp/TransactionSynchronizationRegistry jndiEnv.addEntry(new TransactionSynchronizationRegistryReference()); // for java:comp/BeanManager jndiEnv.addEntry(new BeanManagerReference()); // for java:comp/Validator jndiEnv.addEntry(new ValidatorReference()); // for java:comp/ValidatorFactory jndiEnv.addEntry(new ValidatorFactoryReference()); } protected BeanMetaData createSwitchBoardBMD(DeploymentUnit unit, SwitchBoardImpl switchBoard) { String mcBeanName = switchBoard.getId(); BeanMetaDataBuilder builder = BeanMetaDataBuilderFactory.createBuilder(mcBeanName, switchBoard.getClass().getName()); builder.setConstructorValue(switchBoard); // inject java:global context into switchboard. // the global context is available via the NameSpaces MC bean's "globalContext" property builder.addPropertyMetaData("javaGlobalContext", builder.createInject("NameSpaces", "globalContext")); // inject the appropriate JavaEEComponent or JavaEEModule for the switchboard AbstractInjectionValueMetaData namingContextInjection = this.getNamingContextInjectionMetaData(unit); if (this.informer.isJavaEEComponent(unit) && !this.isSharedENC(unit)) { builder.addPropertyMetaData("javaEEComponent", namingContextInjection); } else { builder.addPropertyMetaData("javaEEModule", namingContextInjection); } // add the dependencies of the Resources, on the switchboard so that // the switchboard will not be installed till those dependencies required by the // ENC binding Resource(s) are satisfied. for (DependencyMetaData bindDependency : switchBoard.getBindDependencies()) { builder.addDependency(bindDependency); } for (DependencyMetaData invocationDependency : switchBoard.getInvocationDependencies()) { builder.addDependency(invocationDependency); } // log the switchboard installation if (logger.isDebugEnabled()) { logger.debug("Installing SwitchBoard: " + mcBeanName + " for unit: " + unit.getSimpleName()); Set<DependencyMetaData> dependencies = builder.getBeanMetaData().getDepends(); if (dependencies != null) { logger.debug("with dependencies:"); for (DependencyMetaData dependency : dependencies) { logger.debug(dependency); } } Set<DemandMetaData> demands = builder.getBeanMetaData().getDemands(); if (demands != null) { logger.debug("demands:"); for (DemandMetaData demand : demands) { logger.debug(demand); } } Set<SupplyMetaData> supplies = builder.getBeanMetaData().getSupplies(); if (supplies != null) { logger.debug("supplies:"); for (SupplyMetaData supply : supplies) { logger.debug(supply); } } } // return the switchboard BMD return builder.getBeanMetaData(); } protected String getSwitchBoardMCBeanName(DeploymentUnit unit) { StringBuilder sb = new StringBuilder("jboss-switchboard:"); String appName = this.getApplicationName(unit); if (appName != null) { sb.append("appName="); sb.append(appName); sb.append(","); } String moduleName = this.getModuleName(unit); sb.append("module="); sb.append(moduleName); if (this.informer.isJavaEEComponent(unit) && !this.isSharedENC(unit)) { String componentName = this.getComponentName(unit); sb.append(",name="); sb.append(componentName); } return sb.toString(); } /** * Returns the MC bean name of either {@link JavaEEComponent} or a {@link JavaEEModule} * depending on the deployment unit * @param deploymentUnit * @return */ protected String getENCContextMCBeanName(DeploymentUnit deploymentUnit) { String applicationName = this.getApplicationName(deploymentUnit); String moduleName = this.getModuleName(deploymentUnit); final StringBuilder builder = new StringBuilder("jboss.naming:"); if (applicationName != null) { builder.append("application=").append(applicationName).append(","); } builder.append("module=").append(moduleName); if (this.informer.isJavaEEComponent(deploymentUnit) && !this.isSharedENC(deploymentUnit)) { String componentName = this.getComponentName(deploymentUnit); builder.append(",component=").append(componentName); } return builder.toString(); } protected boolean isSharedENC(DeploymentUnit deploymentUnit) { JBossMetaData jbossMetaData = deploymentUnit.getAttachment(JBossMetaData.class); JBossWebMetaData jbosswebMetaData = deploymentUnit.getAttachment(JBossWebMetaData.class); if (jbossMetaData != null && jbosswebMetaData != null) { return true; } return false; } protected AbstractInjectionValueMetaData getNamingContextInjectionMetaData(DeploymentUnit deploymentUnit) { String encCtxMCBeanName = this.getENCContextMCBeanName(deploymentUnit); AbstractInjectionValueMetaData namingContextInjectionMetaData = new AbstractInjectionValueMetaData(encCtxMCBeanName); return namingContextInjectionMetaData; } protected abstract void attachSwitchBoardBMD(DeploymentUnit deploymentUnit, BeanMetaData switchBoardBMD); protected abstract void attachBarrier(DeploymentUnit deploymentUnit, Barrier switchBoard); }