Save This Page
Home » jboss-5.0.0.CR1-src » org.jboss.invocation.jrmp » server » [javadoc | source]
    1   /*
    2    * JBoss, Home of Professional Open Source
    3    * Copyright 2005, JBoss Inc., and individual contributors as indicated
    4    * by the @authors tag. See the copyright.txt in the distribution for a
    5    * full listing of individual contributors.
    6    *
    7    * This is free software; you can redistribute it and/or modify it
    8    * under the terms of the GNU Lesser General Public License as
    9    * published by the Free Software Foundation; either version 2.1 of
   10    * the License, or (at your option) any later version.
   11    *
   12    * This software is distributed in the hope that it will be useful,
   13    * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   15    * Lesser General Public License for more details.
   16    *
   17    * You should have received a copy of the GNU Lesser General Public
   18    * License along with this software; if not, write to the Free
   19    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
   20    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
   21    */
   22   package org.jboss.invocation.jrmp.server;
   23   
   24   import java.rmi.MarshalledObject;
   25   
   26   import javax.management.MBeanServer;
   27   import javax.management.ObjectName;
   28   import javax.management.InstanceNotFoundException;
   29   import javax.management.ReflectionException;
   30   
   31   import org.jboss.invocation.jrmp.interfaces.JRMPInvokerProxyHA;
   32   import org.jboss.invocation.Invocation;
   33   import org.jboss.invocation.Invoker;
   34   import org.jboss.invocation.InvokerHA;
   35   import org.jboss.invocation.MarshalledInvocation;
   36   import org.jboss.system.Registry;
   37   
   38   import org.jboss.ha.framework.interfaces.HARMIResponse;
   39   import org.jboss.ha.framework.server.HATarget;
   40   import org.jboss.ha.framework.interfaces.LoadBalancePolicy;
   41   import org.jboss.ha.framework.interfaces.GenericClusteringException;
   42   
   43   import java.util.ArrayList;
   44   import java.util.HashMap;
   45   
   46   
   47   /**
   48    * The JRMPInvokerHA is an HA-RMI implementation that can generate Invocations from RMI/JRMP 
   49    * into the JMX base
   50    *
   51    * @author <a href="mailto:bill@burkecentral.com>Bill Burke</a>
   52    * @author  <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>.
   53    * @author Scott.Stark@jboss.org
   54    * @author <a href="mailto:galder.zamarreno@jboss.com">Galder Zamarreno</a>
   55    * @version $Revision: 69191 $
   56    */
   57   public class JRMPInvokerHA
   58      extends JRMPInvoker
   59      implements InvokerHA
   60   {
   61      /** @since v4.2.3 */
   62      private static final long serialVersionUID = -7657305823982668529L;
   63   
   64      protected HashMap beanMap = new HashMap();
   65      
   66      protected ObjectName serviceName;
   67      
   68      /**
   69       * Explicit no-args constructor.
   70       */
   71      public JRMPInvokerHA()
   72      {
   73         super();
   74      }
   75   
   76      // JRMPInvoker.createService() does the right thing
   77      
   78      protected void startService() throws Exception
   79      {
   80         loadCustomSocketFactories();
   81   
   82         if (log.isDebugEnabled())
   83         {
   84            log.debug("RMI Port='" +  (rmiPort == ANONYMOUS_PORT ?
   85               "Anonymous" : Integer.toString(rmiPort)+"'"));
   86            log.debug("Client SocketFactory='" + (clientSocketFactory == null ?
   87               "Default" : clientSocketFactory.toString()+"'"));
   88            log.debug("Server SocketFactory='" + (serverSocketFactory == null ?
   89               "Default" : serverSocketFactory.toString()+"'"));
   90            log.debug("Server SocketAddr='" + (serverAddress == null ?
   91               "Default" : serverAddress+"'"));
   92            log.debug("SecurityDomain='" + (sslDomain == null ?
   93               "None" : sslDomain+"'"));
   94         }
   95   
   96         exportCI();
   97         Registry.bind(getServiceName(), this);
   98      }
   99   
  100      protected void stopService() throws Exception
  101      {
  102         unexportCI();
  103      }
  104   
  105      // JRMPInvoker.destroyService() does the right thing
  106   
  107      public void registerBean(ObjectName beanName, HATarget target) throws Exception
  108      {
  109         Integer hash = new Integer(beanName.hashCode());
  110         log.debug("registerBean: "+beanName);
  111         
  112         if (beanMap.containsKey(hash))
  113         {
  114            // FIXME [oleg] In theory this is possible!
  115            log.debug("Trying to register target " + target + " using an existing hashCode. Already registered: " + hash + "=" + beanMap.get(hash));
  116            throw new IllegalStateException("Trying to register target using an existing hashCode.");
  117         }
  118         beanMap.put(hash, target);
  119      }
  120      
  121      public Invoker createProxy(ObjectName beanName, LoadBalancePolicy policy,
  122         String proxyFamilyName) throws Exception
  123      {
  124         Integer hash = new Integer(beanName.hashCode());
  125         HATarget target = (HATarget) beanMap.get(hash);
  126         if (target == null)
  127         {
  128            throw new IllegalStateException("The bean hashCode not found");
  129         }
  130   
  131         String familyName = proxyFamilyName;
  132         if (familyName == null)
  133            familyName= target.getAssociatedPartition().getPartitionName() + "/" + beanName;
  134   
  135         return createProxy(target.getReplicants(), policy, familyName, target.getCurrentViewId ());
  136      }
  137   
  138      public void unregisterBean(ObjectName beanName) throws Exception
  139      {
  140         Integer hash = new Integer(beanName.hashCode());
  141         beanMap.remove(hash);
  142      }
  143   
  144      /**
  145       * Invoke a Remote interface method.
  146       */
  147      public Object invoke(Invocation invocation)
  148         throws Exception
  149      {
  150         ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
  151   
  152         try
  153         {
  154            // Deserialize the transaction if it is there
  155            invocation.setTransaction(importTPC(((MarshalledInvocation) invocation).getTransactionPropagationContext()));
  156   
  157            // Extract the ObjectName, the rest is still marshalled
  158            ObjectName mbean = (ObjectName) Registry.lookup(invocation.getObjectName());
  159            long clientViewId = ((Long)invocation.getValue("CLUSTER_VIEW_ID")).longValue();
  160   
  161            HATarget target = (HATarget)beanMap.get(invocation.getObjectName());
  162            if (target == null) 
  163            {
  164               // We could throw IllegalStateException but we have a race condition that could occur:
  165               // when we undeploy a bean, the cluster takes some time to converge
  166               // and to recalculate a new viewId and list of replicant for each HATarget.
  167               // Consequently, a client could own an up-to-date list of the replicants
  168               // (before the cluster has converged) and try to perform an invocation
  169               // on this node where the HATarget no more exist, thus receiving a
  170               // wrong exception and no failover is performed with an IllegalStateException
  171               //
  172               throw new GenericClusteringException(GenericClusteringException.COMPLETED_NO, 
  173                                                    "target is not/no more registered on this node");            
  174            }
  175            
  176            if (!target.invocationsAllowed ())
  177               throw new GenericClusteringException(GenericClusteringException.COMPLETED_NO, 
  178                                           "invocations are currently not allowed on this target");            
  179   
  180            // The cl on the thread should be set in another interceptor
  181            Object rtn = support.getServer().invoke(mbean,
  182                                                    "invoke",
  183                                                    new Object[] { invocation },
  184                                                    Invocation.INVOKE_SIGNATURE);
  185            
  186            HARMIResponse rsp = new HARMIResponse();
  187   
  188            if (clientViewId != target.getCurrentViewId())
  189            {
  190               rsp.newReplicants = new ArrayList(target.getReplicants());
  191               rsp.currentViewId = target.getCurrentViewId();
  192            }
  193            rsp.response = rtn;
  194            
  195            return new MarshalledObject(rsp);
  196         }
  197         catch (InstanceNotFoundException e)
  198         {
  199            throw new GenericClusteringException(GenericClusteringException.COMPLETED_NO, e);
  200         }
  201         catch (ReflectionException e)
  202         {
  203            throw new GenericClusteringException(GenericClusteringException.COMPLETED_NO, e);
  204         }
  205         catch (Exception e)
  206         {
  207            org.jboss.mx.util.JMXExceptionDecoder.rethrow(e);
  208   
  209            // the compiler does not know an exception is thrown by the above
  210            throw new org.jboss.util.UnreachableStatementException();
  211         }
  212         finally
  213         {
  214            Thread.currentThread().setContextClassLoader(oldCl);
  215         }      
  216      }
  217      
  218      public ObjectName getServiceName()
  219      {
  220         return (serviceName == null ? support.getServiceName() : serviceName);
  221      }
  222      
  223      public void setServiceName(ObjectName serviceName)
  224      {
  225         this.serviceName = serviceName;
  226      }
  227   
  228      @Override
  229      public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception
  230      {
  231         ObjectName result = super.preRegister(server, name);
  232         
  233         if (!result.equals(getServiceName()))
  234            throw new IllegalStateException("JMX registration (" + result + 
  235                  ") differs from our configured service name (" + 
  236                  getServiceName() +")");
  237         
  238         return result;
  239      }
  240      
  241      protected Invoker createProxy(ArrayList targets, LoadBalancePolicy policy,
  242            String proxyFamilyName, long viewId)
  243      {
  244         return new JRMPInvokerProxyHA(targets, policy, proxyFamilyName, viewId);
  245      }   
  246      
  247      
  248      
  249   }
  250   

Save This Page
Home » jboss-5.0.0.CR1-src » org.jboss.invocation.jrmp » server » [javadoc | source]