Package hermes.ext.imq

Source Code of hermes.ext.imq.ImqAdmin

/*
* Copyright 2009 Laurent Bovet, Swiss Post IT
*
* 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 hermes.ext.imq;

import hermes.Domain;
import hermes.Hermes;
import hermes.HermesAdmin;
import hermes.browser.HermesBrowser;
import hermes.config.DestinationConfig;
import hermes.ext.HermesAdminSupport;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import javax.jms.Topic;

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

/**
* Support for Sun MQ (aka Java MQ or even Open MQ, technically named imq).
*
* @author bovetl
* @version $Revision$
* @since 01.00.00.00
*/
public class ImqAdmin extends HermesAdminSupport implements HermesAdmin, MessageListener {
  static final String DEST_LIST_TOPIC_NAME = "mq.metrics.destination_list";
  static final String QUEUE_METRICS_TOPIC_PREFIX = "mq.metrics.destination.queue.";
  static final String TOPIC_METRICS_TOPIC_PREFIX = "mq.metrics.destination.topic.";

  private final ConnectionFactory connectionFactory;
  private Connection connection;
  private Session session;
  private MessageConsumer destListTopicSubscriber;

  private final Map<String, MessageConsumer> destMetricTopicSubscribers = new HashMap<String, MessageConsumer>();
  private final Map<String, Long> messageCounts = new HashMap<String, Long>();
  private final Map<String, Map<String, Long>> stats = new HashMap<String, Map<String, Long>>();

  private List<DestinationConfig> destinations = new ArrayList<DestinationConfig>();

  private static Log LOG = LogFactory.getLog(ImqAdminFactory.class);

  private final Object destListGuard = new Object();
  private final Object destMetricGuard = new Object();

  public ImqAdmin(Hermes hermes, ConnectionFactory connectionFactory) {
    super(hermes);
    this.connectionFactory = connectionFactory;

    LOG.debug("Building ImqAdmin");

    try {
      connection = this.connectionFactory.createConnection();
      connection.start();
      session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      Topic destListTopic = session.createTopic(DEST_LIST_TOPIC_NAME);
      destListTopicSubscriber = session.createConsumer(destListTopic);
      destListTopicSubscriber.setMessageListener(this);
    } catch (JMSException e) {
      throw new RuntimeException(e);
    }
  }

  @Override
  public Collection<DestinationConfig> discoverDestinationConfigs() throws JMSException {

    LOG.debug("Discovering destination(s)");

    try {
      synchronized (destListGuard) {
        destListGuard.wait();
      }
    } catch (InterruptedException e) {
    }

    LOG.debug("Discovered " + destinations.size() + " destination(s)");

    return destinations;
  }

  @Override
  public int getDepth(DestinationConfig destinationConfig) throws JMSException {
    LOG.debug("Getting depth");

    try {
      subscribeToDestMetricTopic(destinationConfig.getShortName(), destinationConfig.getDomain());

      synchronized (destMetricGuard) {
        destMetricGuard.wait(5000);
      }
    } catch (InterruptedException e) {
    }

    Long result = messageCounts.get(destinationConfig.getShortName());

    LOG.debug("Got depth for " + destinationConfig.getShortName() + ": " + result);

    if (result == null) {
      throw new RuntimeException("Timeout: Got no data from metric topic.");
    }

    clearDestMetricTopicSubscribers();

    return result.intValue();
  }

  @Override
  public Map<String, Long> getStatistics(DestinationConfig destination) throws JMSException {
    LOG.debug("Getting statistics for " + destination);

    try {
      synchronized (destMetricGuard) {
        subscribeToDestMetricTopic(destination.getShortName(), destination.getDomain());

        destMetricGuard.wait(5000);
      }
    } catch (InterruptedException e) {
    }

    Map<String, Long> result = stats.get(destination.getShortName());

    clearDestMetricTopicSubscribers();

    if (result == null) {
      throw new RuntimeException("Timeout: Got no data from metric topic.");
    }

    return result;
  }

  @Override
  public void close() throws JMSException {
    LOG.debug("Closing IMQ Session");
    clearDestMetricTopicSubscribers();
    destListTopicSubscriber.close();
    session.close();
    connection.close();
  }

  @Override
  public void onMessage(Message msg) {

    try {

      MapMessage mapMsg = (MapMessage) msg;
      String type = mapMsg.getStringProperty("type");

      LOG.debug("Got admin message from broker of type: " + type);

      if (type.equals(DEST_LIST_TOPIC_NAME)) {
        List<DestinationConfig> result = new ArrayList<DestinationConfig>();

        for (@SuppressWarnings("unchecked")
        Enumeration e = mapMsg.getMapNames(); e.hasMoreElements();) {
          String name = (String) e.nextElement();

          @SuppressWarnings("unchecked")
          Map<String, String> object = (Map<String, String>) mapMsg.getObject(name);

          DestinationConfig dest = HermesBrowser.getConfigDAO().createDestinationConfig();
          dest.setName(object.get("name"));
          dest.setShortName(object.get("name"));
          dest.setDomain("queue".equals(object.get("type")) ? Domain.QUEUE.getId() : ("topic".equals(object.get("type")) ? Domain.TOPIC.getId() : Domain.UNKNOWN.getId()));

          result.add(dest);
        }

        Collections.sort(result, new Comparator<DestinationConfig>() {
          @Override
          public int compare(DestinationConfig o1, DestinationConfig o2) {
            return o1.getShortName().compareTo(o2.getShortName());
          }
        });

        destinations = result;

        synchronized (destListGuard) {
          destListGuard.notifyAll();
        }

      } else if (type.startsWith(QUEUE_METRICS_TOPIC_PREFIX)) {
        LOG.debug("Got queue metrics: " + type);

        String queueName = type.substring(QUEUE_METRICS_TOPIC_PREFIX.length());
        messageCounts.put(queueName, mapMsg.getLong("numMsgs"));
        HashMap<String, Long> map = new HashMap<String, Long>();

        @SuppressWarnings("unchecked")
        Enumeration<String> e = mapMsg.getMapNames();
        while (e.hasMoreElements()) {
          String name = e.nextElement();
          map.put(name, mapMsg.getLong(name));
        }
        stats.put(queueName, map);
        LOG.debug("Stored stats for: " + queueName);

        synchronized (destMetricGuard) {
          destMetricGuard.notifyAll();
        }

      } else if (type.startsWith(TOPIC_METRICS_TOPIC_PREFIX)) {
        LOG.debug("Got topic metrics: " + type);

        String topicName = type.substring(TOPIC_METRICS_TOPIC_PREFIX.length());
        messageCounts.put(topicName, mapMsg.getLong("numMsgs"));

        HashMap<String, Long> map = new HashMap<String, Long>();

        @SuppressWarnings("unchecked")
        Enumeration<String> e = mapMsg.getMapNames();
        while (e.hasMoreElements()) {
          String name = e.nextElement();
          map.put(name, mapMsg.getLong(name));
        }
        stats.put(topicName, map);
        LOG.debug("Stored stats for: " + topicName);

        synchronized (destMetricGuard) {
          destMetricGuard.notifyAll();
        }
      }

    } catch (JMSException e) {
      throw new RuntimeException(e);
    }
  }

  private MessageConsumer subscribeToDestMetricTopic(String destName, int domain) throws JMSException {
    LOG.debug("Subscribing to " + destName);

    String topicName = null;

    if (domain == Domain.QUEUE.getId()) {
      topicName = QUEUE_METRICS_TOPIC_PREFIX + destName;
    } else if (domain == Domain.TOPIC.getId()) {
      topicName = TOPIC_METRICS_TOPIC_PREFIX + destName;
    }

    Topic destListTopic = session.createTopic(topicName);
    MessageConsumer subscriber = session.createConsumer(destListTopic);
    subscriber.setMessageListener(this);

    LOG.debug("Created subscriber " + subscriber + " listening to " + topicName);
    return subscriber;
  }

  private void clearDestMetricTopicSubscribers() throws JMSException {
    for (MessageConsumer subscriber : destMetricTopicSubscribers.values()) {
      LOG.debug("Closing subscriber: " + subscriber);
      subscriber.close();
    }
    destMetricTopicSubscribers.clear();
  }

}
TOP

Related Classes of hermes.ext.imq.ImqAdmin

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.