Package net.timewalker.ffmq3.common.session

Source Code of net.timewalker.ffmq3.common.session.AbstractMessageConsumer

/*
* This file is part of FFMQ.
*
* FFMQ 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 of the License, or
* (at your option) any later version.
*
* FFMQ 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 FFMQ; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/
package net.timewalker.ffmq3.common.session;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;

import net.timewalker.ffmq3.FFMQException;
import net.timewalker.ffmq3.common.message.AbstractMessage;
import net.timewalker.ffmq3.storage.message.MessageSerializationLevel;
import net.timewalker.ffmq3.utils.ErrorTools;
import net.timewalker.ffmq3.utils.id.IntegerID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* <p>Base implementation for a {@link MessageConsumer}</p>
*/
public abstract class AbstractMessageConsumer extends AbstractMessageHandler implements MessageConsumer
{
  private static final Log log = LogFactory.getLog(AbstractMessageConsumer.class);
 
  // Attributes
    protected String messageSelector;
    protected boolean noLocal;
    protected MessageListener messageListener;
    protected boolean autoAcknowledge;

    /**
     * Constructor
     */
    public AbstractMessageConsumer( AbstractSession session,
                                    Destination destination,
                                    String messageSelector,
                                    boolean noLocal,
                                    IntegerID consumerId ) throws JMSException
    {
        super(session,destination,consumerId);
        this.messageSelector = messageSelector;
        this.noLocal = noLocal;
        this.autoAcknowledge =
          (session.getAcknowledgeMode() == Session.AUTO_ACKNOWLEDGE ||
           session.getAcknowledgeMode() == Session.DUPS_OK_ACKNOWLEDGE);
       
        if (destination == null)
            throw new FFMQException("Message consumer destination cannot be null","INVALID_DESTINATION");
    }
   
    protected abstract boolean shouldLogListenersFailures();
   
    /* (non-Javadoc)
     * @see javax.jms.MessageProducer#close()
     */
    public final void close() throws JMSException
    {
      synchronized (externalAccessLock)
      {
        if (closed)
          return;
        closed = true;
        onConsumerClose();
      }
      onConsumerClosed();
    }
   
    /**
   * @throws JMSException 
   */
    protected void onConsumerClose()
    {
      session.unregisterConsumer(this);
    }
   
    /**
   * @throws JMSException 
   */
    protected void onConsumerClosed()
    {
      // Nothing
    }
    /* (non-Javadoc)
     * @see javax.jms.MessageConsumer#getMessageSelector()
     */
    public final String getMessageSelector()
    {
        return messageSelector;
    }
   
    /* (non-Javadoc)
     * @see javax.jms.MessageConsumer#getMessageListener()
     */
    public final MessageListener getMessageListener()
    {
        return messageListener;
    }
   
    /* (non-Javadoc)
     * @see javax.jms.MessageConsumer#setMessageListener(javax.jms.MessageListener)
     */
    public void setMessageListener(MessageListener messageListener) throws JMSException
    {
      synchronized (externalAccessLock)
    {
        checkNotClosed();
        this.messageListener = messageListener;
    }
    }
   
    /* (non-Javadoc)
     * @see javax.jms.MessageConsumer#receive()
     */
    public final Message receive() throws JMSException
    {
        return receive(-1);
    }
   
    /* (non-Javadoc)
     * @see javax.jms.MessageConsumer#receiveNoWait()
     */
    public final Message receiveNoWait() throws JMSException
    {
        return receive(0);
    }
   
    /*
     * (non-Javadoc)
     * @see javax.jms.MessageConsumer#receive(long)
     */
    public final Message receive(long timeout) throws JMSException
    {
        if (messageListener != null)
            throw new FFMQException("Cannot receive messages while a listener is active","INVALID_OPERATION");
       
        AbstractMessage message = receiveFromDestination(timeout,true);
        if (message != null)
        {
          message.ensureDeserializationLevel(MessageSerializationLevel.FULL);
         
            message.setSession(session);
           
            // Auto acknowledge message
            if (autoAcknowledge)
                session.acknowledge();
        }
        return message;
    }
   
    /**
     * Receive a message from a destination
     */
    protected abstract AbstractMessage receiveFromDestination( long timeout , boolean duplicateRequired ) throws JMSException;

    /**
     * Wake up the consumer message listener
     */
    protected final void wakeUpMessageListener()
    {
      try
      {
        while (true)
        {
          synchronized (session.deliveryLock) // [JMS spec]
        {
            AbstractMessage message = receiveFromDestination(0,true);
            if (message == null)
              break;
           
            // Make sure the message's session is set
                message.setSession(session);
               
                // Call the message listener
                boolean listenerFailed = false;
                  try
                  {
                      messageListener.onMessage(message);
                  }
                  catch (Throwable e)
                  {
                    listenerFailed = true;
                    if (shouldLogListenersFailures())
                        log.error("Message listener failed",e);
                  }
                 
                // Auto acknowledge message
                if (autoAcknowledge)
                {
                  if (listenerFailed)
                    session.recover();
                  else
                    session.acknowledge();
                }
          }
        }
      }
      catch (JMSException e)
      {
        ErrorTools.log(e, log);
      }
    }
   
    /**
     * Notify the consumer of the immediate availability of a new message
     */
    public abstract void messageAvailable() throws JMSException;
}
TOP

Related Classes of net.timewalker.ffmq3.common.session.AbstractMessageConsumer

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.