Package org.hornetq.jms.client

Source Code of org.hornetq.jms.client.HornetQConnection$JMSFailureListener

/*
* Copyright 2009 Red Hat, Inc.
* Red Hat licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*    http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.  See the License for the specific language governing
* permissions and limitations under the License.
*/

package org.hornetq.jms.client;

import java.lang.ref.WeakReference;
import java.util.HashSet;
import java.util.Set;

import javax.jms.Connection;
import javax.jms.ConnectionConsumer;
import javax.jms.ConnectionMetaData;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.IllegalStateException;
import javax.jms.JMSException;
import javax.jms.Queue;
import javax.jms.QueueConnection;
import javax.jms.QueueSession;
import javax.jms.ServerSessionPool;
import javax.jms.Session;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicSession;
import javax.jms.XAQueueSession;
import javax.jms.XASession;
import javax.jms.XATopicSession;

import org.hornetq.api.core.HornetQException;
import org.hornetq.api.core.SimpleString;
import org.hornetq.api.core.client.ClientSession;
import org.hornetq.api.core.client.ClientSessionFactory;
import org.hornetq.api.core.client.SessionFailureListener;
import org.hornetq.api.jms.HornetQJMSConstants;
import org.hornetq.core.logging.Logger;
import org.hornetq.core.version.Version;
import org.hornetq.utils.UUIDGenerator;
import org.hornetq.utils.VersionLoader;

/**
* HornetQ implementation of a JMS Connection.
*
* @author <a href="mailto:ovidiu@feodorov.com">Ovidiu Feodorov</a>
* @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a>
* @author <a href="mailto:ataylor@redhat.com">Andy Taylor</a>
* @version <tt>$Revision: 11379 $</tt>
*          <p/>
*          $Id: HornetQConnection.java 11379 2011-09-20 23:57:01Z clebert.suconic@jboss.com $
*/
public class HornetQConnection implements Connection, TopicConnection, QueueConnection
{
   // Constants ------------------------------------------------------------------------------------

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

   public static final int TYPE_GENERIC_CONNECTION = 0;

   public static final int TYPE_QUEUE_CONNECTION = 1;

   public static final int TYPE_TOPIC_CONNECTION = 2;

   public static final String EXCEPTION_FAILOVER = "FAILOVER";

   public static final String EXCEPTION_DISCONNECT = "DISCONNECT";

   public static final SimpleString CONNECTION_ID_PROPERTY_NAME = new SimpleString("__HQ_CID");

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

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

   private final int connectionType;

   private final Set<HornetQSession> sessions = new org.hornetq.utils.ConcurrentHashSet<HornetQSession>();

   private final Set<SimpleString> tempQueues = new org.hornetq.utils.ConcurrentHashSet<SimpleString>();

   private volatile boolean hasNoLocal;

   private volatile ExceptionListener exceptionListener;

   private volatile boolean justCreated = true;

   private volatile ConnectionMetaData metaData;

   private volatile boolean closed;

   private volatile boolean started;

   private String clientID;

   private final ClientSessionFactory sessionFactory;

   private final SimpleString uid;

   private final String username;

   private final String password;

   private final SessionFailureListener listener = new JMSFailureListener(this);

   private final Version thisVersion;

   private final int dupsOKBatchSize;

   private final int transactionBatchSize;

   private ClientSession initialSession;

   private final Exception creationStack;

   private HornetQConnectionFactory factoryReference;

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

   public HornetQConnection(final String username,
                            final String password,
                            final int connectionType,
                            final String clientID,
                            final int dupsOKBatchSize,
                            final int transactionBatchSize,
                            final ClientSessionFactory sessionFactory)
   {
      this.username = username;

      this.password = password;

      this.connectionType = connectionType;

      this.clientID = clientID;

      this.sessionFactory = sessionFactory;

      uid = UUIDGenerator.getInstance().generateSimpleStringUUID();

      thisVersion = VersionLoader.getVersion();

      this.dupsOKBatchSize = dupsOKBatchSize;

      this.transactionBatchSize = transactionBatchSize;

      creationStack = new Exception();
   }

   // Connection implementation --------------------------------------------------------------------

   public Session createSession(final boolean transacted, final int acknowledgeMode) throws JMSException
   {
      checkClosed();

      return (Session)createSessionInternal(transacted, acknowledgeMode, false, HornetQConnection.TYPE_GENERIC_CONNECTION);
   }

   public String getClientID() throws JMSException
   {
      checkClosed();

      return clientID;
   }

   public void setClientID(final String clientID) throws JMSException
   {
      checkClosed();

      if (this.clientID != null)
      {
         throw new IllegalStateException("Client id has already been set");
      }

      if (!justCreated)
      {
         throw new IllegalStateException("setClientID can only be called directly after the connection is created");
      }
     
      try
      {
         initialSession.addUniqueMetaData("jms-client-id", clientID);
      }
      catch (HornetQException e)
      {
         if (e.getCode() == HornetQException.DUPLICATE_METADATA)
         {
            throw new IllegalStateException("clientID=" + clientID + " was already set into another connection");
         }
      }

      this.clientID = clientID;
      try
      {
         this.addSessionMetaData(initialSession);
      }
      catch (HornetQException e)
      {
         JMSException ex = new JMSException("Internal error setting metadata jms-client-id");
         ex.setLinkedException(e);
         throw ex;
      }

      justCreated = false;
   }

   public ConnectionMetaData getMetaData() throws JMSException
   {
      checkClosed();

      justCreated = false;

      if (metaData == null)
      {
         metaData = new HornetQConnectionMetaData(thisVersion);
      }

      return metaData;
   }

   public ExceptionListener getExceptionListener() throws JMSException
   {
      checkClosed();

      justCreated = false;

      return exceptionListener;
   }

   public void setExceptionListener(final ExceptionListener listener) throws JMSException
   {
      checkClosed();

      exceptionListener = listener;
      justCreated = false;
   }

   public synchronized void start() throws JMSException
   {
      checkClosed();

      for (HornetQSession session : sessions)
      {
         session.start();
      }

      justCreated = false;
      started = true;
   }

   public synchronized void stop() throws JMSException
   {
      checkClosed();

      for (HornetQSession session : sessions)
      {
         session.stop();
      }

      justCreated = false;
      started = false;
   }

   public synchronized void close() throws JMSException
   {
      if (closed)
      {
         return;
      }
     
      sessionFactory.close();

      try
      {
         for (HornetQSession session : new HashSet<HornetQSession>(sessions))
         {
            session.close();
         }

         try
         {
            if (!tempQueues.isEmpty())
            {
               // Remove any temporary queues

               for (SimpleString queueName : tempQueues)
               {
                  if (!initialSession.isClosed())
                  {
                     try
                     {
                        initialSession.deleteQueue(queueName);
                     }
                     catch (HornetQException ignore)
                     {
                        //Exception on deleting queue shouldn't prevent close from completing
                     }
                  }
               }
            }
         }
         finally
         {
            if (initialSession != null)
            {
               initialSession.close();
            }
         }

         closed = true;
      }
      catch (HornetQException e)
      {
         throw JMSExceptionHelper.convertFromHornetQException(e);
      }
   }

   public ConnectionConsumer createConnectionConsumer(final Destination destination,
                                                      final String messageSelector,
                                                      final ServerSessionPool sessionPool,
                                                      final int maxMessages) throws JMSException
   {
      checkClosed();

      checkTempQueues(destination);
      return null;
   }

   private void checkTempQueues(Destination destination)
         throws JMSException
   {
      HornetQDestination jbdest = (HornetQDestination)destination;

      if (jbdest.isTemporary() && !containsTemporaryQueue(jbdest.getSimpleAddress()))
      {
         throw new JMSException("Can not create consumer for temporary destination " + destination +
                                " from another JMS connection");
      }
   }

   public ConnectionConsumer createDurableConnectionConsumer(final Topic topic,
                                                             final String subscriptionName,
                                                             final String messageSelector,
                                                             final ServerSessionPool sessionPool,
                                                             final int maxMessages) throws JMSException
   {
      checkClosed();
      // As spec. section 4.11
      if (connectionType == HornetQConnection.TYPE_QUEUE_CONNECTION)
      {
         String msg = "Cannot create a durable connection consumer on a QueueConnection";
         throw new javax.jms.IllegalStateException(msg);
      }
      checkTempQueues(topic);
      // TODO
      return null;
   }

   // QueueConnection implementation ---------------------------------------------------------------

   public QueueSession createQueueSession(final boolean transacted, final int acknowledgeMode) throws JMSException
   {
      checkClosed();
      return (QueueSession)createSessionInternal(transacted, acknowledgeMode, false, HornetQSession.TYPE_QUEUE_SESSION);
   }

   public ConnectionConsumer createConnectionConsumer(final Queue queue,
                                                      final String messageSelector,
                                                      final ServerSessionPool sessionPool,
                                                      final int maxMessages) throws JMSException
   {
      checkClosed();
      checkTempQueues(queue);
      return null;
   }

   // TopicConnection implementation ---------------------------------------------------------------

   public TopicSession createTopicSession(final boolean transacted, final int acknowledgeMode) throws JMSException
   {
      checkClosed();
      return (TopicSession)createSessionInternal(transacted, acknowledgeMode, false, HornetQSession.TYPE_TOPIC_SESSION);
   }

   public ConnectionConsumer createConnectionConsumer(final Topic topic,
                                                      final String messageSelector,
                                                      final ServerSessionPool sessionPool,
                                                      final int maxMessages) throws JMSException
   {
      checkClosed();
      checkTempQueues(topic);
      return null;
   }

   // XAConnection implementation ------------------------------------------------------------------

   public XASession createXASession() throws JMSException
   {
      checkClosed();
      return (XASession)createSessionInternal(true, Session.SESSION_TRANSACTED, true, HornetQSession.TYPE_GENERIC_SESSION);
   }

   // XAQueueConnection implementation -------------------------------------------------------------

   public XAQueueSession createXAQueueSession() throws JMSException
   {
      checkClosed();
      return (XAQueueSession)createSessionInternal(true, Session.SESSION_TRANSACTED, true, HornetQSession.TYPE_QUEUE_SESSION);

   }

   // XATopicConnection implementation -------------------------------------------------------------

   public XATopicSession createXATopicSession() throws JMSException
   {
      checkClosed();
      return (XATopicSession)createSessionInternal(true, Session.SESSION_TRANSACTED, true, HornetQSession.TYPE_TOPIC_SESSION);

   }

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

   public void addTemporaryQueue(final SimpleString queueAddress)
   {
      tempQueues.add(queueAddress);
   }

   public void removeTemporaryQueue(final SimpleString queueAddress)
   {
      tempQueues.remove(queueAddress);
   }

   public boolean containsTemporaryQueue(final SimpleString queueAddress)
   {
      return tempQueues.contains(queueAddress);
   }

   public boolean hasNoLocal()
   {
      return hasNoLocal;
   }

   public void setHasNoLocal()
   {
      hasNoLocal = true;
   }

   public SimpleString getUID()
   {
      return uid;
   }

   public void removeSession(final HornetQSession session)
   {
      sessions.remove(session);
   }

   public ClientSession getInitialSession()
   {
      return initialSession;
   }

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

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

   // In case the user forgets to close the connection manually

   @Override
   protected void finalize() throws Throwable
   {
      if (!closed)
      {
         HornetQConnection.log.warn("I'm closing a JMS connection you left open. Please make sure you close all JMS connections explicitly " + "before letting them go out of scope!");

         HornetQConnection.log.warn("The JMS connection you didn't close was created here:", creationStack);

         close();
      }
   }

   private Object createSessionInternal(final boolean transacted,
                                                  int acknowledgeMode,
                                                  final boolean isXA,
                                                  final int type) throws JMSException
   {
      if (transacted)
      {
         acknowledgeMode = Session.SESSION_TRANSACTED;
      }

      try
      {
         ClientSession session;

         if (acknowledgeMode == Session.SESSION_TRANSACTED)
         {
            session = sessionFactory.createSession(username,
                                                   password,
                                                   isXA,
                                                   false,
                                                   false,
                                                   sessionFactory.getServerLocator().isPreAcknowledge(),
                                                   transactionBatchSize);
         }
         else if (acknowledgeMode == Session.AUTO_ACKNOWLEDGE)
         {
            session = sessionFactory.createSession(username,
                                                   password,
                                                   isXA,
                                                   true,
                                                   true,
                                                   sessionFactory.getServerLocator().isPreAcknowledge(),
                                                   0);
         }
         else if (acknowledgeMode == Session.DUPS_OK_ACKNOWLEDGE)
         {
            session = sessionFactory.createSession(username,
                                                   password,
                                                   isXA,
                                                   true,
                                                   true,
                                                   sessionFactory.getServerLocator().isPreAcknowledge(),
                                                   dupsOKBatchSize);
         }
         else if (acknowledgeMode == Session.CLIENT_ACKNOWLEDGE)
         {
            session = sessionFactory.createSession(username,
                                                   password,
                                                   isXA,
                                                   true,
                                                   false,
                                                   sessionFactory.getServerLocator().isPreAcknowledge(),
                                                   transactionBatchSize);
         }
         else if (acknowledgeMode == HornetQJMSConstants.PRE_ACKNOWLEDGE)
         {
            session = sessionFactory.createSession(username, password, isXA, true, false, true, transactionBatchSize);
         }
         else
         {
            throw new IllegalArgumentException("Invalid ackmode: " + acknowledgeMode);
         }

         justCreated = false;

         // Setting multiple times on different sessions doesn't matter since RemotingConnection maintains
         // a set (no duplicates)
         session.addFailureListener(listener);
        
        
        

         HornetQSession jbs;
        
         if (isXA)
         {
            jbs = new HornetQXASession(this, transacted, isXA, acknowledgeMode, session, type);
         }
         else
         {
            jbs = new HornetQSession(this, transacted, isXA, acknowledgeMode, session, type);
         }

         sessions.add(jbs);

         if (started)
         {
            session.start();
         }
        
         this.addSessionMetaData(session);

         return jbs;
      }
      catch (HornetQException e)
      {
         throw JMSExceptionHelper.convertFromHornetQException(e);
      }
   }

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

   private void checkClosed() throws JMSException
   {
      if (closed)
      {
         throw new IllegalStateException("Connection is closed");
      }
   }

   public void authorize() throws JMSException
   {
      try
      {
         initialSession = sessionFactory.createSession(username, password, false, false, false, false, 0);

         addSessionMetaData(initialSession);

         initialSession.addFailureListener(listener);
      }
      catch (HornetQException me)
      {
         throw JMSExceptionHelper.convertFromHornetQException(me);
      }
   }

   private void addSessionMetaData(ClientSession session) throws HornetQException
   {
      session.addMetaData("jms-session", "");
      if (clientID != null)
      {
         session.addMetaData("jms-client-id", clientID);
      }
   }

   public void setReference(HornetQConnectionFactory factory)
   {
      this.factoryReference = factory;
   }

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

   private static class JMSFailureListener implements SessionFailureListener
   {
      private final WeakReference<HornetQConnection> connectionRef;

      JMSFailureListener(final HornetQConnection connection)
      {
         connectionRef = new WeakReference<HornetQConnection>(connection);
      }

      public synchronized void connectionFailed(final HornetQException me, boolean failedOver)
      {
         if (me == null)
         {
            return;
         }

         HornetQConnection conn = connectionRef.get();

         if (conn != null)
         {
            try
            {
               final ExceptionListener exceptionListener = conn.getExceptionListener();

               if (exceptionListener != null)
               {
                  final JMSException je = new JMSException(me.toString(), failedOver?EXCEPTION_FAILOVER: EXCEPTION_DISCONNECT);

                  je.initCause(me);

                  new Thread(new Runnable()
                  {
                     public void run()
                     {
                        exceptionListener.onException(je);
                     }
                  }).start();
               }
            }
            catch (JMSException e)
            {
               if (!conn.closed)
               {
                  HornetQConnection.log.error("Failed to get exception listener", e);
               }
            }
         }
      }

      public void beforeReconnect(final HornetQException me)
      {
      }

   }
}
TOP

Related Classes of org.hornetq.jms.client.HornetQConnection$JMSFailureListener

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.