/*
* Copyright 2003,2004,2005 Colin Crist
*
* 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.activemq;
import hermes.Domain;
import hermes.Hermes;
import hermes.HermesException;
import hermes.browser.HermesBrowser;
import hermes.config.DestinationConfig;
import hermes.ext.HermesAdminSupport;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import javax.jms.JMSException;
import javax.jms.QueueBrowser;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanInfo;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.log4j.Logger;
/**
* @author colincrist@hermesjms.com
* @version $Id: ActiveMQAdmin.java,v 1.3 2006/07/13 07:35:32 colincrist Exp $
*/
public class ActiveMQAdmin extends HermesAdminSupport implements hermes.HermesAdmin
{
private static final Logger log = Logger.getLogger(ActiveMQAdmin.class);
private JMXServiceURL serviceURL;
private JMXConnector connector;
private MBeanServerConnection server;
private String[] queueProperties = new String[] { "ConsumerCount", "EnqueueCount", "DequeueCount", "MemoryLimit", "MemoryPercentageUsed", "QueueSize" };
private ActiveMQAdminFactory factory;
public ActiveMQAdmin(ActiveMQAdminFactory factory, Hermes hermes, String brokerName, JMXServiceURL serviceURL)
{
super(hermes);
this.serviceURL = serviceURL;
this.factory = factory;
}
@Override
public int getDepth(DestinationConfig destination) throws JMSException
{
try
{
if (destination.getDomain() == Domain.QUEUE.getId())
{
ObjectName objectName = getDestinationObjectName(destination);
return ((Long) getConnection().getAttribute(objectName, "QueueSize")).intValue();
}
else if (destination.getDomain() == Domain.TOPIC.getId() && destination.isDurable())
{
ObjectName objectName = getDestinationObjectName(destination);
return ((Integer) getConnection().getAttribute(objectName, "PendingQueueSize")).intValue();
}
else
{
return 0;
}
}
catch (Exception ex)
{
close();
log.error(ex.getMessage(), ex);
throw new HermesException(ex);
}
}
@Override
public QueueBrowser createDurableSubscriptionBrowser(DestinationConfig dConfig) throws JMSException
{
try
{
/**
* ObjectName objectName = getDestinationObjectName(dConfig);
* TabularData data = (TabularData) getConnection().invoke(objectName,
* "browseAsTable", new Object[] {}, new String[] {});
* log.debug(data.size() + " messages");
*/
return super.createDurableSubscriptionBrowser(dConfig);
}
catch (Exception ex)
{
throw new HermesException(ex);
}
}
public Object getAttributeQuietly(ObjectName objectName, String attribute)
{
try
{
return getConnection().getAttribute(objectName, attribute);
}
catch (Exception e)
{
log.error(e.getMessage(), e);
return e.getMessage();
}
}
@Override
public Collection<DestinationConfig> discoverDestinationConfigs() throws JMSException
{
Collection<DestinationConfig> rval = new HashSet<DestinationConfig>();
try
{
ObjectName[] queues = (ObjectName[]) getConnection().getAttribute(getBrokerObjectName(), "Queues");
for (ObjectName queue : queues)
{
String name = (String) getConnection().getAttribute(queue, "Name");
rval.add(HermesBrowser.getConfigDAO().createDestinationConfig(name, Domain.QUEUE));
}
try
{
ObjectName[] tempQueues = (ObjectName[]) getConnection().getAttribute(getBrokerObjectName(), "TemporaryQueues");
for (ObjectName queue : tempQueues)
{
String name = (String) getConnection().getAttribute(queue, "Name");
rval.add(HermesBrowser.getConfigDAO().createDestinationConfig(name, Domain.QUEUE));
}
}
catch (Exception ex)
{
log.error(ex.getMessage(), ex);
}
ObjectName[] topics = (ObjectName[]) getConnection().getAttribute(getBrokerObjectName(), "Topics");
for (ObjectName topic : topics)
{
String name = (String) getConnection().getAttribute(topic, "Name");
rval.add(HermesBrowser.getConfigDAO().createDestinationConfig(name, Domain.TOPIC));
}
}
catch (Exception ex)
{
throw new HermesException(ex);
}
rval.addAll(_discoverDurableSubscriptions());
return rval;
}
protected Collection<DestinationConfig> _discoverDurableSubscriptions() throws JMSException
{
Collection<DestinationConfig> rval = new HashSet<DestinationConfig>();
try
{
ObjectName[] subs = (ObjectName[]) getConnection().getAttribute(getBrokerObjectName(), "DurableTopicSubscribers");
for (ObjectName sub : subs)
{
String name = (String) getConnection().getAttribute(sub, "DestinationName");
String subscriptionName = (String) getConnection().getAttribute(sub, "SubscriptionName");
DestinationConfig dConfig = HermesBrowser.getConfigDAO().createDestinationConfig(name, Domain.TOPIC);
dConfig.setDurable(true);
dConfig.setClientID(subscriptionName);
rval.add(dConfig);
}
}
catch (Exception e)
{
throw new HermesException(e);
}
try
{
ObjectName[] subs = (ObjectName[]) getConnection().getAttribute(getBrokerObjectName(), "InactiveDurableTopicSubscribers");
for (ObjectName sub : subs)
{
String name = (String) getConnection().getAttribute(sub, "DestinationName");
String subscriptionName = (String) getConnection().getAttribute(sub, "SubscriptionName");
DestinationConfig dConfig = HermesBrowser.getConfigDAO().createDestinationConfig(name, Domain.TOPIC);
dConfig.setDurable(true);
dConfig.setClientID(subscriptionName);
rval.add(dConfig);
}
}
catch (Exception e)
{
throw new HermesException(e);
}
return rval;
}
@Override
public Map getStatistics(DestinationConfig destination) throws JMSException
{
Map<String, Object> rval = new HashMap<String, Object>();
try
{
ObjectName objectName = getDestinationObjectName(destination);
MBeanInfo objectInfo = getConnection().getMBeanInfo(objectName);
for (MBeanAttributeInfo info : objectInfo.getAttributes())
{
Object o = getConnection().getAttribute(objectName, info.getName());
rval.put(info.getName(), o);
}
}
catch (Exception ex)
{
close();
log.error(ex.getMessage(), ex);
throw new HermesException(ex);
}
return rval;
}
/**
* Convert a Hermes destination configuration object into an ActiveMQ JMX
* ObjectName.
*
* @param destination
* @return
* @throws MalformedObjectNameException
* @throws NullPointerException
* @throws JMSException
*/
private ObjectName getDestinationObjectName(DestinationConfig destination) throws MalformedObjectNameException, NullPointerException, JMSException
{
if (destination.getDomain() == Domain.QUEUE.getId())
{
return new ObjectName("org.apache.activemq:BrokerName=" + factory.getBrokerName() + ",Type=Queue,Destination=" + destination.getName());
}
else
{
if (destination.isDurable())
{
try
{
return new ObjectName("org.apache.activemq:BrokerName=" + factory.getBrokerName() + ",Type=Subscription,active=true,name="
+ getHermes().getConnection().getClientID() + "_" + destination.getClientID());
}
catch (MalformedObjectNameException e)
{
return new ObjectName("org.apache.activemq:BrokerName=" + factory.getBrokerName() + ",Type=Subscription,active=false,name="
+ getHermes().getConnection().getClientID() + "_" + destination.getClientID());
}
}
else
{
return new ObjectName("org.apache.activemq:BrokerName=" + factory.getBrokerName() + ",Type=Topic,Destination=" + destination.getName());
}
}
}
private ObjectName getBrokerObjectName() throws MalformedObjectNameException, NullPointerException
{
return new ObjectName("org.apache.activemq:BrokerName=" + factory.getBrokerName() + ",Type=Broker");
}
public synchronized void close() throws JMSException
{
try
{
if (connector != null)
{
connector.close();
log.debug("closed ActiveMQ JMX connection to " + factory.getBrokerName());
}
}
catch (IOException ex)
{
log.error(ex.getMessage(), ex);
}
finally
{
connector = null;
server = null;
}
}
private Map getMap()
{
if (factory.getUsername() == null)
{
return Collections.EMPTY_MAP;
}
else
{
final Map rval = new HashMap();
rval.put("jmx.remote.credentials", new String[] { factory.getUsername(), factory.getPassword() });
return rval;
}
}
private synchronized void connect() throws JMSException
{
close();
try
{
connector = JMXConnectorFactory.connect(serviceURL, getMap());
server = connector.getMBeanServerConnection();
}
catch (Exception ex)
{
throw new HermesException(ex);
}
}
private synchronized MBeanServerConnection getConnection() throws JMSException
{
if (server == null)
{
connect();
}
return server;
}
}