Package org.jboss.ejb3.singleton.deployer

Source Code of org.jboss.ejb3.singleton.deployer.SingletonBeanJNDIBinderDeployer

/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt 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.ejb3.singleton.deployer;

import java.lang.reflect.InvocationHandler;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

import org.jboss.aop.AspectManager;
import org.jboss.aop.advice.AdviceStack;
import org.jboss.aop.advice.Interceptor;
import org.jboss.beans.metadata.spi.BeanMetaData;
import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
import org.jboss.dependency.spi.ControllerState;
import org.jboss.deployers.spi.DeploymentException;
import org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployerWithInput;
import org.jboss.deployers.spi.deployer.helpers.DeploymentVisitor;
import org.jboss.deployers.structure.spi.DeploymentUnit;
import org.jboss.ejb3.EJBContainer;
import org.jboss.ejb3.Ejb3Registry;
import org.jboss.ejb3.proxy.impl.remoting.ProxyRemotingUtils;
import org.jboss.ejb3.proxy.reflect.ReflectProxyFactory;
import org.jboss.ejb3.proxy.spi.factory.ProxyFactory;
import org.jboss.ejb3.singleton.deployer.jndi.Binding;
import org.jboss.ejb3.singleton.deployer.jndi.SingletonBeanJndiBinder;
import org.jboss.ejb3.singleton.proxy.impl.invocationhandler.SingletonBeanLocalInvocationHandler;
import org.jboss.ejb3.singleton.proxy.impl.invocationhandler.SingletonBeanRemoteInvocationHandler;
import org.jboss.logging.Logger;
import org.jboss.metadata.ejb.jboss.JBossEnterpriseBeanMetaData;
import org.jboss.metadata.ejb.jboss.JBossSessionBean31MetaData;
import org.jboss.metadata.ejb.jboss.JBossSessionBeanMetaData;
import org.jboss.metadata.ejb.jboss.LocalBindingMetaData;
import org.jboss.metadata.ejb.jboss.RemoteBindingMetaData;
import org.jboss.metadata.ejb.jboss.jndi.resolver.impl.JNDIPolicyBasedJNDINameResolverFactory;
import org.jboss.metadata.ejb.jboss.jndi.resolver.spi.SessionBeanJNDINameResolver;
import org.jboss.metadata.ejb.jboss.jndipolicy.plugins.DefaultJNDIBindingPolicyFactory;
import org.jboss.metadata.ejb.jboss.jndipolicy.spi.DefaultJndiBindingPolicy;
import org.jboss.metadata.ejb.spec.BusinessLocalsMetaData;
import org.jboss.metadata.ejb.spec.BusinessRemotesMetaData;

/**
* Deployer which is responsible for deploying (multiple) MC based
* JNDI binders for a singleton bean
*
* @author Jaikiran Pai
* @version $Revision: $
*/
public class SingletonBeanJNDIBinderDeployer extends AbstractRealDeployerWithInput<EJBContainer>
      implements
         DeploymentVisitor<EJBContainer>
{

   /**
    * Client side AOP interceptors for the remote business interface(s) of the singleton bean
    */
   private final static String REMOTE_CLIENT_INTERCEPTOR_STACK_NAME = "SingletonSessionClientInterceptors";
  
   /**
    * Client side AOP interceptors for the local business interface(s) of the singleton bean
    */
   private static final String LOCAL_CLIENT_INTERCEPTOR_STACK_NAME = "LocalClientInterceptors";

   /**
    * Logger
    */
   private static Logger logger = Logger.getLogger(SingletonBeanJNDIBinderDeployer.class);
  

   /**
    *
    */
   public SingletonBeanJNDIBinderDeployer()
   {
      this.setDeploymentVisitor(this);
      this.setAllInputs(true);
      this.setInput(EJBContainer.class);
      this.setComponentsOnly(true);

      // we output the jndi binders as a MC bean
      addOutput(BeanMetaData.class);
   }

   /**
    * @see org.jboss.deployers.spi.deployer.helpers.DeploymentVisitor#deploy(org.jboss.deployers.structure.spi.DeploymentUnit, java.lang.Object)
    */
   @Override
   public void deploy(DeploymentUnit unit, EJBContainer container) throws DeploymentException
   {
      JBossEnterpriseBeanMetaData enterpriseBean = container.getXml();
      if (!enterpriseBean.isSession())
      {
         return;
      }
      JBossSessionBeanMetaData sessionBean = (JBossSessionBeanMetaData) enterpriseBean;
      if (sessionBean instanceof JBossSessionBean31MetaData == false)
      {
         return;
      }
      JBossSessionBean31MetaData sessionBean31 = (JBossSessionBean31MetaData) sessionBean;
      if (!sessionBean31.isSingleton())
      {
         return;
      }
      process(unit, sessionBean31, container);

   }

   /**
    * @see org.jboss.deployers.spi.deployer.helpers.DeploymentVisitor#getVisitorType()
    */
   @Override
   public Class<EJBContainer> getVisitorType()
   {
      return EJBContainer.class;
   }

   /**
    * {@inheritDoc}
    */
   @Override
   public void undeploy(DeploymentUnit unit, EJBContainer deployment)
   {
      // TODO Auto-generated method stub

   }

   /**
    * Process the container and create appropriate JNDI binders for binding
    * the remote and local proxies of a singleton bean
    *
    * @param unit The deployment unit being processed
    * @param sessionBean The bean metadata
    * @param container The container being processed
    */
   private void process(DeploymentUnit unit, JBossSessionBean31MetaData sessionBean, EJBContainer container)
   {

      List<Binding> bindings = new ArrayList<Binding>();
      // process remote business interfaces
      bindings.addAll(processRemoteBusinessInterfaces(unit, sessionBean, container));
      // process local business interfaces
      bindings.addAll(processLocalBusinessInterfaces(unit, sessionBean, container));
     
      Context initCtx;
      try
      {
         initCtx = new InitialContext();
      }
      catch (NamingException ne)
      {
         throw new RuntimeException(ne);
      }
     
      SingletonBeanJndiBinder jndiBinder = new SingletonBeanJndiBinder(initCtx, bindings);
      // attach the jndi binder as BMD to the unit
      this.createAndAttachJNDIBinerBeanMetaData(unit, jndiBinder, container);

      // just print out the bindings
      StringBuilder sb = new StringBuilder("Binding the following entries in JNDI for singleton bean: ");
      sb.append(container.getEjbName());
      sb.append("\n\n");
      for (Binding binding :bindings)
      {
         sb.append(binding);
         sb.append("\n");
      }
      log.info(sb.toString());
   }

   /**
    * Responsible for creating jndi binders for each of the remote business interface views
    * of a singleton bean
    *
    * @param unit The deployment unit being processed
    * @param sessionBean The bean metadata
    * @param container The container being processed
    */
   private Collection<Binding> processRemoteBusinessInterfaces(DeploymentUnit unit, JBossSessionBean31MetaData sessionBean,
         EJBContainer container)
   {
      BusinessRemotesMetaData businessRemotes = sessionBean.getBusinessRemotes();
      if (businessRemotes == null || businessRemotes.size() == 0)
      {
         return Collections.emptySet();
      }
      Set<Binding> bindings = new HashSet<Binding>();
     
      String defaultInvokerLocatorURL = ProxyRemotingUtils.getDefaultClientBinding();

      DefaultJndiBindingPolicy jndibindingPolicy = DefaultJNDIBindingPolicyFactory.getDefaultJNDIBindingPolicy();
      SessionBeanJNDINameResolver jndiNameResolver = JNDIPolicyBasedJNDINameResolverFactory.getJNDINameResolver(
            sessionBean, jndibindingPolicy);

      String containerRegistryKey = container.getObjectName().getCanonicalName();
      String containerGUID = Ejb3Registry.guid(container);

      ProxyFactory proxyFactory = new ReflectProxyFactory();
      Interceptor[] clientInterceptors = this.getRemoteClientInterceptors(container);

      Set<Class<?>> allRemoteinterfaces = new HashSet<Class<?>>();
      for (String businessRemote : businessRemotes)
      {
         try
         {
            Class<?> businessRemoteIntf = unit.getClassLoader().loadClass(businessRemote);
            allRemoteinterfaces.add(businessRemoteIntf);

            InvocationHandler invocationHandler = new SingletonBeanRemoteInvocationHandler(containerRegistryKey, containerGUID,
                  defaultInvokerLocatorURL, clientInterceptors, businessRemote);

            // time to create a proxy
            Object proxy = proxyFactory.createProxy(new Class<?>[]
            {businessRemoteIntf}, invocationHandler);

            // bind to jndi

            String jndiName = jndiNameResolver.resolveJNDIName(sessionBean, businessRemote);

            Binding binding = new Binding(jndiName, proxy, "EJB3.x Remote Business Interface");
            bindings.add(binding);

         }
         catch (ClassNotFoundException cnfe)
         {
            throw new RuntimeException("Could not load business remote interface " + businessRemote, cnfe);
         }

      }

      // time to create a proxy
      List<RemoteBindingMetaData> remoteBindings = sessionBean.getRemoteBindings();
      if (remoteBindings == null || remoteBindings.isEmpty())
      {

         InvocationHandler invocationHandler = new SingletonBeanRemoteInvocationHandler(containerRegistryKey, containerGUID,
               defaultInvokerLocatorURL, clientInterceptors);
         String defaultRemoteJNDIName = jndiNameResolver.resolveRemoteBusinessDefaultJNDIName(sessionBean);
         Object proxy = proxyFactory.createProxy(allRemoteinterfaces.toArray(new Class<?>[allRemoteinterfaces.size()]),
               invocationHandler);
         Binding binding = new Binding(defaultRemoteJNDIName, proxy, "EJB3.x Default Remote Business Interface");
         bindings.add(binding);

      }
      else
      {
         for (RemoteBindingMetaData remoteBinding : remoteBindings)
         {
            String jndiName = remoteBinding.getJndiName();
            // if not explicitly specified, then use the default jndi name
            if (jndiName == null)
            {
               jndiName = jndiNameResolver.resolveRemoteBusinessDefaultJNDIName(sessionBean);
            }
            String invokerLocatorURL = getClientBindURL(remoteBinding);
            InvocationHandler invocationHandler = new SingletonBeanRemoteInvocationHandler(containerRegistryKey, containerGUID,
                  invokerLocatorURL, clientInterceptors);
            Object proxy = proxyFactory.createProxy(allRemoteinterfaces
                  .toArray(new Class<?>[allRemoteinterfaces.size()]), invocationHandler);
            Binding binding = new Binding(jndiName, proxy, "EJB3.x Default Remote Business Interface");
            bindings.add(binding);
         }

      }
      return bindings;
   }

   /**
    * Responsible for creating jndi binders for each of the local business interface views
    * of a singleton bean
    *
    * @param unit The deployment unit being processed
    * @param sessionBean The bean metadata
    * @param container The container being processed
    */
   private Collection<Binding> processLocalBusinessInterfaces(DeploymentUnit unit, JBossSessionBean31MetaData sessionBean,
         EJBContainer container)
   {
      BusinessLocalsMetaData businessLocals = sessionBean.getBusinessLocals();
      if (businessLocals == null || businessLocals.size() == 0)
      {
         return Collections.emptySet();
      }
     
      Set<Binding> bindings = new HashSet<Binding>();
     
      DefaultJndiBindingPolicy jndibindingPolicy = DefaultJNDIBindingPolicyFactory.getDefaultJNDIBindingPolicy();
      SessionBeanJNDINameResolver jndiNameResolver = JNDIPolicyBasedJNDINameResolverFactory.getJNDINameResolver(
            sessionBean, jndibindingPolicy);

      // TODO: Rethink
      String containerRegistryKey = container.getObjectName().getCanonicalName();
      String containerGUID = Ejb3Registry.guid(container);

      ProxyFactory proxyFactory = new ReflectProxyFactory();

      Set<Class<?>> allLocalinterfaces = new HashSet<Class<?>>();
      // get the client side AOP interceptor(s) for local business interface of the singleton bean
      Interceptor[] clientInterceptors = this.getLocalClientInterceptors(container);

      for (String businessLocal : businessLocals)
      {
         Class<?> businessLocalIntf = null;
         try
         {
            businessLocalIntf = unit.getClassLoader().loadClass(businessLocal);
         }
         catch (ClassNotFoundException cnfe)
         {
            throw new RuntimeException("Could not load business local interface " + businessLocal, cnfe);
         }
         allLocalinterfaces.add(businessLocalIntf);

         InvocationHandler invocationHandler = new SingletonBeanLocalInvocationHandler(containerRegistryKey,
               containerGUID, businessLocal, clientInterceptors);

         // time to create a proxy
         Object proxy = proxyFactory.createProxy(new Class<?>[]
         {businessLocalIntf}, invocationHandler);

         // bind to jndi

         String jndiName = jndiNameResolver.resolveJNDIName(sessionBean, businessLocal);

         Binding binding = new Binding(jndiName, proxy, "EJB3.x Local Business Interface");
         bindings.add(binding);

      }

      List<LocalBindingMetaData> localBindings = sessionBean.getLocalBindings();
      if (localBindings == null || localBindings.isEmpty())
      {
         InvocationHandler invocationHandler = new SingletonBeanLocalInvocationHandler(containerRegistryKey, containerGUID, clientInterceptors);
         String defaultBusinessLocalJNDIName = jndiNameResolver.resolveLocalBusinessDefaultJNDIName(sessionBean);
         Object proxy = proxyFactory.createProxy(allLocalinterfaces.toArray(new Class<?>[allLocalinterfaces.size()]),
               invocationHandler);
         Binding binding = new Binding(defaultBusinessLocalJNDIName, proxy, "EJB3.x Default Local Business Interface");
         bindings.add(binding);
      }
      else
      {
         for (LocalBindingMetaData localBinding : localBindings)
         {
            String jndiName = localBinding.getJndiName();
            // if not explicitly specified, then use the default jndi name
            if (jndiName == null)
            {
               jndiName = jndiNameResolver.resolveLocalBusinessDefaultJNDIName(sessionBean);
            }
            InvocationHandler invocationHandler = new SingletonBeanLocalInvocationHandler(containerRegistryKey, containerGUID, clientInterceptors);
            Object proxy = proxyFactory.createProxy(
                  allLocalinterfaces.toArray(new Class<?>[allLocalinterfaces.size()]), invocationHandler);
            Binding binding = new Binding(jndiName, proxy, "EJB3.x Default Local Business Interface");
            bindings.add(binding);

         }

      }
      return bindings;
   }

   /**
    * Returns the appropriate client bind url from a {@link RemoteBindingMetaData}
    * @param remoteBinding
    * @return
    */
   private String getClientBindURL(RemoteBindingMetaData remoteBinding)
   {

      // RemoteBinding allows for specifying the invoker (MC bean) name through
      // which the invoker locator url can be obtained. check if it's explicitly
      // specified
      String invokerName = remoteBinding.getInvokerName();
      String generatedClientBindURL = null;
      if (invokerName != null && invokerName.trim().isEmpty() == false)
      {
         invokerName = invokerName.trim();
         generatedClientBindURL = ProxyRemotingUtils.getClientBinding(invokerName);
      }
      // RemoteBinding also allows for specifying clientBindURL explicitly
      // Check if it's specified. Obviously, specifying both client bind url
      // and the invokername is wrong. So let's print out a WARN and use the
      // client bind url generated through invokerName (that way, the client
      // bind url can be overridden through xml).
      String explicitClientBindURL = remoteBinding.getClientBindUrl();
      if (explicitClientBindURL != null && explicitClientBindURL.trim().isEmpty())
      {
         explicitClientBindURL = null;
      }
      if (explicitClientBindURL != null && generatedClientBindURL != null)
      {
         logger
               .warn("Both invokerName and clientBindURL specified on RemoteBinding. Ignoring the explicitly specified bind url "
                     + explicitClientBindURL + " and instead using " + generatedClientBindURL);
      }
      String bindURL = generatedClientBindURL == null ? explicitClientBindURL : generatedClientBindURL;
      return bindURL == null ? ProxyRemotingUtils.getDefaultClientBinding() : bindURL;
   }

   /**
    * Returns the client side interceptors for the remote business interface of the bean
    * represented by the <code>container</code>
    *
    * @param container The {@link EJBContainer}
    * @return
    */
   private Interceptor[] getRemoteClientInterceptors(EJBContainer container)
   {
      // Obtain interceptors by stack name via Aspect Manager
      AspectManager manager = AspectManager.instance();
      AdviceStack stack = manager.getAdviceStack(REMOTE_CLIENT_INTERCEPTOR_STACK_NAME);

      if (stack == null)
      {
         throw new RuntimeException("Could not find Advice Stack with name: " + REMOTE_CLIENT_INTERCEPTOR_STACK_NAME);
      }
      Interceptor[] interceptors = stack.createInterceptors(container.getAdvisor(), null);
      return interceptors;
   }
  
  
   /**
    * Returns the client side interceptors for the local business interface of the bean
    * represented by the <code>container</code>
    *
    * @param container The {@link EJBContainer}
    * @return
    */
   private Interceptor[] getLocalClientInterceptors(EJBContainer container)
   {
      // Obtain interceptors by stack name via Aspect Manager
      AspectManager manager = AspectManager.instance();
      AdviceStack stack = manager.getAdviceStack(LOCAL_CLIENT_INTERCEPTOR_STACK_NAME);

      if (stack == null)
      {
         throw new RuntimeException("Could not find Advice Stack with name: " + LOCAL_CLIENT_INTERCEPTOR_STACK_NAME);
      }
      Interceptor[] interceptors = stack.createInterceptors(container.getAdvisor(), null);
      return interceptors;
   }


   private void createAndAttachJNDIBinerBeanMetaData(DeploymentUnit unit, SingletonBeanJndiBinder jndiBinder, EJBContainer container)
   {
      String containerName = container.getXml().getContainerName();
      String binderName = containerName + ",type=singleton-bean-jndi-binder";
     
      BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(binderName, jndiBinder.getClass().getName());
      builder.setConstructorValue(jndiBinder);

      // the proxies/invocation handlers for singleton do NOT push the container
      // states. So let's just depend on a START state container, so that when the
      // jndi binder binds the proxies, they will be ready to use (i.e. will be sure that
      // the container is available for invocation).
      builder.addDemand(containerName, ControllerState.START, ControllerState.START, null);
      for (Binding binding : jndiBinder.getBindings())
      {
         builder.addSupply("jndi:" + binding.getJndiName());
      }
      if (unit.isComponent())
      {
         // Attach it to parent since we are processing a component DU and BeanMetaDataDeployer doesn't
         // pick up BeanMetaData from component DU
         unit.getParent().addAttachment(BeanMetaData.class + ":" + binderName, builder.getBeanMetaData());
      }
      else
      {
         unit.addAttachment(BeanMetaData.class + ":" + binderName, builder.getBeanMetaData());
      }
   }
}
TOP

Related Classes of org.jboss.ejb3.singleton.deployer.SingletonBeanJNDIBinderDeployer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.