Package org.jboss.jms.client.remoting

Source Code of org.jboss.jms.client.remoting.ConsolidatedRemotingConnectionListener

/**
* JBoss, Home of Professional Open Source
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.jms.client.remoting;

import javax.jms.ExceptionListener;
import javax.jms.JMSException;

import org.jboss.jms.client.container.ConnectionFailureListener;
import org.jboss.jms.client.state.ConnectionState;
import org.jboss.logging.Logger;
import org.jboss.remoting.Client;
import org.jboss.remoting.ConnectionListener;

/**
* The ONLY remoting connection listener for a JMS connection's underlying remoting connection.
* Added to the remoting connection when the JMS connection is created, and removed when the
* JMS connection is closed. Any second tier listeners (the JMS connection ExceptionListener,
* and the HA's connection failure detector) are registered with this consolidated listener and not
* with the remoting connection directly.
*
* @author <a href="mailto:ovidiu@feodorov.com">Ovidiu Feodorov</a>
* @version <tt>$Revision: 8498 $</tt>
*
* $Id: ConsolidatedRemotingConnectionListener.java 8498 2012-02-09 10:51:07Z gaohoward $
*/
public class ConsolidatedRemotingConnectionListener implements ConnectionListener
{
   // Constants ------------------------------------------------------------------------------------

   private static final Logger log = Logger.getLogger(ConsolidatedRemotingConnectionListener.class);

   // Static ---------------------------------------------------------------------------------------

   // Attributes -----------------------------------------------------------------------------------

   private ConnectionState state;

   private ExceptionListener jmsExceptionListener;

   private ConnectionFailureListener remotingListener;
     
   private boolean started;

   private JMSException jmsException;

   private Object jmsExceptionLock = new Object();

   private Object exceptionLock = new Object();
  
   private boolean beingHandled = false;

   // Constructors ---------------------------------------------------------------------------------

   public ConsolidatedRemotingConnectionListener()
   {
   }

   // ConnectionListener implementation ------------------------------------------------------------

   //for simplicity, we changed from partial synchronization to full synchronization. This
   //method is not supposed to have high concurrent access.
   public synchronized void handleConnectionException(Throwable throwable, Client client)
   {
      if (!started)
      {
         return;
      }
     
      //if the connection is already closed then there is no point handling it again.
      if (!setBeingHandled())
      {
         return;
      }
           
      // forward the exception to delegate listener and JMS ExceptionListeners;
      boolean forwardToJMSListener = true;
     
      //save a copy. This is because if the failover failed the listener will be cleaned up.
      ExceptionListener jmsListenerCopy = jmsExceptionListener;

      if (remotingListener != null)
      {
         try
         {
            log.trace(this + " forwarding remoting failure \"" + throwable + "\" to " + remotingListener);
           
            //We only forward to the JMS listener if failover did not successfully handle the exception
            //If failover handled the exception transparently then there is effectively no problem
            //with the logical connection that the client needs to be aware of
            forwardToJMSListener = !remotingListener.handleConnectionException(throwable, client);
         }
         catch(Exception e)
         {
            log.warn("Failed to forward " + throwable + " to " + remotingListener, e);
         }
      }
     
      if (forwardToJMSListener)
      {
         // if a listener already set, notify it instantly and forget the exception.
         synchronized (jmsExceptionLock)
         {
            // the connection is broken, we need to remember this
            if (throwable instanceof Error)
            {
               final String msg = "Caught Error on underlying remoting connection";
               log.error(this + ": " + msg, throwable);
               jmsException = new JMSException(msg + ": " + throwable.getMessage());
            }
            else if (throwable instanceof Exception)
            {
               Exception e = (Exception)throwable;
               jmsException = new JMSException("Failure on underlying remoting connection");
               jmsException.setLinkedException(e);
            }
            else
            {
               // Some other Throwable subclass
               final String msg = "Caught Throwable on underlying remoting connection";
               log.error(this + ": " + msg, throwable);
               jmsException = new JMSException(msg + ": " + throwable.getMessage());
            }
           
            if (jmsListenerCopy != null)
            {
               jmsListenerCopy.onException(jmsException);
               jmsException = null;
            }
         }
      }
   }

   // Public ---------------------------------------------------------------------------------------

   public synchronized void setDelegateListener(ConnectionFailureListener l)
   {
      log.trace(this + " setting delegate listener " + l);
     
      if (remotingListener != null)
      {
         throw new IllegalStateException("There is already a connection listener for the connection");
      }
     
      remotingListener = l;
   }

   public synchronized void addJMSExceptionListener(ExceptionListener listener)
   {
      log.trace(this + " adding JMS exception listener " + listener + " current exception: " + jmsException);

      synchronized (jmsExceptionLock)
      {
         this.jmsExceptionListener = listener;
     
         // if a connection failure event already happened, we notify it.
         // https://jira.jboss.org/jira/browse/JBMESSAGING-1776
         if (jmsException != null)
         {
            final JMSException copy = jmsException;
            jmsException = null;
            notifyJMSExceptionListener(listener, copy);
         }
      }
   }
  
   //Called when the listener is added after the connection exception.
   private void notifyJMSExceptionListener(final ExceptionListener l, final JMSException ex)
   {
      new Thread()
      {
         public void run()
         {
            l.onException(ex);
         }
      }.start();
   }

   public ExceptionListener getJMSExceptionListener()
   {
      synchronized (jmsExceptionLock)
      {
         return jmsExceptionListener;
      }
   }

   /**
    * Clears all delegate listeners
    */
   public synchronized void clear()
   {
      clearJmsExceptionListener();
      remotingListener = null;
      log.trace(this + " cleared");
   }
  
   //https://issues.jboss.org/browse/JBMESSAGING-1912
   public boolean setBeingHandled()
   {
      synchronized (exceptionLock)
      {
         if (beingHandled)
         {
            return false;
         }
         beingHandled = true;
         return true;
      }
   }

   private void clearJmsExceptionListener()
   {
      synchronized (jmsExceptionLock)
      {
         jmsExceptionListener = null;
      }
   }

   public void setConnectionState(ConnectionState state)
   {
      this.state = state;
   }

   public String toString()
   {
      if (state == null)
      {
         return "ConsolidatedListener(UNINITIALIZED)";
      }
      return state + ".ConsolidatedListener";
   }
     
   public void start()
   {
      started = true;
   }

   // Package protected ----------------------------------------------------------------------------

   // Protected ------------------------------------------------------------------------------------

   // Private --------------------------------------------------------------------------------------

   // Inner classes --------------------------------------------------------------------------------

}
TOP

Related Classes of org.jboss.jms.client.remoting.ConsolidatedRemotingConnectionListener

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.