/*
 * JBossMQ, the OpenSource JMS implementation
 * 
 * Distributable under LGPL license. See terms of license at gnu.org.
 */
package org.jboss.mq;

import java.io.Serializable;

import javax.jms.ConnectionConsumer;
import javax.jms.Destination;
import javax.jms.IllegalStateException;
import javax.jms.InvalidDestinationException;
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.TemporaryQueue;
import javax.jms.TemporaryTopic;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicSession;

import org.jboss.util.UnreachableStatementException;

/**
 * This class implements javax.jms.QueueConnection and
 * javax.jms.TopicConnection
 * 
 * @author Norbert Lataille (Norbert.Lataille@m4x.org)
 * @author Hiram Chirino (Cojonudo14@hotmail.com)
 * @author <a href="mailto:adrian@jboss.org">Adrian Brock</a>
 * @version $Revision: 1.15.6.2 $
 */
public class SpyConnection extends Connection implements Serializable, TopicConnection, QueueConnection
{
   // Constants -----------------------------------------------------

   private static final long serialVersionUID = -6227193901482445607L;

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

   // Constructor ---------------------------------------------------

   /**
	 * Create a new SpyConnection
	 * 
	 * @param userId the user
	 * @param password the password
	 * @param gcf the constructing class
	 * @throws JMSException for any error
	 */
   public SpyConnection(String userId, String password, GenericConnectionFactory gcf) throws JMSException
   {
      super(userId, password, gcf);
   }

   /**
	 * Create a new SpyConnection
	 * 
	 * @param gcf the constructing class
	 * @throws JMSException for any error
	 */
   public SpyConnection(GenericConnectionFactory gcf) throws JMSException
   {
      super(gcf);
   }

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

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

   public ConnectionConsumer createConnectionConsumer(Destination destination, String messageSelector,
         ServerSessionPool sessionPool, int maxMessages) throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");

      if (destination == null)
         throw new InvalidDestinationException("Null destination");

      return new SpyConnectionConsumer(this, destination, messageSelector, sessionPool, maxMessages);
   }

   public Session createSession(boolean transacted, int acknowledgeMode) throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");
      checkClientID();

      if (transacted)
         acknowledgeMode = 0;
      Session session = new SpySession(this, transacted, acknowledgeMode, false);

      //add the new session to the createdSessions list
      synchronized (createdSessions)
      {
         createdSessions.add(session);
      }

      return session;
   }

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

   public TopicSession createTopicSession(boolean transacted, int acknowledgeMode) throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");
      checkClientID();

      if (transacted)
         acknowledgeMode = 0;
      TopicSession session = new SpyTopicSession(this, transacted, acknowledgeMode);

      //add the new session to the createdSessions list
      synchronized (createdSessions)
      {
         createdSessions.add(session);
      }

      return session;
   }

   public ConnectionConsumer createConnectionConsumer(Topic topic, String messageSelector,
         ServerSessionPool sessionPool, int maxMessages) throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");

      if (topic == null)
         throw new InvalidDestinationException("Null topic");

      checkClientID();

      return new SpyConnectionConsumer(this, topic, messageSelector, sessionPool, maxMessages);
   }

   public ConnectionConsumer createDurableConnectionConsumer(Topic topic, String subscriptionName,
         String messageSelector, ServerSessionPool sessionPool, int maxMessages) throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");

      if (topic == null)
         throw new InvalidDestinationException("Null topic");
      if (topic instanceof TemporaryTopic)
         throw new InvalidDestinationException("Attempt to create a durable subscription for a temporary topic");

      if (subscriptionName == null || subscriptionName.trim().length() == 0)
         throw new JMSException("Null or empty subscription");

      SpyTopic t = new SpyTopic((SpyTopic) topic, getClientID(), subscriptionName, messageSelector);
      return new SpyConnectionConsumer(this, t, messageSelector, sessionPool, maxMessages);
   }

   public ConnectionConsumer createConnectionConsumer(Queue queue, String messageSelector,
         ServerSessionPool sessionPool, int maxMessages) throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");

      if (queue == null)
         throw new InvalidDestinationException("Null queue");

      return new SpyConnectionConsumer(this, queue, messageSelector, sessionPool, maxMessages);
   }

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

   public QueueSession createQueueSession(boolean transacted, int acknowledgeMode) throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");
      checkClientID();

      if (transacted)
         acknowledgeMode = 0;
      QueueSession session = new SpyQueueSession(this, transacted, acknowledgeMode);

      //add the new session to the createdSessions list
      synchronized (createdSessions)
      {
         createdSessions.add(session);
      }

      return session;
   }
   
   // Package protected ---------------------------------------------
   
   TemporaryTopic getTemporaryTopic() throws JMSException
   {
      if (closed)
         throw new IllegalStateException("The connection is closed");
      checkClientID();

      try
      {
         SpyTemporaryTopic temp = (SpyTemporaryTopic) serverIL.getTemporaryTopic(connectionToken);
         temp.setConnection(this);
         synchronized (temps)
         {
            temps.add(temp);
         }
         return temp;
      }
      catch (Throwable t)
      {
         SpyJMSException.rethrowAsJMSException("Cannot create a Temporary Topic", t);
         throw new UnreachableStatementException();
      }
   }

   Topic createTopic(String name) throws JMSException
   {
      try
      {
         if (closed)
            throw new IllegalStateException("The connection is closed");
         checkClientID();

         return serverIL.createTopic(connectionToken, name);
      }
      catch (Throwable t)
      {
         SpyJMSException.rethrowAsJMSException("Cannot get the Topic from the provider", t);
         throw new UnreachableStatementException();
      }
   }

   TemporaryQueue getTemporaryQueue() throws JMSException
   {
      if (closed)
      {
         throw new IllegalStateException("The connection is closed");
      }
      checkClientID();

      try
      {
         SpyTemporaryQueue temp = (SpyTemporaryQueue) serverIL.getTemporaryQueue(connectionToken);
         temp.setConnection(this);
         synchronized (temps)
         {
            temps.add(temp);
         }
         return temp;
      }
      catch (Throwable t)
      {
         SpyJMSException.rethrowAsJMSException("Cannot create a Temporary Queue", t);
         throw new UnreachableStatementException();
      }
   }

   Queue createQueue(String name) throws JMSException
   {
      try
      {
         if (closed)
            throw new IllegalStateException("The connection is closed");
         checkClientID();

         return serverIL.createQueue(connectionToken, name);
      }
      catch (Throwable t)
      {
         SpyJMSException.rethrowAsJMSException("Cannot get the Queue from the provider", t);
         throw new UnreachableStatementException();
      }
   }
   
   // Protected -----------------------------------------------------
   
   // Private -------------------------------------------------------
   
   // Inner classes -------------------------------------------------
}