Package org.codehaus.activemq.service.impl

Source Code of org.codehaus.activemq.service.impl.DurableQueueMessageContainer

/**
*
* Copyright 2004 Protique Ltd
*
* Licensed 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.codehaus.activemq.service.impl;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.message.ActiveMQMessage;
import org.codehaus.activemq.message.MessageAck;
import org.codehaus.activemq.service.MessageIdentity;
import org.codehaus.activemq.service.QueueList;
import org.codehaus.activemq.service.QueueListEntry;
import org.codehaus.activemq.service.QueueMessageContainer;
import org.codehaus.activemq.store.MessageStore;
import org.codehaus.activemq.store.PersistenceAdapter;
import org.codehaus.activemq.util.Callback;
import org.codehaus.activemq.util.TransactionTemplate;

import javax.jms.JMSException;

/**
* A default implemenation of a Durable Queue based
* {@link org.codehaus.activemq.service.MessageContainer}
* which acts as an adapter between the {@link org.codehaus.activemq.service.MessageContainerManager}
* requirements and those of the persistent {@link MessageStore} implementations.
*
* @version $Revision: 1.19 $
*/
public class DurableQueueMessageContainer implements QueueMessageContainer {
    private static final Log log = LogFactory.getLog(DurableQueueMessageContainer.class);

    private MessageStore messageStore;
    private String destinationName;

    /**
     * messages to be delivered
     */
    private QueueList messagesToBeDelivered;
    /**
     * messages that have been delivered but not acknowledged
     */
    private QueueList deliveredMessages;
    private PersistenceAdapter persistenceAdapter;
    private TransactionTemplate transactionTemplate;

    public DurableQueueMessageContainer(PersistenceAdapter persistenceAdapter, MessageStore messageStore, String destinationName) {
        this(persistenceAdapter, messageStore, destinationName, new DefaultQueueList(), new DefaultQueueList());
    }

    public DurableQueueMessageContainer(PersistenceAdapter persistenceAdapter, MessageStore messageStore, String destinationName, QueueList messagesToBeDelivered, QueueList deliveredMessages) {
        this.persistenceAdapter = persistenceAdapter;
        this.messageStore = messageStore;
        this.destinationName = destinationName;
        this.messagesToBeDelivered = messagesToBeDelivered;
        this.deliveredMessages = deliveredMessages;
        this.transactionTemplate = new TransactionTemplate(persistenceAdapter);
    }

    public String getDestinationName() {
        return destinationName;
    }

    public MessageIdentity addMessage(ActiveMQMessage message) throws JMSException {
        MessageIdentity answer = messageStore.addMessage(message);
        synchronized( this ) {
          messagesToBeDelivered.add(answer);
        }
        return answer;

    }

    public synchronized void delete(MessageIdentity messageID, MessageAck ack) throws JMSException {
       
        // lets find the cached identity as it has the sequence number
        // attached to it
      MessageIdentity storedIdentity=null;

      synchronized( this ) {
          QueueListEntry entry = deliveredMessages.getFirstEntry();
          while (entry != null) {
              MessageIdentity identity = (MessageIdentity) entry.getElement();
              if (messageID.equals(identity)) {
                  deliveredMessages.remove(entry);
                  storedIdentity=identity;
                  break;
              }
              entry = deliveredMessages.getNextEntry(entry);
          }
         
          if (storedIdentity==null) {
              // maybe the messages have not been delivered yet
              // as we are recovering from a previous transaction log
              entry = messagesToBeDelivered.getFirstEntry();
              while (entry != null) {
                  MessageIdentity identity = (MessageIdentity) entry.getElement();
                  if (messageID.equals(identity)) {
                      messagesToBeDelivered.remove(entry);
                      storedIdentity=identity;
                      break;
                  }
                  entry = messagesToBeDelivered.getNextEntry(entry);
              }
          }
      }
     
        if (storedIdentity==null) {
            log.error("Attempt to acknowledge unknown messageID: " + messageID);
        } else {
            messageStore.removeMessage(storedIdentity, ack);         
        }
       
    }

    public ActiveMQMessage getMessage(MessageIdentity messageID) throws JMSException {
        return messageStore.getMessage(messageID);
    }


    public boolean containsMessage(MessageIdentity messageIdentity) throws JMSException {
        /** TODO: make more optimal implementation */
        return getMessage(messageIdentity) != null;
    }

    /**
     * Does nothing since when we receive an acknowledgement on a queue
     * we can delete the message
     *
     * @param messageIdentity
     */
    public void registerMessageInterest(MessageIdentity messageIdentity) {
    }

    /**
     * Does nothing since when we receive an acknowledgement on a queue
     * we can delete the message
     *
     * @param messageIdentity
     * @param ack
     */
    public void unregisterMessageInterest(MessageIdentity messageIdentity, MessageAck ack) {
    }

    public ActiveMQMessage poll() throws JMSException {
        ActiveMQMessage message = null;
        MessageIdentity messageIdentity=null;
      synchronized( this ) {
          messageIdentity = (MessageIdentity) messagesToBeDelivered.removeFirst();
          if (messageIdentity != null) {
              deliveredMessages.add(messageIdentity);
          }
      }
        if (messageIdentity != null) {
            message = messageStore.getMessage(messageIdentity);
        }
        return message;
    }

    public ActiveMQMessage peekNext(MessageIdentity messageID) throws JMSException {
      ActiveMQMessage answer = null;
      MessageIdentity identity = null;
      synchronized( this ) {
            if (messageID == null) {
              identity = (MessageIdentity) messagesToBeDelivered.getFirst();
            }
            else {
                int index = messagesToBeDelivered.indexOf(messageID);
                if (index >= 0 && (index + 1) < messagesToBeDelivered.size()) {
                  identity = (MessageIdentity) messagesToBeDelivered.get(index + 1);
                }
            }
           
      }
        if (identity != null) {
            answer = messageStore.getMessage(identity);
        }
        return answer;
    }


    public synchronized void returnMessage(MessageIdentity messageIdentity) throws JMSException {
        boolean result = deliveredMessages.remove(messageIdentity);
        messagesToBeDelivered.addFirst(messageIdentity);
    }

    /**
     * called to reset dispatch pointers if a new Message Consumer joins
     *
     * @throws javax.jms.JMSException
     */
    public synchronized void reset() throws JMSException {
        //new Message Consumer - move all filtered/undispatched messages to front of queue
        int count = 0;
        MessageIdentity messageIdentity = (MessageIdentity) deliveredMessages.removeFirst();
        while (messageIdentity != null) {
            messagesToBeDelivered.add(count++, messageIdentity);
            messageIdentity = (MessageIdentity) deliveredMessages.removeFirst();
        }
    }

    public synchronized void start() throws JMSException {
        final QueueMessageContainer container = this;
        transactionTemplate.run(new Callback() {
            public void execute() throws Throwable {
                messageStore.start();
                messageStore.recover(container);
            }
        });

    }

    public synchronized void recoverMessageToBeDelivered(MessageIdentity messageIdentity) throws JMSException {
        messagesToBeDelivered.add(messageIdentity);
    }

    public void stop() throws JMSException {
        messageStore.stop();
    }
}
TOP

Related Classes of org.codehaus.activemq.service.impl.DurableQueueMessageContainer

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.