org.wso2.andes.server.AMQBrokerManagerMBean.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.andes.server.AMQBrokerManagerMBean.java

Source

/*
 * Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. 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.wso2.andes.server;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.management.JMException;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.wso2.andes.AMQException;
import org.wso2.andes.amqp.AMQPUtils;
import org.wso2.andes.amqp.QpidAMQPBridge;
import org.wso2.andes.framing.AMQShortString;
import org.wso2.andes.kernel.AndesContext;
import org.wso2.andes.kernel.MessagingEngine;
import org.wso2.andes.kernel.AndesContextStore;
import org.wso2.andes.kernel.AndesQueue;
import org.wso2.andes.kernel.AndesException;
import org.wso2.andes.server.logging.LogMessage;
import org.wso2.andes.subscription.SubscriptionStore;
import org.wso2.andes.management.common.mbeans.ManagedBroker;
import org.wso2.andes.management.common.mbeans.ManagedQueue;
import org.wso2.andes.management.common.mbeans.annotations.MBeanConstructor;
import org.wso2.andes.management.common.mbeans.annotations.MBeanDescription;
import org.wso2.andes.server.exchange.Exchange;
import org.wso2.andes.server.exchange.ExchangeFactory;
import org.wso2.andes.server.exchange.ExchangeRegistry;
import org.wso2.andes.server.exchange.ExchangeType;
import org.wso2.andes.server.management.AMQManagedObject;
import org.wso2.andes.server.management.ManagedObject;
import org.wso2.andes.server.queue.AMQQueue;
import org.wso2.andes.server.queue.AMQQueueFactory;
import org.wso2.andes.server.queue.AMQQueueMBean;
import org.wso2.andes.server.queue.QueueRegistry;
import org.wso2.andes.server.store.DurableConfigurationStore;
import org.wso2.andes.server.virtualhost.VirtualHost;
import org.wso2.andes.server.virtualhost.VirtualHostImpl;
import org.wso2.andes.server.logging.actors.CurrentActor;
import org.wso2.andes.server.logging.actors.ManagementActor;

/**
 * This MBean implements the broker management interface and exposes the
 * Broker level management features like creating and deleting exchanges and queue.
 */
@MBeanDescription("This MBean exposes the broker level management features")
public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBroker {
    private static Log log = LogFactory.getLog(AMQBrokerManagerMBean.class);

    private final QueueRegistry _queueRegistry;
    private final ExchangeRegistry _exchangeRegistry;
    private final ExchangeFactory _exchangeFactory;
    private final DurableConfigurationStore _durableConfig;

    private final VirtualHostImpl.VirtualHostMBean _virtualHostMBean;

    //ContextStore object to do the database calls
    private static AndesContextStore contextStore;

    @MBeanConstructor("Creates the Broker Manager MBean")
    public AMQBrokerManagerMBean(VirtualHostImpl.VirtualHostMBean virtualHostMBean) throws JMException {
        super(ManagedBroker.class, ManagedBroker.TYPE);

        _virtualHostMBean = virtualHostMBean;
        VirtualHost virtualHost = virtualHostMBean.getVirtualHost();

        _queueRegistry = virtualHost.getQueueRegistry();
        _exchangeRegistry = virtualHost.getExchangeRegistry();
        _durableConfig = virtualHost.getDurableConfigurationStore();
        _exchangeFactory = virtualHost.getExchangeFactory();
    }

    public String getObjectInstanceName() {
        return _virtualHostMBean.getVirtualHost().getName();
    }

    /**
     * Returns an array of the exchange types available for creation.
     * @since Qpid JMX API 1.3
     * @throws IOException
     */
    public String[] getExchangeTypes() throws IOException {
        ArrayList<String> exchangeTypes = new ArrayList<String>();
        for (ExchangeType<? extends Exchange> ex : _exchangeFactory.getPublicCreatableTypes()) {
            exchangeTypes.add(ex.getName().toString());
        }

        return exchangeTypes.toArray(new String[0]);
    }

    /**
     * Returns a list containing the names of the attributes available for the Queue mbeans.
     * @since Qpid JMX API 1.3
     * @throws IOException
     */
    public List<String> retrieveQueueAttributeNames() throws IOException {
        return ManagedQueue.QUEUE_ATTRIBUTES;
    }

    /**
     * Returns a List of Object Lists containing the requested attribute values (in the same sequence requested) for each queue in the virtualhost.
     * If a particular attribute cant be found or raises an mbean/reflection exception whilst being gathered its value is substituted with the String "-".
     * @since Qpid JMX API 1.3
     * @throws IOException
     */
    public List<List<Object>> retrieveQueueAttributeValues(String[] attributes) throws IOException {
        if (_queueRegistry.getQueues().size() == 0) {
            return new ArrayList<List<Object>>();
        }

        List<List<Object>> queueAttributesList = new ArrayList<List<Object>>(_queueRegistry.getQueues().size());

        int attributesLength = attributes.length;

        for (AMQQueue queue : _queueRegistry.getQueues()) {
            AMQQueueMBean mbean = (AMQQueueMBean) queue.getManagedObject();

            if (mbean == null) {
                continue;
            }

            List<Object> attributeValues = new ArrayList<Object>(attributesLength);

            for (String attribute : attributes) {
                try {
                    attributeValues.add(mbean.getAttribute(attribute));
                } catch (Exception e) {
                    attributeValues.add("-");
                }
            }

            queueAttributesList.add(attributeValues);
        }

        return queueAttributesList;
    }

    /**
     * Creates new exchange and registers it with the registry.
     *
     * @param exchangeName
     * @param type
     * @param durable
     * @throws JMException
     * @throws MBeanException
     */
    public void createNewExchange(String exchangeName, String type, boolean durable)
            throws JMException, MBeanException {
        CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger()));
        try {
            synchronized (_exchangeRegistry) {
                Exchange exchange = _exchangeRegistry.getExchange(new AMQShortString(exchangeName));
                if (exchange == null) {
                    exchange = _exchangeFactory.createExchange(new AMQShortString(exchangeName),
                            new AMQShortString(type), durable, false, 0);
                    _exchangeRegistry.registerExchange(exchange);
                    if (durable) {
                        _durableConfig.createExchange(exchange);

                        //tell Andes kernel to create Exchange
                        QpidAMQPBridge.getInstance().createExchange(exchange);
                    }
                } else {
                    throw new JMException("The exchange \"" + exchangeName + "\" already exists.");
                }
            }
        } catch (AMQException ex) {
            JMException jme = new JMException(ex.toString());
            throw new MBeanException(jme, "Error in creating exchange " + exchangeName);
        } finally {
            CurrentActor.remove();
        }
    }

    /**
     * Unregisters the exchange from registry.
     *
     * @param exchangeName
     * @throws JMException
     * @throws MBeanException
     */
    public void unregisterExchange(String exchangeName) throws JMException, MBeanException {
        // TODO
        // Check if the exchange is in use.
        // boolean inUse = false;
        // Check if there are queue-bindings with the exchange and unregister
        // when there are no bindings.
        CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger()));
        try {
            _exchangeRegistry.unregisterExchange(new AMQShortString(exchangeName), false);
        } catch (AMQException ex) {
            JMException jme = new JMException(ex.toString());
            throw new MBeanException(jme, "Error in unregistering exchange " + exchangeName);
        } finally {
            CurrentActor.remove();
        }
    }

    /**
     * Creates a new queue and registers it with the registry and puts it
     * in persistance storage if durable queue.
     *
     * @param queueName
     * @param durable
     * @param owner
     * @throws JMException
     * @throws MBeanException
     */
    public void createNewQueue(String queueName, String owner, boolean durable, boolean exclusiveConsumer)
            throws JMException, MBeanException {
        AMQQueue queue = _queueRegistry.getQueue(new AMQShortString(queueName));
        try {
            if (queue != null) {
                //ClusterResourceHolder.getInstance().getCassandraMessageStore().addQueue(queueName);
                throw new JMException("The queue \"" + queueName + "\" already exists.");
            }

            CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger()));
            AMQShortString ownerShortString = null;
            if (owner != null) {
                ownerShortString = new AMQShortString(owner);
            }

            queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(queueName), durable, ownerShortString,
                    false, false, getVirtualHost(), null);
            if (queue.isDurable() && !queue.isAutoDelete()) {
                _durableConfig.createQueue(queue);

                //tell Andes kernel to create queue
                QpidAMQPBridge.getInstance().createQueue(queue, exclusiveConsumer);
            }

        } catch (Exception ex) {
            JMException jme = new JMException(ex.toString());
            throw new MBeanException(jme, "The queue \"" + queueName + "\" already exists.");
        } finally {
            CurrentActor.remove();
        }
    }

    private VirtualHost getVirtualHost() {
        return _virtualHostMBean.getVirtualHost();
    }

    /**
     * Deletes the queue from queue registry and persistant storage.
     *
     * @param queueName
     * @throws JMException
     * @throws MBeanException
     */
    public void deleteQueue(final String queueName) throws JMException, MBeanException {
        AMQQueue queue = _queueRegistry.getQueue(new AMQShortString(queueName));
        if (queue == null) {
            throw new JMException("The Queue " + queueName + " is not a registered queue.");
        }
        try {
            boolean isQueueDeletable = ClusterResourceHolder.getInstance().getVirtualHostConfigSynchronizer()
                    .checkIfQueueDeletable(queue);
            if (isQueueDeletable) {
                CurrentActor.set(new ManagementActor(_logActor.getRootMessageLogger()));
                queue.delete();
                if (queue.isDurable()) {
                    _durableConfig.removeQueue(queue);
                }

                //tell Andes kernel to remove queue
                QpidAMQPBridge.getInstance().deleteQueue(queue);
            } else {
                _logActor.message(new LogMessage() {
                    String message = "Cannot Delete Queue" + queueName + " It Has Registered Subscriptions.";

                    public String toString() {
                        return message;
                    }

                    public String getLogHierarchy() {
                        return "amqp.queue";
                    }
                });
                throw new AMQException("Cannot Delete Queue" + queueName + " It Has Registered Subscriptions.");
            }
        } catch (AMQException ex) {
            JMException jme = new JMException(ex.toString());
            if (ex.toString().contains("not a registered queue")) {
                throw new MBeanException(jme, "The Queue " + queueName + " is not a registered queue.");
            } else if (ex.toString().contains("Has Registered Subscriptions")) {
                throw new MBeanException(jme,
                        "Queue " + queueName + " has active subscribers. Please stop them first.");
            } else {
                throw new MBeanException(jme, "Error in deleting queue " + queueName + ":");
            }
        } catch (Exception e) {
            throw new MBeanException(e,
                    "Error in deleting queue " + queueName + ". There was an issue with cluster coordination");
        } finally {
            CurrentActor.remove();
        }
    }

    @Override
    public ManagedObject getParentObject() {
        return _virtualHostMBean;
    }

    // This will have a single instance for a virtual host, so not having the name property in the ObjectName
    @Override
    public ObjectName getObjectName() throws MalformedObjectNameException {
        return getObjectNameForSingleInstanceMBean();
    }

    public void resetStatistics() throws Exception {
        getVirtualHost().resetStatistics();
    }

    public double getPeakMessageDeliveryRate() {
        return getVirtualHost().getMessageDeliveryStatistics().getPeak();
    }

    public double getPeakDataDeliveryRate() {
        return getVirtualHost().getDataDeliveryStatistics().getPeak();
    }

    public double getMessageDeliveryRate() {
        return getVirtualHost().getMessageDeliveryStatistics().getRate();
    }

    public double getDataDeliveryRate() {
        return getVirtualHost().getDataDeliveryStatistics().getRate();
    }

    public long getTotalMessagesDelivered() {
        return getVirtualHost().getMessageDeliveryStatistics().getTotal();
    }

    public long getTotalDataDelivered() {
        return getVirtualHost().getDataDeliveryStatistics().getTotal();
    }

    public double getPeakMessageReceiptRate() {
        return getVirtualHost().getMessageReceiptStatistics().getPeak();
    }

    public double getPeakDataReceiptRate() {
        return getVirtualHost().getDataReceiptStatistics().getPeak();
    }

    public double getMessageReceiptRate() {
        return getVirtualHost().getMessageReceiptStatistics().getRate();
    }

    public double getDataReceiptRate() {
        return getVirtualHost().getDataReceiptStatistics().getRate();
    }

    public long getTotalMessagesReceived() {
        return getVirtualHost().getMessageReceiptStatistics().getTotal();
    }

    public long getTotalDataReceived() {
        return getVirtualHost().getDataReceiptStatistics().getTotal();
    }

    public boolean isStatisticsEnabled() {
        return getVirtualHost().isStatisticsEnabled();
    }

    /**
     * Updating exclusive Consumer Value
     * @param queueName name of the queue
     * @param isExclusiveConsumer   exclusive consumer value of the queue
     * @throws IOException
     * @throws JMException
     * @throws AndesException
     */
    @Override
    public void updateExclusiveConsumerValue(String queueName, boolean isExclusiveConsumer)
            throws IOException, JMException, AndesException {

        List<AndesQueue> queueList = null;
        try {
            queueList = AndesContext.getInstance().getAndesContextStore().getAllQueuesStored();

            if (queueList != null) {
                for (AndesQueue andesQueue : queueList) {

                    if (andesQueue.queueName.equals(queueName)) {
                        andesQueue.isExclusiveConsumer = isExclusiveConsumer;

                        //updating the database
                        AndesContext.getInstance().getAndesContextStore().updateExclusiveConsumerForQueue(queueName,
                                isExclusiveConsumer);
                    }
                }
            }
        } catch (AndesException e) {
            log.error("Error in updating exclusive consumer value", e);
            throw new AndesException("Error in updating exclusive consumer value.");
        }
    }
}