Package org.activemq.service.boundedvm

Source Code of org.activemq.service.boundedvm.TransientTopicBoundedMessageContainer

/**
*
* 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.activemq.service.boundedvm;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import javax.jms.JMSException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.activemq.broker.BrokerClient;
import org.activemq.filter.Filter;
import org.activemq.io.util.MemoryBoundedQueue;
import org.activemq.message.ActiveMQDestination;
import org.activemq.message.ActiveMQMessage;
import org.activemq.message.ConsumerInfo;
import org.activemq.message.MessageAck;
import org.activemq.service.MessageContainer;
import org.activemq.service.MessageContainerAdmin;
import org.activemq.service.MessageIdentity;
import org.activemq.service.Service;

import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;

/**
* A MessageContainer for transient topics One of these exists for every active Connection consuming transient Topic
* messages
*
* @version $Revision: 1.1.1.1 $
*/
public class TransientTopicBoundedMessageContainer
        implements
            MessageContainer,
            Service,
            Runnable,
            MessageContainerAdmin {
    private SynchronizedBoolean started;
    private TransientTopicBoundedMessageManager manager;
    private BrokerClient client;
    private MemoryBoundedQueue queue;
    private Thread worker;
    private CopyOnWriteArrayList subscriptions;
    private Log log;

    /**
     * Construct this beast
     *
     * @param manager
     * @param client
     * @param queue
     */
    public TransientTopicBoundedMessageContainer(TransientTopicBoundedMessageManager manager, BrokerClient client,
            MemoryBoundedQueue queue) {
        this.manager = manager;
        this.client = client;
        this.queue = queue;
        this.started = new SynchronizedBoolean(false);
        this.subscriptions = new CopyOnWriteArrayList();
        this.log = LogFactory.getLog("TransientTopicBoundedMessageContainer:- " + client);
    }

    /**
     * @return true if this Container has no active subscriptions
     */
    public boolean isInactive() {
        return subscriptions.isEmpty();
    }

    /**
     * @return the BrokerClient this Container is dispatching to
     */
    public BrokerClient getBrokerClient() {
        return client;
    }

    /**
     * Add a consumer to dispatch messages to
     *
     * @param filter
     * @param info
     */
    public TransientTopicSubscription addConsumer(Filter filter, ConsumerInfo info) {
        TransientTopicSubscription ts = findMatch(info);
        if (ts == null) {
            ts = new TransientTopicSubscription(filter, info, client);
            subscriptions.add(ts);
        }
        return ts;
    }

    /**
     * Remove a consumer
     *
     * @param info
     */
    public void removeConsumer(ConsumerInfo info) {
        TransientTopicSubscription ts = findMatch(info);
        if (ts != null) {
            subscriptions.remove(ts);
        }
    }

    /**
     * start working
     */
    public void start() {
        if (started.commit(false, true)) {
            if (manager.isDecoupledDispatch()) {
                worker = new Thread(this, "TransientTopicDispatcher");
                worker.setPriority(Thread.NORM_PRIORITY + 2);
                worker.start();
            }
        }
    }

    /**
     * See if this container should get this message and dispatch it
     *
     * @param sender the BrokerClient the message came from
     * @param message
     * @return true if it is a valid container
     * @throws JMSException
     */
    public boolean targetAndDispatch(BrokerClient sender, ActiveMQMessage message) throws JMSException {
        boolean result = false;
        if (!this.client.isClusteredConnection() || !sender.isClusteredConnection()) {
            List tmpList = null;
            for (Iterator i = subscriptions.iterator();i.hasNext();) {
                TransientTopicSubscription ts = (TransientTopicSubscription) i.next();

                if (!(ts.client.getChannel() != null && ts.client.getChannel().isMulticast() && ts.client.equals(sender)) && ts.isTarget(message)) {
                    if (tmpList == null) {
                        tmpList = new ArrayList();
                    }
                    tmpList.add(ts);
                }
            }
            dispatchToQueue(message, tmpList);
            result = tmpList != null;
        }
        return result;
    }

    /**
     * stop working
     */
    public void stop() {
        started.set(false);
        queue.clear();
    }

    /**
     * close down this container
     */
    public void close() {
        if (started.get()) {
            stop();
        }
        queue.close();
    }
   
  
    /**
     * do some dispatching
     */
    public void run() {
        int count = 0;
        ActiveMQMessage message = null;
        while (started.get()) {
            try {
                message = (ActiveMQMessage) queue.dequeue(2000);
                if (message != null) {
                    if (!message.isExpired()) {
                        client.dispatch(message);
                        if (++count == 250) {
                            count = 0;
                            Thread.yield();
                        }
                    }else {
                        if (log.isDebugEnabled()){
                            log.debug("Message: " + message + " has expired");
                        }
                    }
                }
            }
            catch (Exception e) {
                stop();
                log.warn("stop dispatching", e);
            }
        }
    }

    private void dispatchToQueue(ActiveMQMessage message, List list) throws JMSException {
        if (list != null && !list.isEmpty()) {
            int[] ids = new int[list.size()];
            for (int i = 0;i < list.size();i++) {
                TransientTopicSubscription ts = (TransientTopicSubscription) list.get(i);
                ids[i] = ts.getConsumerInfo().getConsumerNo();
            }
            message = message.shallowCopy();
            message.setConsumerNos(ids);
            if (manager.isDecoupledDispatch()) {
                queue.enqueue(message);
            }
            else {
                client.dispatch(message);
            }
        }
    }

    private TransientTopicSubscription findMatch(ConsumerInfo info) {
        TransientTopicSubscription result = null;
        for (Iterator i = subscriptions.iterator();i.hasNext();) {
            TransientTopicSubscription ts = (TransientTopicSubscription) i.next();
            if (ts.getConsumerInfo().equals(info)) {
                result = ts;
                break;
            }
        }
        return result;
    }

    /**
     * @param destination
     * @return true if a
     */
    public boolean hasConsumerFor(ActiveMQDestination destination) {
        for (Iterator i = subscriptions.iterator();i.hasNext();) {
            TransientTopicSubscription ts = (TransientTopicSubscription) i.next();
            ConsumerInfo info = ts.getConsumerInfo();
            if (info.getDestination().matches(destination)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return the destination name
     */
    public String getDestinationName() {
        return "";
    }

    /**
     * @param msg
     * @return @throws JMSException
     */
    public void addMessage(ActiveMQMessage msg) throws JMSException {
    }

    /**
     * @param messageIdentity
     * @param ack
     * @throws JMSException
     */
    public void delete(MessageIdentity messageIdentity, MessageAck ack) throws JMSException {
    }

    /**
     * @param messageIdentity
     * @return @throws JMSException
     */
    public ActiveMQMessage getMessage(MessageIdentity messageIdentity) throws JMSException {
        return null;
    }

    /**
     * @param messageIdentity
     * @throws JMSException
     */
    public void registerMessageInterest(MessageIdentity messageIdentity) throws JMSException {
    }

    /**
     * @param messageIdentity
     * @param ack
     * @throws JMSException
     */
    public void unregisterMessageInterest(MessageIdentity messageIdentity) throws JMSException {
    }

    /**
     * @param messageIdentity
     * @return @throws JMSException
     */
    public boolean containsMessage(MessageIdentity messageIdentity) throws JMSException {
        return false;
    }

    /**
     * @see org.activemq.service.MessageContainer#getMessageContainerAdmin()
     */
    public MessageContainerAdmin getMessageContainerAdmin() {
        return this;
    }

    /**
     * @see org.activemq.service.MessageContainerAdmin#empty()
     */
    public void empty() throws JMSException {
        // TODO implement me
    }

    /**
     * @see org.activemq.service.MessageContainer#isDeadLetterQueue()
     */
    public boolean isDeadLetterQueue() {
        return false;
    }
}
TOP

Related Classes of org.activemq.service.boundedvm.TransientTopicBoundedMessageContainer

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.