Package org.jboss.ejb3.nointerface.impl.invocationhandler

Source Code of org.jboss.ejb3.nointerface.impl.invocationhandler.NoInterfaceViewInvocationHandler

/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, 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.ejb3.nointerface.impl.invocationhandler;

import org.jboss.ejb3.async.spi.AsyncEndpoint;
import org.jboss.ejb3.endpoint.Endpoint;
import org.jboss.ejb3.nointerface.impl.async.AsyncClientInterceptor;
import org.jboss.ejb3.sis.Interceptor;
import org.jboss.ejb3.sis.InterceptorAssembly;
import org.jboss.ejb3.sis.reflect.InterceptorInvocationHandler;
import org.jboss.kernel.spi.dependency.KernelControllerContext;
import org.jboss.logging.Logger;
import org.jboss.metadata.ejb.spec.AsyncMethodsMetaData;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import static java.lang.reflect.Modifier.isFinal;
import static java.lang.reflect.Modifier.isNative;
import static java.lang.reflect.Modifier.isPublic;
import static java.lang.reflect.Modifier.isStatic;

/**
* NoInterfaceViewInvocationHandler
*
* An {@link InvocationHandler} which corresponds to the
* no-interface view of a EJB container. All calls on the no-interface
* view are routed through this {@link InvocationHandler} to the container.
*
*
* @author Jaikiran Pai
* @version $Revision: $
*/
public class NoInterfaceViewInvocationHandler implements InvocationHandler
{

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

   /**
    * The KernelControllerContext corresponding to the endpoint for which
    * the no-interface view is to be created by this factory. This context
    * may <i>not</i> be in INSTALLED state. This factory is responsible
    * for pushing it to INSTALLED state whenever necessary.
    *
    * All calls to this invocation handler will be forwarded to the container represented
    * by this context
    *
    *
    */
   private KernelControllerContext endpointContext;

   /**
    * The session used to interact with the {@link Endpoint}
    */
   private Serializable session;

   /**
    * The business interface (== bean class, since this is a no-interface view) on
    * which the proxy invocation happens.
    */
   private Class<?> businessInterface;

   private InvocationHandler delegate;
  
   /**
    * Constructor
    */
   public NoInterfaceViewInvocationHandler(KernelControllerContext endpointContext, Serializable session, Class<?> businessInterface,final AsyncMethodsMetaData asyncMethods)
   {
      assert endpointContext != null : "Endpoint context is null for no-interface view invocation handler";
      this.endpointContext = endpointContext;
      this.session = session;
      this.businessInterface = businessInterface;

      InvocationHandler endpointInvocationHandler = new InvocationHandler()
      {
         @Override
         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
         {
            return invokeEndpoint(proxy, method, args);
         }
      };
      final Interceptor asyncInterceptor = new AsyncClientInterceptor((AsyncEndpoint) endpointContext.getTarget(),
            asyncMethods, session);
      Interceptor chain = new InterceptorAssembly(new Interceptor[]
      {new ObjectMethodsInterceptor(this), asyncInterceptor});
      this.delegate = new InterceptorInvocationHandler(endpointInvocationHandler, chain);
   }

   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
   {
      return delegate.invoke(proxy, method, args);
   }

   /**
    * The entry point when a client calls any methods on the no-interface view of a bean,
    * returned through JNDI.
    *
    *
    * @param proxy
    * @param method The invoked method
    * @param args The arguments to the method
    */
   private Object invokeEndpoint(Object proxy, Method method, Object[] args) throws Throwable
   {
      // check to see if this method is expected to be handled
      // by the nointerface view (for ex: only public methods of bean are allowed
      // on nointerface view)
      if (!isHandled(method))
      {
         throw new javax.ejb.EJBException("Cannot invoke method " + method.getName() + " on nointerface view");
      }

      // get the endpoint (which will involve pushing it to INSTALLED state)
      Endpoint endpoint = getInstalledEndpoint();
      assert endpoint != null : "No endpoint associated with context " + this.endpointContext
            + " - cannot invoke the method on bean";

      // finally pass-on the control to the endpoint
      return endpoint.invoke(this.session, this.businessInterface, method, args);
   }

   /**
    * Returns the context corresponding to the container, associated with this invocation handler
    *
    * @return
    */
   public KernelControllerContext getContainerContext()
   {
      return this.endpointContext;
   }

   /**
    * Returns the {@link Endpoint} container corresponding to this
    * {@link NoInterfaceViewInvocationHandler}. Internally, the {@link Endpoint}
    * will be first pushed to the INSTALLED state
    *
    * @return
    */
   public Endpoint getInstalledEndpoint()
   {
      try
      {
         // EJBTHREE-2166 - Changing state through MC API won't work. So for now,
         // we are going to rely on an already INSTALLED endpoint context
//         this.endpointContext.getController().change(this.endpointContext, ControllerState.INSTALLED);
        
         // get hold of the endpoint from its context
         Endpoint endpoint = (Endpoint) this.endpointContext.getTarget();
         return endpoint;
      }
      catch (Throwable t)
      {
         throw new RuntimeException("Error getting endpoint out of container KernelControllerContext "
               + this.endpointContext, t);
      }

   }

   /**
    * Returns the {@link Endpoint} container corresponding to this
    * {@link NoInterfaceViewInvocationHandler}. Note that this method does NOT
    * change the state of the KernelControllerContext of this Endpoint. As such,
    * the Endpoint returned by this method is NOT guaranteed to be in INSTALLED state.
    * If the Endpoint with INSTALLED state is required, then use the {@link #getInstalledEndpoint()}
    * method.
    * 
    * @return
    * @see #getInstalledEndpoint()
    */
   private Endpoint getEndpoint()
   {
      Object endpoint = this.endpointContext.getTarget();
      assert endpoint instanceof Endpoint : "Unexpected type " + endpoint.getClass().getName() + " found in context "
            + this.endpointContext + " Expected " + Endpoint.class.getName();
      return (Endpoint) endpoint;
   }

   /**
    * @see Object#equals(Object)
    */
   @Override
   public boolean equals(Object other)
   {
      // simple object comparison
      if (this == other)
      {
         return true;
      }

      // equals() method contract specifies that if the other object is null
      // then equals() should return false
      if (other == null)
      {
         return false;
      }

      // If the other object is not an instance of MCAwareNoInterfaceViewInvocationHandler
      // then they are not equal
      if (!(other instanceof NoInterfaceViewInvocationHandler))
      {
         return other.equals(this);
      }

      NoInterfaceViewInvocationHandler otherNoInterfaceViewInvocationHandler = (NoInterfaceViewInvocationHandler) other;

      // First check whether the Endpoints of both these InvocationHandlers are equal. If
      // not, then no need for any further comparison, just return false
      if (!(this.getInstalledEndpoint().equals(otherNoInterfaceViewInvocationHandler.getInstalledEndpoint())))
      {
         return false;
      }

      // If the endpoints are equal, then let's next check whether the sessions for
      // these invocation handlers are equal. If not, return false.
      if (!(this.session.equals(otherNoInterfaceViewInvocationHandler.session)))
      {
         return false;
      }
      // All possible, inequality conditions have been tested, so return true.
      return true;
   }

   /**
    * @see Object#hashCode()
    */
   @Override
   public int hashCode()
   {
      int hashCode = this.endpointContext.hashCode();
      if (this.session != null)
      {
         hashCode += this.session.hashCode();
      }
      return hashCode;
   }

   /**
    * @see Object#toString()
    */
   @Override
   public String toString()
   {
      StringBuilder sb = new StringBuilder("No-Interface view for endpoint [ " + endpointContext.getName() + " ]");
      if (this.session != null)
      {
         sb.append(" and session " + this.session);
      }
      return sb.toString();
   }

   /**
    *
    * @param method
    * @return
    */
   public boolean isHandled(Method method)
   {
      int m = method.getModifiers();
      // We handle only public, non-static, non-final methods
      if (!isPublic(m))
      {
         if (logger.isTraceEnabled())
         {
            logger.trace("Method " + method + " is *not* public");
         }
         // it's not a public method
         return false;
      }
      if (isFinal(m))
      {
         if (logger.isTraceEnabled())
         {
            logger.trace("Method " + method + " is final");
         }
         // it's a final method
         return false;
      }
      if (isStatic(m))
      {
         if (logger.isTraceEnabled())
         {
            logger.trace("Method " + method + " is static");
         }
         // it's a static method
         return false;
      }
      if (isNative(m))
      {
         if (logger.isTraceEnabled())
         {
            logger.trace("Method " + method + " is native");
         }
         // it's a native method
         return false;
      }
      // we handle rest of the methods
      return true;
   }
}
TOP

Related Classes of org.jboss.ejb3.nointerface.impl.invocationhandler.NoInterfaceViewInvocationHandler

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.