diff options
| author | Robert Gemmell <robbie@apache.org> | 2012-06-28 16:46:12 +0000 |
|---|---|---|
| committer | Robert Gemmell <robbie@apache.org> | 2012-06-28 16:46:12 +0000 |
| commit | 07c285f662e8f60d4e8aca247b65b77ca5df4587 (patch) | |
| tree | 7fe15262589c0fe5206e02a5e9336c6288f004e0 /qpid/java/broker/src/main | |
| parent | bb45ec03f95ffdfa6c0163067dcb75af8b64ceb5 (diff) | |
| download | qpid-python-07c285f662e8f60d4e8aca247b65b77ca5df4587.tar.gz | |
QPID-3998, QPID-3999, QPID-4093: add new management plugins for jmx/rest/webui functionality, partial merge from the java-config-and-management branch at r1355039
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1355072 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/broker/src/main')
128 files changed, 7802 insertions, 6347 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java b/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java index dca62f34b4..79bedb2a7e 100644 --- a/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java +++ b/qpid/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java @@ -26,8 +26,6 @@ import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; -import org.apache.qpid.server.logging.management.LoggingManagementMBean; - import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -65,7 +63,6 @@ public class QpidLog4JConfigurator LOCK.lock(); parseXMLConfigFile(filename); - checkLoggerLevels(filename); DOMConfigurator.configure(filename); @@ -84,7 +81,6 @@ public class QpidLog4JConfigurator SAXException, IllegalLoggerLevelException { parseXMLConfigFile(filename); - checkLoggerLevels(filename); QpidLog4JXMLWatchdog watchdog = new QpidLog4JXMLWatchdog(filename); watchdog.setDelay(delay); @@ -200,23 +196,6 @@ public class QpidLog4JConfigurator return; } - try - { - checkLoggerLevels(filename); - } - catch (Exception e) - { - //logger will be instantiated following first configuration success, which has been pre-validated - //and so the null check should never actually be required. - if(_logger != null) - { - _logger.warn("Errors were found when validating the logger level values in the " + - "log4j XML configuration file. The new configuration was not applied. " + - "Correct the issues to prompt another update attempt: " + e.getMessage()); - } - return; - } - //everything checked was ok, let the normal update process proceed super.doOnChange(); @@ -235,60 +214,7 @@ public class QpidLog4JConfigurator } } - - protected static void checkLoggerLevels(String filename) throws IllegalLoggerLevelException, IOException - { - //check that the logger levels specified in the XML are actually valid - try - { - LOCK.lock(); - - //get the Logger levels to check - Map<String, String> loggersLevels; - loggersLevels = LoggingManagementMBean.retrieveConfigFileLoggersLevels(filename); - //add the RootLogger to the list too - String rootLoggerlevelString = LoggingManagementMBean.retrieveConfigFileRootLoggerLevel(filename); - loggersLevels.put("Root", rootLoggerlevelString); - - - for (Map.Entry<String, String> entry : loggersLevels.entrySet()) - { - String loggerName = entry.getKey(); - String levelString = entry.getValue(); - - //let log4j replace any properties in the string - String log4jConfiguredString = domConfig.subst(levelString); - - if(log4jConfiguredString.equals("") && ! log4jConfiguredString.equals(levelString)) - { - //log4j has returned an empty string but this isnt what we gave it. - //There may have been an undefined property. Unlike an incorrect - //literal value, we will allow this case to proceed, but warn users. - - if(_logger != null) - { - _logger.warn("Unable to detect Level value from '" + levelString - +"' for logger '" + loggerName + "', Log4J will default this to DEBUG"); - } - else - { - System.err.println("Unable to detect Level value from '" + levelString - +"' for logger " + loggerName + ", Log4J will default this to DEBUG"); - } - - continue; - } - - checkLevel(loggerName,log4jConfiguredString); - } - } - finally - { - LOCK.unlock(); - } - } - private static void checkLevel(String loggerName, String levelString) throws IllegalLoggerLevelException { if("null".equalsIgnoreCase(levelString) || "inherited".equalsIgnoreCase(levelString)) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java index 034a4ae53c..0d48aec562 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java @@ -540,6 +540,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener return getMsgReceives(); } + public long getMsgDrops() + { + return 0l; + } + public long getByteReceives() { return _bytesReceived.get(); @@ -550,6 +555,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener return getByteReceives(); } + public long getByteDrops() + { + return 0l; + } + public long getCreateTime() { return _createTime; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java index 787cede2b7..1b173c7e11 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java @@ -21,6 +21,8 @@ package org.apache.qpid.qmf; +import java.util.Collection; +import java.util.Collections; import org.apache.commons.lang.NotImplementedException; import org.apache.qpid.framing.AMQShortString; @@ -111,6 +113,16 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead return 0; } + public String getUserId() + { + return null; + } + + public String getAppId() + { + return null; + } + public String getMessageId() { return null; @@ -166,6 +178,12 @@ public class QMFMessage implements ServerMessage, InboundMessage, AMQMessageHead return false; } + @Override + public Collection<String> getHeaderNames() + { + return Collections.EMPTY_SET; + } + public boolean containsHeader(String name) { return false; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java deleted file mode 100644 index 0f32b98aa8..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java +++ /dev/null @@ -1,410 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeFactory; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.exchange.ExchangeType; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.model.UUIDGenerator; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.AMQQueueMBean; -import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; - -import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.UUID; - -/** - * 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 final QueueRegistry _queueRegistry; - private final ExchangeRegistry _exchangeRegistry; - private final ExchangeFactory _exchangeFactory; - - private final VirtualHostImpl.VirtualHostMBean _virtualHostMBean; - - @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(); - _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(int i=0; i < attributesLength; i++) - { - try - { - attributeValues.add(mbean.getAttribute(attributes[i])); - } - 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(getLogActor().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) - { - getVirtualHost().getMessageStore().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. - - // Check if there are queue-bindings with the exchange and unregister - // when there are no bindings. - CurrentActor.set(new ManagementActor(getLogActor().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) throws JMException, MBeanException - { - createNewQueue(queueName, owner, durable, null); - } - - public void createNewQueue(String queueName, String owner, boolean durable, Map<String,Object> arguments) throws JMException - { - final AMQShortString queueNameAsAMQShortString = new AMQShortString(queueName); - synchronized (_queueRegistry) - { - AMQQueue queue = _queueRegistry.getQueue(queueNameAsAMQShortString); - if (queue != null) - { - throw new JMException("The queue \"" + queueName + "\" already exists."); - } - - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - FieldTable args = null; - if(arguments != null) - { - args = FieldTable.convertToFieldTable(arguments); - } - final VirtualHost virtualHost = getVirtualHost(); - - queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), queueName, durable, owner, - false, false, getVirtualHost(), arguments); - if (queue.isDurable() && !queue.isAutoDelete()) - { - getVirtualHost().getMessageStore().createQueue(queue, args); - } - - virtualHost.getBindingFactory().addBinding(queueName, queue, _exchangeRegistry.getDefaultExchange(), null); - } - catch (AMQException ex) - { - JMException jme = new JMException(ex.toString()); - throw new MBeanException(jme, "Error in creating queue " + queueName); - } - 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(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."); - } - - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - queue.delete(); - if (queue.isDurable()) - { - getVirtualHost().getMessageStore().removeQueue(queue); - } - } - catch (AMQException ex) - { - JMException jme = new JMException(ex.toString()); - throw new MBeanException(jme, "Error in deleting queue " + queueName); - } - 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(); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java index 4fd4e02220..030fd3f499 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java @@ -140,7 +140,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm private UnacknowledgedMessageMap _unacknowledgedMessageMap = new UnacknowledgedMessageMapImpl(DEFAULT_PREFETCH); - // Set of messages being acknoweledged in the current transaction + // Set of messages being acknowledged in the current transaction private SortedSet<QueueEntry> _acknowledgedMessages = new TreeSet<QueueEntry>(); private final AtomicBoolean _suspended = new AtomicBoolean(false); @@ -263,6 +263,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm return _txnCount.get(); } + public Long getTxnStart() + { + return _txnStarts.get(); + } + public int getChannelId() { return _channelId; @@ -440,7 +445,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm * @param acks Are acks enabled for this subscriber * @param filters Filters to apply to this subscriber * - * @param noLocal Flag stopping own messages being receivied. + * @param noLocal Flag stopping own messages being received. * @param exclusive Flag requesting exclusive access to the queue * @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests * @@ -1417,6 +1422,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm return false; } + public int getUnacknowledgedMessageCount() + { + return getUnacknowledgedMessageMap().size(); + } + private void flow(boolean flow) { MethodRegistry methodRegistry = _session.getMethodRegistry(); @@ -1424,6 +1434,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm _session.writeFrame(responseBody.generateFrame(_channelId)); } + @Override public boolean getBlocking() { return _blocking.get(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java index 90603777d1..c843ce6a23 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/Broker.java @@ -25,24 +25,17 @@ import java.io.IOException; import java.io.InputStream; import java.net.InetAddress; import java.net.InetSocketAddress; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Properties; -import java.util.Set; +import java.util.*; import javax.net.ssl.SSLContext; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; import org.apache.log4j.xml.QpidLog4JConfigurator; import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.configuration.ServerNetworkTransportConfiguration; -import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean; -import org.apache.qpid.server.information.management.ServerInformationMBean; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.GenericActor; -import org.apache.qpid.server.logging.management.LoggingManagementMBean; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.protocol.AmqpProtocolVersion; import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; @@ -118,6 +111,14 @@ public class Broker ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile, options.getBundleContext()); ServerConfiguration serverConfig = config.getConfiguration(); + if (options.getQpidWork() != null) + { + serverConfig.setQpidWork(options.getQpidWork()); + } + if (options.getQpidHome() != null) + { + serverConfig.setQpidHome(options.getQpidHome()); + } updateManagementPorts(serverConfig, options.getJmxPortRegistryServer(), options.getJmxPortConnectorServer()); ApplicationRegistry.initialise(config); @@ -135,14 +136,6 @@ public class Broker try { - configureLoggingManagementMBean(logConfigFile, options.getLogWatchFrequency()); - - ConfigurationManagementMBean configMBean = new ConfigurationManagementMBean(); - configMBean.register(); - - ServerInformationMBean sysInfoMBean = new ServerInformationMBean(config); - sysInfoMBean.register(); - Set<Integer> ports = new HashSet<Integer>(options.getPorts()); if(ports.isEmpty()) { @@ -258,7 +251,7 @@ public class Broker transport.accept(settings, protocolEngineFactory, null); ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress, - new QpidAcceptor(transport,"TCP")); + new QpidAcceptor(transport,QpidAcceptor.Transport.TCP, supported)); CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port)); } } @@ -302,7 +295,7 @@ public class Broker transport.accept(settings, protocolEngineFactory, sslContext); ApplicationRegistry.getInstance().addAcceptor(inetSocketAddress, - new QpidAcceptor(transport,"TCP")); + new QpidAcceptor(transport,QpidAcceptor.Transport.SSL, supported)); CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", sslPort)); } } @@ -495,12 +488,6 @@ public class Broker } } - private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception - { - LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime); - - blm.register(); - } private void addShutdownHook() { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java index cec614881d..434d40d557 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java @@ -33,6 +33,7 @@ public class BrokerOptions public static final String DEFAULT_CONFIG_FILE = "etc/config.xml"; public static final String DEFAULT_LOG_CONFIG_FILE = "etc/log4j.xml"; public static final String QPID_HOME = "QPID_HOME"; + public static final String QPID_WORK = "QPID_WORK"; private final Set<Integer> _ports = new HashSet<Integer>(); private final Set<Integer> _sslPorts = new HashSet<Integer>(); @@ -47,6 +48,8 @@ public class BrokerOptions private BundleContext _bundleContext; private Integer _logWatchFrequency = 0; + private String _qpidWorkFolder; + private String _qpidHomeFolder; public void addPort(final int port) { @@ -109,7 +112,7 @@ public class BrokerOptions } public String getQpidHome() { - return System.getProperty(QPID_HOME); + return _qpidHomeFolder == null? System.getProperty(QPID_HOME): _qpidHomeFolder; } public Set<Integer> getExcludedPorts(final ProtocolExclusion excludeProtocol) @@ -179,4 +182,19 @@ public class BrokerOptions Set<Integer> ports = _inclusionMap.get(includeProtocol); ports.add(port); } + + public String getQpidWork() + { + return _qpidWorkFolder; + } + + public void setQpidWork(String qpidWorkFolder) + { + _qpidWorkFolder = qpidWorkFolder; + } + + public void setQpidHome(String qpidHomeFolder) + { + _qpidHomeFolder = qpidHomeFolder; + } }
\ No newline at end of file diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java index 41c51d9684..6633d93adf 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java @@ -49,7 +49,12 @@ public interface ExchangeConfig extends ConfiguredObject<ExchangeConfigType, Exc long getMsgRoutes(); + long getMsgDrops(); + long getByteReceives(); long getByteRoutes(); + + long getByteDrops(); + }
\ No newline at end of file diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java index 40bafb4275..8f03383777 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java @@ -126,6 +126,11 @@ public class QueueConfiguration extends ConfigurationPlugin return _name; } + public String getDescription() + { + return getStringValue("description"); + } + public int getMaximumMessageAge() { return getIntValue("maximumMessageAge", _vHostConfig.getMaximumMessageAge()); @@ -226,4 +231,5 @@ public class QueueConfiguration extends ConfigurationPlugin } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index b48d8c5fdb..c23e58fdab 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -64,6 +64,7 @@ public class ServerConfiguration extends ConfigurationPlugin public static final long DEFAULT_HOUSEKEEPING_PERIOD = 30000L; public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999; public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100; + public static final int DEFAULT_HTTP_MANAGEMENT_PORT = 8080; public static final String QPID_HOME = "QPID_HOME"; public static final String QPID_WORK = "QPID_WORK"; @@ -75,6 +76,8 @@ public class ServerConfiguration extends ConfigurationPlugin private File _configFile; private File _vhostsFile; + private String _qpidWork; + private String _qpidHome; // Map of environment variables to config items private static final Map<String, String> envVarMap = new HashMap<String, String>(); @@ -110,6 +113,8 @@ public class ServerConfiguration extends ConfigurationPlugin envVarMap.put("QPID_MSGAUTH", "security.msg-auth"); envVarMap.put("QPID_AUTOREGISTER", "auto_register"); envVarMap.put("QPID_MANAGEMENTENABLED", "management.enabled"); + envVarMap.put("QPID_HTTPMANAGEMENTENABLED", "management.http.enabled"); + envVarMap.put("QPID_HTTPMANAGEMENTPORT", "management.http.port"); envVarMap.put("QPID_HEARTBEATDELAY", "heartbeat.delay"); envVarMap.put("QPID_HEARTBEATTIMEOUTFACTOR", "heartbeat.timeoutFactor"); envVarMap.put("QPID_MAXIMUMMESSAGEAGE", "maximumMessageAge"); @@ -511,12 +516,26 @@ public class ServerConfiguration extends ConfigurationPlugin public String getQpidWork() { - return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir")); + if ( _qpidWork == null ) + { + return System.getProperty(QPID_WORK, System.getProperty("java.io.tmpdir")); + } + else + { + return _qpidWork; + } } public String getQpidHome() { - return System.getProperty(QPID_HOME); + if ( _qpidHome == null ) + { + return System.getProperty(QPID_HOME); + } + else + { + return _qpidHome; + } } public void setJMXPortRegistryServer(int registryServerPort) @@ -554,6 +573,16 @@ public class ServerConfiguration extends ConfigurationPlugin return getBooleanValue("management.platform-mbeanserver", true); } + public boolean getHTTPManagementEnabled() + { + return getBooleanValue("management.http.enabled", true); + } + + public int getHTTPManagementPort() + { + return getIntValue("management.http.port", 8080); + } + public String[] getVirtualHosts() { return _virtualHosts.keySet().toArray(new String[_virtualHosts.size()]); @@ -622,7 +651,7 @@ public class ServerConfiguration extends ConfigurationPlugin public boolean getManagementSSLEnabled() { - return getBooleanValue("management.ssl.enabled", true); + return getBooleanValue("management.ssl.enabled", false); } public String getManagementKeyStorePassword() @@ -636,16 +665,11 @@ public class ServerConfiguration extends ConfigurationPlugin return getBooleanValue("queue.auto_register", true); } - public boolean getManagementEnabled() + public boolean getJMXManagementEnabled() { return getBooleanValue("management.enabled", true); } - public void setManagementEnabled(boolean enabled) - { - getConfig().setProperty("management.enabled", enabled); - } - public int getHeartBeatDelay() { return getIntValue("heartbeat.delay", 5); @@ -981,4 +1005,14 @@ public class ServerConfiguration extends ConfigurationPlugin return reply == null ? null : AmqpProtocolVersion.valueOf(reply); } + + public void setQpidWork(String path) + { + _qpidWork = path; + } + + public void setQpidHome(String path) + { + _qpidHome = path; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java deleted file mode 100644 index f0ca5dc139..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.configuration.management; - -import org.apache.qpid.management.common.mbeans.ConfigurationManagement; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import javax.management.NotCompliantMBeanException; - -public class ConfigurationManagementMBean extends AMQManagedObject implements ConfigurationManagement -{ - - public ConfigurationManagementMBean() throws NotCompliantMBeanException - { - super(ConfigurationManagement.class, ConfigurationManagement.TYPE); - } - - public String getObjectInstanceName() - { - return ConfigurationManagement.TYPE; - } - - public void reloadSecurityConfiguration() throws Exception - { - ApplicationRegistry.getInstance().getConfiguration().reparseConfigFileSecuritySections(); - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java index a539743081..451754e6d8 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java @@ -88,6 +88,13 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable } } } + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.connectionRegistered(connnection); + } + } } public void deregisterConnection(AMQConnectionModel connnection) @@ -104,6 +111,14 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable } } } + + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.connectionUnregistered(connnection); + } + } } public void addRegistryChangeListener(RegistryChangeListener listener) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index 9493f400f2..e633ddd341 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -30,15 +30,12 @@ import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.ExchangeMessages; import org.apache.qpid.server.logging.subjects.ExchangeLogSubject; -import org.apache.qpid.server.management.Managable; -import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; -import javax.management.JMException; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -50,10 +47,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -public abstract class AbstractExchange implements Exchange, Managable +public abstract class AbstractExchange implements Exchange { - - private AMQShortString _name; private final AtomicBoolean _closed = new AtomicBoolean(); @@ -66,9 +61,6 @@ public abstract class AbstractExchange implements Exchange, Managable private final List<Exchange.Task> _closeTaskList = new CopyOnWriteArrayList<Exchange.Task>(); - - private AbstractExchangeMBean _exchangeMbean; - /** * Whether the exchange is automatically deleted once all queues have detached from it */ @@ -86,6 +78,8 @@ public abstract class AbstractExchange implements Exchange, Managable private final AtomicLong _receivedMessageSize = new AtomicLong(); private final AtomicLong _routedMessageCount = new AtomicLong(); private final AtomicLong _routedMessageSize = new AtomicLong(); + private final AtomicLong _droppedMessageCount = new AtomicLong(); + private final AtomicLong _droppedMessageSize = new AtomicLong(); private final CopyOnWriteArrayList<Exchange.BindingListener> _listeners = new CopyOnWriteArrayList<Exchange.BindingListener>(); @@ -107,13 +101,6 @@ public abstract class AbstractExchange implements Exchange, Managable return _type.getName(); } - /** - * Concrete exchanges must implement this method in order to create the managed representation. This is - * called during initialisation (template method pattern). - * @return the MBean - */ - protected abstract AbstractExchangeMBean createMBean() throws JMException; - public void initialise(UUID id, VirtualHost host, AMQShortString name, boolean durable, int ticket, boolean autoDelete) throws AMQException { @@ -126,26 +113,12 @@ public abstract class AbstractExchange implements Exchange, Managable _id = id; getConfigStore().addConfiguredObject(this); - createAndRegisterMBean(); _logSubject = new ExchangeLogSubject(this, this.getVirtualHost()); // Log Exchange creation CurrentActor.get().message(ExchangeMessages.CREATED(String.valueOf(getTypeShortString()), String.valueOf(name), durable)); } - private void createAndRegisterMBean() - { - try - { - _exchangeMbean = createMBean(); - _exchangeMbean.register(); - } - catch (JMException e) - { - throw new RuntimeException("Failed to register mbean",e); - } - } - public ConfigStore getConfigStore() { return getVirtualHost().getConfigStore(); @@ -171,10 +144,6 @@ public abstract class AbstractExchange implements Exchange, Managable if(_closed.compareAndSet(false,true)) { - if (_exchangeMbean != null) - { - _exchangeMbean.unregister(); - } getConfigStore().removeConfiguredObject(this); if(_alternateExchange != null) { @@ -196,11 +165,6 @@ public abstract class AbstractExchange implements Exchange, Managable return getClass().getSimpleName() + "[" + getNameShortString() +"]"; } - public ManagedObject getManagedObject() - { - return _exchangeMbean; - } - public VirtualHost getVirtualHost() { return _virtualHost; @@ -359,6 +323,11 @@ public abstract class AbstractExchange implements Exchange, Managable _routedMessageCount.incrementAndGet(); _routedMessageSize.addAndGet(message.getSize()); } + else + { + _droppedMessageCount.incrementAndGet(); + _droppedMessageSize.addAndGet(message.getSize()); + } return queues; } @@ -374,6 +343,11 @@ public abstract class AbstractExchange implements Exchange, Managable return _routedMessageCount.get(); } + public long getMsgDrops() + { + return _droppedMessageCount.get(); + } + public long getByteReceives() { return _receivedMessageSize.get(); @@ -384,6 +358,11 @@ public abstract class AbstractExchange implements Exchange, Managable return _routedMessageSize.get(); } + public long getByteDrops() + { + return _droppedMessageSize.get(); + } + public long getCreateTime() { return _createTime; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java deleted file mode 100644 index 034331abd9..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.exchange; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.ManagedExchange; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.management.ManagedObjectRegistry; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import javax.management.openmbean.ArrayType; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularType; -import java.util.Collections; - - -/** - * Abstract MBean class. This has some of the methods implemented from - * management intrerface for exchanges. Any implementaion of an - * Exchange MBean should extend this class. - */ -public abstract class AbstractExchangeMBean<T extends AbstractExchange> extends AMQManagedObject implements ManagedExchange -{ - // open mbean data types for representing exchange bindings - private OpenType[] _bindingItemTypes; - private CompositeType _bindingDataType; - private TabularType _bindinglistDataType; - - - private T _exchange; - - public AbstractExchangeMBean(final T abstractExchange) throws NotCompliantMBeanException - { - super(ManagedExchange.class, ManagedExchange.TYPE); - _exchange = abstractExchange; - } - - protected void init() throws OpenDataException - { - _bindingItemTypes = new OpenType[2]; - _bindingItemTypes[0] = SimpleType.STRING; - _bindingItemTypes[1] = new ArrayType(1, SimpleType.STRING); - _bindingDataType = new CompositeType("Exchange Binding", "Binding key and Queue names", - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), _bindingItemTypes); - _bindinglistDataType = new TabularType("Exchange Bindings", "Exchange Bindings for " + getName(), - _bindingDataType, TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); - } - - public ManagedObject getParentObject() - { - return _exchange.getVirtualHost().getManagedObject(); - } - - public T getExchange() - { - return _exchange; - } - - - public String getObjectInstanceName() - { - return ObjectName.quote(_exchange.getName()); - } - - public String getName() - { - return _exchange.getName(); - } - - public String getExchangeType() - { - return _exchange.getTypeShortString().toString(); - } - - public Integer getTicketNo() - { - return _exchange.getTicket(); - } - - public boolean isDurable() - { - return _exchange.isDurable(); - } - - public boolean isAutoDelete() - { - return _exchange.isAutoDelete(); - } - - // Added exchangetype in the object name lets maangement apps to do any customization required - public ObjectName getObjectName() throws MalformedObjectNameException - { - String objNameString = super.getObjectName().toString(); - objNameString = objNameString + ",ExchangeType=" + getExchangeType(); - return new ObjectName(objNameString); - } - - protected ManagedObjectRegistry getManagedObjectRegistry() - { - return ApplicationRegistry.getInstance().getManagedObjectRegistry(); - } - - public void createNewBinding(String queueName, String binding) throws JMException - { - VirtualHost vhost = getExchange().getVirtualHost(); - AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName)); - if (queue == null) - { - throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost."); - } - - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - vhost.getBindingFactory().addBinding(binding,queue,getExchange(),null); - } - catch (AMQException ex) - { - JMException jme = new JMException(ex.toString()); - throw new MBeanException(jme, "Error creating new binding " + binding); - } - CurrentActor.remove(); - } - - /** - * Removes a queue binding from the exchange. - * - * @see org.apache.qpid.server.binding.BindingFactory#removeBinding(String, AMQQueue, Exchange, java.util.Map) - */ - public void removeBinding(String queueName, String binding) throws JMException - { - VirtualHost vhost = getExchange().getVirtualHost(); - AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName)); - if (queue == null) - { - throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost."); - } - - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - vhost.getBindingFactory().removeBinding(binding, queue, _exchange, Collections.<String, Object>emptyMap()); - } - catch (AMQException ex) - { - JMException jme = new JMException(ex.toString()); - throw new MBeanException(jme, "Error removing binding " + binding); - } - CurrentActor.remove(); - } - - - protected OpenType[] getBindingItemTypes() - { - return _bindingItemTypes; - } - - protected void setBindingItemTypes(OpenType[] bindingItemTypes) - { - _bindingItemTypes = bindingItemTypes; - } - - protected CompositeType getBindingDataType() - { - return _bindingDataType; - } - - protected void setBindingDataType(CompositeType bindingDataType) - { - _bindingDataType = bindingDataType; - } - - protected TabularType getBindinglistDataType() - { - return _bindinglistDataType; - } - - protected void setBindinglistDataType(TabularType bindinglistDataType) - { - _bindinglistDataType = bindinglistDataType; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java index bf4184bf0b..baf9cc3d09 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java @@ -29,7 +29,9 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.store.DurableConfigurationStore; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -46,6 +48,8 @@ public class DefaultExchangeRegistry implements ExchangeRegistry private Exchange _defaultExchange; private VirtualHost _host; + private final Collection<RegistryChangeListener> _listeners = + Collections.synchronizedCollection(new ArrayList<RegistryChangeListener>()); public DefaultExchangeRegistry(VirtualHost host) { @@ -68,6 +72,14 @@ public class DefaultExchangeRegistry implements ExchangeRegistry { _exchangeMap.put(exchange.getNameShortString(), exchange); _exchangeMapStr.put(exchange.getNameShortString().toString(), exchange); + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.exchangeRegistered(exchange); + } + + } } public void setDefaultExchange(Exchange exchange) @@ -114,6 +126,15 @@ public class DefaultExchangeRegistry implements ExchangeRegistry getDurableConfigurationStore().removeExchange(e); } e.close(); + + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.exchangeUnregistered(exchange); + } + } + } else { @@ -126,6 +147,16 @@ public class DefaultExchangeRegistry implements ExchangeRegistry unregisterExchange(new AMQShortString(name), inUse); } + public Collection<Exchange> getExchanges() + { + return new ArrayList<Exchange>(_exchangeMap.values()); + } + + public void addRegistryChangeListener(RegistryChangeListener listener) + { + _listeners.add(listener); + } + public Exchange getExchange(AMQShortString name) { if ((name == null) || name.length() == 0) @@ -158,16 +189,14 @@ public class DefaultExchangeRegistry implements ExchangeRegistry { final Exchange exchange = getExchange(exchangeName); - if (exchange instanceof AbstractExchange) + //TODO: this is a bit of a hack, what if the listeners aren't aware + //that we are just unregistering the MBean because of HA, and aren't + //actually removing the exchange as such. + synchronized (_listeners) { - AbstractExchange abstractExchange = (AbstractExchange) exchange; - try - { - abstractExchange.getManagedObject().unregister(); - } - catch (AMQException e) + for(RegistryChangeListener listener : _listeners) { - LOGGER.warn("Failed to unregister mbean", e); + listener.exchangeUnregistered(exchange); } } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index af9322764a..92326412c1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java @@ -127,11 +127,6 @@ public class DirectExchange extends AbstractExchange super(TYPE); } - protected AbstractExchangeMBean createMBean() throws JMException - { - return new DirectExchangeMBean(this); - } - public List<? extends BaseQueue> doRoute(InboundMessage payload) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java deleted file mode 100644 index 0bfaf7035d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.exchange; - -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.binding.Binding; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * MBean class implementing the management interfaces. - */ -@MBeanDescription("Management Bean for Direct Exchange") -final class DirectExchangeMBean extends AbstractExchangeMBean<DirectExchange> -{ - @MBeanConstructor("Creates an MBean for AMQ direct exchange") - public DirectExchangeMBean(final DirectExchange exchange) throws JMException - { - super(exchange); - - init(); - } - - public TabularData bindings() throws OpenDataException - { - TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType()); - - Map<String, List<String>> bindingMap = new HashMap<String, List<String>>(); - - for (Binding binding : getExchange().getBindings()) - { - String key = binding.getBindingKey(); - List<String> queueList = bindingMap.get(key); - if(queueList == null) - { - queueList = new ArrayList<String>(); - bindingMap.put(key, queueList); - } - queueList.add(binding.getQueue().getNameShortString().toString()); - - } - - for(Map.Entry<String, List<String>> entry : bindingMap.entrySet()) - { - Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[0])}; - CompositeData bindingData = new CompositeDataSupport(getBindingDataType(), - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - bindingItemValues); - bindingList.put(bindingData); - } - - return bindingList; - } - - - -}// End of MBean class diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java index 795ae2e140..692a2b2b0d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java @@ -7,9 +7,9 @@ * 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 @@ -57,4 +57,14 @@ public interface ExchangeRegistry void clearAndUnregisterMbeans(); Exchange getExchange(UUID exchangeId); + + Collection<Exchange> getExchanges(); + + void addRegistryChangeListener(RegistryChangeListener listener); + + interface RegistryChangeListener + { + void exchangeRegistered(Exchange exchange); + void exchangeUnregistered(Exchange exchange); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java index 5ebcfd095f..5f4998f77f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java @@ -48,11 +48,6 @@ public class FanoutExchange extends AbstractExchange */ private final ConcurrentHashMap<AMQQueue,Integer> _queues = new ConcurrentHashMap<AMQQueue,Integer>(); - protected AbstractExchangeMBean createMBean() throws JMException - { - return new FanoutExchangeMBean(this); - } - public static final ExchangeType<FanoutExchange> TYPE = new ExchangeType<FanoutExchange>() { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java deleted file mode 100644 index 61e23c896c..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.exchange; - -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.binding.Binding; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import java.util.ArrayList; - -/** - * MBean class implementing the management interfaces. - */ -@MBeanDescription("Management Bean for Fanout Exchange") -final class FanoutExchangeMBean extends AbstractExchangeMBean<FanoutExchange> -{ - private static final String BINDING_KEY_SUBSTITUTE = "*"; - - @MBeanConstructor("Creates an MBean for AMQ fanout exchange") - public FanoutExchangeMBean(final FanoutExchange exchange) throws JMException - { - super(exchange); - init(); - } - - public TabularData bindings() throws OpenDataException - { - - TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType()); - - - ArrayList<String> queueNames = new ArrayList<String>(); - - for (Binding binding : getExchange().getBindings()) - { - String queueName = binding.getQueue().getNameShortString().toString(); - queueNames.add(queueName); - } - - Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])}; - CompositeData bindingData = new CompositeDataSupport(getBindingDataType(), - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - bindingItemValues); - bindingList.put(bindingData); - - return bindingList; - } - - -} // End of MBean class diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index 16ba3c0431..6bad59c2ae 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java @@ -227,11 +227,6 @@ public class HeadersExchange extends AbstractExchange return !getBindings().isEmpty(); } - protected AbstractExchangeMBean createMBean() throws JMException - { - return new HeadersExchangeMBean(this); - } - protected void onBind(final Binding binding) { String bindingKey = binding.getBindingKey(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java deleted file mode 100644 index 395c6c8a91..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.exchange; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.openmbean.ArrayType; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import javax.management.openmbean.TabularType; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * HeadersExchangeMBean class implements the management interface for the - * Header Exchanges. - */ -@MBeanDescription("Management Bean for Headers Exchange") -final class HeadersExchangeMBean extends AbstractExchangeMBean<HeadersExchange> -{ - - @MBeanConstructor("Creates an MBean for AMQ Headers exchange") - public HeadersExchangeMBean(final HeadersExchange headersExchange) throws JMException - { - super(headersExchange); - init(); - } - - /** - * initialises the OpenType objects. - */ - protected void init() throws OpenDataException - { - - setBindingItemTypes(new OpenType[3]); - getBindingItemTypes()[0] = SimpleType.INTEGER; - getBindingItemTypes()[1] = SimpleType.STRING; - getBindingItemTypes()[2] = new ArrayType(1, SimpleType.STRING); - setBindingDataType(new CompositeType("Exchange Binding", "Queue name and header bindings", - HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]), - HEADERS_COMPOSITE_ITEM_DESC.toArray(new String[HEADERS_COMPOSITE_ITEM_DESC.size()]), getBindingItemTypes())); - setBindinglistDataType(new TabularType("Exchange Bindings", "List of exchange bindings for " + getName(), - getBindingDataType(), HEADERS_TABULAR_UNIQUE_INDEX.toArray(new String[HEADERS_TABULAR_UNIQUE_INDEX.size()]))); - } - - public TabularData bindings() throws OpenDataException - { - TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType()); - int count = 1; - for (Binding binding : getExchange().getBindings()) - { - - String queueName = binding.getQueue().getNameShortString().toString(); - - - Map<String,Object> headerMappings = binding.getArguments(); - final List<String> mappingList = new ArrayList<String>(); - - if(headerMappings != null) - { - for(Map.Entry<String,Object> entry : headerMappings.entrySet()) - { - - mappingList.add(entry.getKey() + "=" + entry.getValue()); - } - } - - - Object[] bindingItemValues = {count++, queueName, mappingList.toArray(new String[0])}; - CompositeData bindingData = new CompositeDataSupport(getBindingDataType(), - HEADERS_COMPOSITE_ITEM_NAMES.toArray(new String[HEADERS_COMPOSITE_ITEM_NAMES.size()]), bindingItemValues); - bindingList.put(bindingData); - } - - return bindingList; - } - - @Override - public void createNewBinding(String queueName, String binding) throws JMException - { - VirtualHost vhost = getExchange().getVirtualHost(); - AMQQueue queue = vhost.getQueueRegistry().getQueue(new AMQShortString(queueName)); - if (queue == null) - { - throw new JMException("Queue \"" + queueName + "\" is not registered with the virtualhost."); - } - - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - - final Map<String,Object> arguments = new HashMap<String, Object>(); - final String[] bindings = binding.split(","); - for (int i = 0; i < bindings.length; i++) - { - final String[] keyAndValue = bindings[i].split("="); - if (keyAndValue == null || keyAndValue.length == 0 || keyAndValue.length > 2 || keyAndValue[0].length() == 0) - { - throw new JMException("Format for headers binding should be \"<attribute1>=<value1>,<attribute2>=<value2>\" "); - } - - if(keyAndValue.length == 1) - { - //no value was given, only a key. Use an empty value to signal match on key presence alone - arguments.put(keyAndValue[0], ""); - } - else - { - arguments.put(keyAndValue[0], keyAndValue[1]); - } - } - try - { - vhost.getBindingFactory().addBinding(binding,queue,getExchange(),arguments); - } - catch (AMQException ex) - { - JMException jme = new JMException(ex.toString()); - throw new MBeanException(jme, "Error creating new binding " + binding); - } - CurrentActor.remove(); - } - -} // End of MBean class diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index 7ea7a41826..480d4e4215 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -403,11 +403,6 @@ public class TopicExchange extends AbstractExchange } } - protected AbstractExchangeMBean createMBean() throws JMException - { - return new TopicExchangeMBean(this); - } - private Collection<AMQQueue> getMatchedQueues(InboundMessage message, AMQShortString routingKey) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java deleted file mode 100644 index 481a377fc4..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.exchange; - -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.binding.Binding; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** TopicExchangeMBean class implements the management interface for the Topic exchanges. */ -@MBeanDescription("Management Bean for Topic Exchange") -final class TopicExchangeMBean extends AbstractExchangeMBean<TopicExchange> -{ - private TopicExchange _topicExchange; - - @MBeanConstructor("Creates an MBean for AMQ topic exchange") - public TopicExchangeMBean(final TopicExchange topicExchange) throws JMException - { - super(topicExchange); - init(); - } - - /** returns exchange bindings in tabular form */ - public TabularData bindings() throws OpenDataException - { - TabularDataSupport bindingList = new TabularDataSupport(getBindinglistDataType()); - Map<String, List<String>> bindingData = new HashMap<String, List<String>>(); - for (Binding binding : getExchange().getBindings()) - { - String key = binding.getBindingKey(); - List<String> queueNames = bindingData.get(key); - if(queueNames == null) - { - queueNames = new ArrayList<String>(); - bindingData.put(key, queueNames); - } - queueNames.add(binding.getQueue().getNameShortString().toString()); - - } - for(Map.Entry<String, List<String>> entry : bindingData.entrySet()) - { - Object[] bindingItemValues = {entry.getKey(), entry.getValue().toArray(new String[entry.getValue().size()]) }; - CompositeData bindingCompositeData = - new CompositeDataSupport(getBindingDataType(), - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - bindingItemValues); - bindingList.put(bindingCompositeData); - } - - return bindingList; - } - -} // End of MBean class diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java deleted file mode 100644 index 4d395f625a..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.information.management; - -import org.apache.qpid.common.QpidProperties; -import org.apache.qpid.management.common.mbeans.ServerInformation; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.registry.ApplicationRegistry; - -import javax.management.JMException; -import java.io.IOException; - -/** MBean class for the ServerInformationMBean. */ -@MBeanDescription("Server Information Interface") -public class ServerInformationMBean extends AMQManagedObject implements ServerInformation -{ - private String buildVersion; - private String productVersion; - private ApplicationRegistry registry; - - public ServerInformationMBean(ApplicationRegistry applicationRegistry) throws JMException - { - super(ServerInformation.class, ServerInformation.TYPE); - - registry = applicationRegistry; - buildVersion = QpidProperties.getBuildVersion(); - productVersion = QpidProperties.getReleaseVersion(); - } - - public String getObjectInstanceName() - { - return ServerInformation.TYPE; - } - - public Integer getManagementApiMajorVersion() throws IOException - { - return QPID_JMX_API_MAJOR_VERSION; - } - - public Integer getManagementApiMinorVersion() throws IOException - { - return QPID_JMX_API_MINOR_VERSION; - } - - public String getBuildVersion() throws IOException - { - return buildVersion; - } - - public String getProductVersion() throws IOException - { - return productVersion; - } - - - public void resetStatistics() throws Exception - { - registry.resetStatistics(); - } - - public double getPeakMessageDeliveryRate() - { - return registry.getMessageDeliveryStatistics().getPeak(); - } - - public double getPeakDataDeliveryRate() - { - return registry.getDataDeliveryStatistics().getPeak(); - } - - public double getMessageDeliveryRate() - { - return registry.getMessageDeliveryStatistics().getRate(); - } - - public double getDataDeliveryRate() - { - return registry.getDataDeliveryStatistics().getRate(); - } - - public long getTotalMessagesDelivered() - { - return registry.getMessageDeliveryStatistics().getTotal(); - } - - public long getTotalDataDelivered() - { - return registry.getDataDeliveryStatistics().getTotal(); - } - - public double getPeakMessageReceiptRate() - { - return registry.getMessageReceiptStatistics().getPeak(); - } - - public double getPeakDataReceiptRate() - { - return registry.getDataReceiptStatistics().getPeak(); - } - - public double getMessageReceiptRate() - { - return registry.getMessageReceiptStatistics().getRate(); - } - - public double getDataReceiptRate() - { - return registry.getDataReceiptStatistics().getRate(); - } - - public long getTotalMessagesReceived() - { - return registry.getMessageReceiptStatistics().getTotal(); - } - - public long getTotalDataReceived() - { - return registry.getDataReceiptStatistics().getTotal(); - } - - public boolean isStatisticsEnabled() - { - return registry.isStatisticsEnabled(); - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java new file mode 100644 index 0000000000..a1065319d3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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.apache.qpid.server.logging; + +import java.util.Iterator; +import org.apache.log4j.Appender; +import org.apache.log4j.Layout; +import org.apache.log4j.Logger; +import org.apache.log4j.spi.ErrorHandler; +import org.apache.log4j.spi.Filter; +import org.apache.log4j.spi.LoggingEvent; + +public class LogRecorder implements Appender, Iterable<LogRecorder.Record> +{ + private ErrorHandler _errorHandler; + private Filter _filter; + private String _name; + private long _recordId; + + private final int _bufferSize = 4096; + private final int _mask = _bufferSize - 1; + private Record[] _records = new Record[_bufferSize]; + + + public static class Record + { + private final long _id; + private final String _logger; + private final long _timestamp; + private final String _threadName; + private final String _level; + private final String _message; + + + public Record(long id, LoggingEvent event) + { + _id = id; + _logger = event.getLoggerName(); + _timestamp = event.timeStamp; + _threadName = event.getThreadName(); + _level = event.getLevel().toString(); + _message = event.getRenderedMessage(); + } + + public long getId() + { + return _id; + } + + public long getTimestamp() + { + return _timestamp; + } + + public String getThreadName() + { + return _threadName; + } + + public String getLevel() + { + return _level; + } + + public String getMessage() + { + return _message; + } + + public String getLogger() + { + return _logger; + } + } + + public LogRecorder() + { + + Logger.getRootLogger().addAppender(this); + } + + @Override + public void addFilter(Filter filter) + { + _filter = filter; + } + + @Override + public void clearFilters() + { + _filter = null; + } + + @Override + public void close() + { + //TODO - Implement + } + + @Override + public synchronized void doAppend(LoggingEvent loggingEvent) + { + _records[((int) (_recordId & _mask))] = new Record(_recordId, loggingEvent); + _recordId++; + } + + @Override + public ErrorHandler getErrorHandler() + { + return _errorHandler; + } + + @Override + public Filter getFilter() + { + return _filter; + } + + @Override + public Layout getLayout() + { + return null; + } + + @Override + public String getName() + { + return _name; + } + + @Override + public boolean requiresLayout() + { + return false; + } + + @Override + public void setErrorHandler(ErrorHandler errorHandler) + { + _errorHandler = errorHandler; + } + + @Override + public void setLayout(Layout layout) + { + + } + + @Override + public void setName(String name) + { + _name = name; + } + + @Override + public Iterator<Record> iterator() + { + return new RecordIterator(Math.max(_recordId-_bufferSize, 0l)); + } + + private class RecordIterator implements Iterator<Record> + { + private long _id; + + public RecordIterator(long currentRecordId) + { + _id = currentRecordId; + } + + @Override + public boolean hasNext() + { + return _id < _recordId; + } + + @Override + public Record next() + { + Record record = _records[((int) (_id & _mask))]; + while(_id < _recordId-_bufferSize) + { + _id = _recordId-_bufferSize; + record = _records[((int) (_id & _mask))]; + } + _id++; + return record; + } + + @Override + public void remove() + { + throw new UnsupportedOperationException(); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java deleted file mode 100644 index c699dff175..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java +++ /dev/null @@ -1,822 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.logging.management; - -import org.apache.log4j.Level; -import org.apache.log4j.LogManager; -import org.apache.log4j.Logger; -import org.apache.log4j.xml.Log4jEntityResolver; -import org.apache.log4j.xml.QpidLog4JConfigurator; -import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException; -import org.apache.log4j.xml.QpidLog4JConfigurator.QpidLog4JSaxErrorHandler; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.NodeList; -import org.xml.sax.ErrorHandler; -import org.xml.sax.SAXException; - -import org.apache.qpid.management.common.mbeans.LoggingManagement; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.management.AMQManagedObject; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import javax.management.openmbean.TabularType; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.OutputKeys; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Random; - -import static org.apache.log4j.xml.QpidLog4JConfigurator.LOCK; - - -/** MBean class for BrokerLoggingManagerMBean. It implements all the management features exposed for managing logging. */ -@MBeanDescription("Logging Management Interface") -public class LoggingManagementMBean extends AMQManagedObject implements LoggingManagement -{ - - private static final Logger _logger = Logger.getLogger(LoggingManagementMBean.class); - private String _log4jConfigFileName; - private int _log4jLogWatchInterval; - private static final String INHERITED = "INHERITED"; - private static final String[] LEVELS = new String[]{Level.ALL.toString(), Level.TRACE.toString(), - Level.DEBUG.toString(), Level.INFO.toString(), - Level.WARN.toString(), Level.ERROR.toString(), - Level.FATAL.toString(),Level.OFF.toString(), - INHERITED}; - private static TabularType _loggerLevelTabularType; - private static CompositeType _loggerLevelCompositeType; - - static - { - try - { - OpenType[] loggerLevelItemTypes = new OpenType[]{SimpleType.STRING, SimpleType.STRING}; - - _loggerLevelCompositeType = new CompositeType("LoggerLevelList", "Logger Level Data", - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), - loggerLevelItemTypes); - - _loggerLevelTabularType = new TabularType("LoggerLevel", "List of loggers with levels", - _loggerLevelCompositeType, - TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); - } - catch (OpenDataException e) - { - _logger.error("Tabular data setup for viewing logger levels was incorrect."); - _loggerLevelTabularType = null; - } - } - - public LoggingManagementMBean(String log4jConfigFileName, int log4jLogWatchInterval) throws JMException - { - super(LoggingManagement.class, LoggingManagement.TYPE); - _log4jConfigFileName = log4jConfigFileName; - _log4jLogWatchInterval = log4jLogWatchInterval; - } - - public String getObjectInstanceName() - { - return LoggingManagement.TYPE; - } - - public Integer getLog4jLogWatchInterval() - { - return _log4jLogWatchInterval; - } - - public String[] getAvailableLoggerLevels() - { - return LEVELS; - } - @SuppressWarnings("unchecked") - public synchronized boolean setRuntimeLoggerLevel(String logger, String level) - { - //check specified level is valid - Level newLevel; - try - { - newLevel = getLevel(level); - } - catch (Exception e) - { - return false; - } - - //check specified logger exists - Enumeration loggers = LogManager.getCurrentLoggers(); - Boolean loggerExists = false; - - while(loggers.hasMoreElements()) - { - Logger log = (Logger) loggers.nextElement(); - if (log.getName().equals(logger)) - { - loggerExists = true; - break; - } - } - - if(!loggerExists) - { - return false; - } - - //set the logger to the new level - _logger.info("Setting level to " + level + " for logger: " + logger); - - Logger log = Logger.getLogger(logger); - log.setLevel(newLevel); - - return true; - } - - @SuppressWarnings("unchecked") - public synchronized TabularData viewEffectiveRuntimeLoggerLevels() - { - if (_loggerLevelTabularType == null) - { - _logger.warn("TabluarData type not set up correctly"); - return null; - } - - _logger.info("Getting levels for currently active log4j loggers"); - - Enumeration loggers = LogManager.getCurrentLoggers(); - - TabularData loggerLevelList = new TabularDataSupport(_loggerLevelTabularType); - - Logger logger; - String loggerName; - String level; - - try - { - while(loggers.hasMoreElements()){ - logger = (Logger) loggers.nextElement(); - - loggerName = logger.getName(); - level = logger.getEffectiveLevel().toString(); - - Object[] itemData = {loggerName, level}; - CompositeData loggerData = new CompositeDataSupport(_loggerLevelCompositeType, - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData); - loggerLevelList.put(loggerData); - } - } - catch (OpenDataException e) - { - _logger.warn("Unable to create logger level list due to :" + e); - return null; - } - - return loggerLevelList; - - } - - public synchronized String getRuntimeRootLoggerLevel() - { - Logger rootLogger = Logger.getRootLogger(); - - return rootLogger.getLevel().toString(); - } - - public synchronized boolean setRuntimeRootLoggerLevel(String level) - { - Level newLevel; - try - { - newLevel = getLevel(level); - } - catch (Exception e) - { - return false; - } - - if(newLevel == null) - { - //A null Level reference implies inheritance. Setting the runtime RootLogger - //to null is catastrophic (and prevented by Log4J at startup and runtime anyway). - return false; - } - - _logger.info("Setting RootLogger level to " + level); - - Logger log = Logger.getRootLogger(); - log.setLevel(newLevel); - - return true; - } - - //method to convert from a string to a log4j Level, throws exception if the given value is invalid - private Level getLevel(String level) throws Exception - { - if("null".equalsIgnoreCase(level) || INHERITED.equalsIgnoreCase(level)) - { - //the string "null" or "inherited" signals to inherit from a parent logger, - //using a null Level reference for the logger. - return null; - } - - Level newLevel = Level.toLevel(level); - - //above Level.toLevel call returns a DEBUG Level if the request fails. Check the result. - if (newLevel.equals(Level.DEBUG) && !(level.equalsIgnoreCase("debug"))) - { - //received DEBUG but we did not ask for it, the Level request failed. - throw new Exception("Invalid level name"); - } - - return newLevel; - } - - //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content. - private static synchronized Document parseConfigFile(String fileName) throws IOException - { - try - { - LOCK.lock(); - - //check file was specified, exists, and is readable - if(fileName == null) - { - _logger.warn("Provided log4j XML configuration filename is null"); - throw new IOException("Provided log4j XML configuration filename is null"); - } - - File configFile = new File(fileName); - - if (!configFile.exists()) - { - _logger.warn("The log4j XML configuration file could not be found: " + fileName); - throw new IOException("The log4j XML configuration file could not be found"); - } - else if (!configFile.canRead()) - { - _logger.warn("The log4j XML configuration file is not readable: " + fileName); - throw new IOException("The log4j XML configuration file is not readable"); - } - - //parse it - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder; - Document doc; - - ErrorHandler errHandler = new QpidLog4JSaxErrorHandler(); - try - { - docFactory.setValidating(true); - docBuilder = docFactory.newDocumentBuilder(); - docBuilder.setErrorHandler(errHandler); - docBuilder.setEntityResolver(new Log4jEntityResolver()); - doc = docBuilder.parse(fileName); - } - catch (ParserConfigurationException e) - { - _logger.warn("Unable to parse the log4j XML file due to possible configuration error: " + e); - //recommended that MBeans should use java.* and javax.* exceptions only - throw new IOException("Unable to parse the log4j XML file due to possible configuration error: " + e.getMessage()); - } - catch (SAXException e) - { - _logger.warn("The specified log4j XML file is invalid: " + e); - //recommended that MBeans should use standard java.* and javax.* exceptions only - throw new IOException("The specified log4j XML file is invalid: " + e.getMessage()); - } - catch (IOException e) - { - _logger.warn("Unable to parse the specified log4j XML file" + e); - throw new IOException("Unable to parse the specified log4j XML file: " + e.getMessage()); - } - - return doc; - } - finally - { - LOCK.unlock(); - } - } - - - private static synchronized boolean writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException - { - try - { - LOCK.lock(); - - File log4jConfigFile = new File(log4jConfigFileName); - - if (!log4jConfigFile.canWrite()) - { - _logger.warn("Specified log4j XML configuration file is not writable: " + log4jConfigFile); - throw new IOException("Specified log4j XML configuration file is not writable"); - } - - Transformer transformer = null; - try - { - transformer = TransformerFactory.newInstance().newTransformer(); - } - catch (Exception e) - { - _logger.warn("Could not create an XML transformer: " +e); - return false; - } - - transformer.setOutputProperty(OutputKeys.INDENT, "yes"); - transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "log4j.dtd"); - DOMSource source = new DOMSource(doc); - - File tmp; - Random r = new Random(); - do - { - tmp = new File(log4jConfigFile.getPath() + r.nextInt() + ".tmp"); - } - while(tmp.exists()); - - tmp.deleteOnExit(); - - try - { - StreamResult result = new StreamResult(tmp); - transformer.transform(source, result); - } - catch (TransformerException e) - { - _logger.warn("Could not transform the XML into new file: " +e); - throw new IOException("Could not transform the XML into new file: " +e); - } - - // Swap temp file in to replace existing configuration file. - File old = new File(log4jConfigFile.getAbsoluteFile() + ".old"); - if (old.exists()) - { - old.delete(); - } - - if(!log4jConfigFile.renameTo(old)) - { - //unable to rename the existing file to the backup name - _logger.error("Could not backup the existing log4j XML file"); - throw new IOException("Could not backup the existing log4j XML file"); - } - - if(!tmp.renameTo(log4jConfigFile)) - { - //failed to rename the new file to the required filename - - if(!old.renameTo(log4jConfigFile)) - { - //unable to return the backup to required filename - _logger.error("Could not rename the new log4j configuration file into place, and unable to restore original file"); - throw new IOException("Could not rename the new log4j configuration file into place, and unable to restore original file"); - } - - _logger.error("Could not rename the new log4j configuration file into place"); - throw new IOException("Could not rename the new log4j configuration file into place"); - } - - return true; - } - finally - { - LOCK.unlock(); - } - } - - - /* The log4j XML configuration file DTD defines three possible element - * combinations for specifying optional logger+level settings. - * Must account for the following: - * - * <category name="x"> <priority value="y"/> </category> OR - * <category name="x"> <level value="y"/> </category> OR - * <logger name="x"> <level value="y"/> </logger> - * - * Noting also that the level/priority child element is optional too, - * and not the only possible child element. - */ - - public static synchronized Map<String,String> retrieveConfigFileLoggersLevels(String fileName) throws IOException - { - try - { - LOCK.lock(); - - Document doc = parseConfigFile(fileName); - - HashMap<String,String> loggerLevelList = new HashMap<String,String>(); - - //retrieve the 'category' element nodes - NodeList categoryElements = doc.getElementsByTagName("category"); - - String categoryName; - String priority = null; - - for (int i = 0; i < categoryElements.getLength(); i++) - { - Element categoryElement = (Element) categoryElements.item(i); - categoryName = categoryElement.getAttribute("name"); - - //retrieve the category's mandatory 'priority' or 'level' element's value. - //It may not be the only child node, so request by tag name. - NodeList priorityElements = categoryElement.getElementsByTagName("priority"); - NodeList levelElements = categoryElement.getElementsByTagName("level"); - - if (priorityElements.getLength() != 0) - { - Element priorityElement = (Element) priorityElements.item(0); - priority = priorityElement.getAttribute("value"); - } - else if (levelElements.getLength() != 0) - { - Element levelElement = (Element) levelElements.item(0); - priority = levelElement.getAttribute("value"); - } - else - { - //there is no exiting priority or level to view, move onto next category/logger - continue; - } - - loggerLevelList.put(categoryName, priority); - } - - //retrieve the 'logger' element nodes - NodeList loggerElements = doc.getElementsByTagName("logger"); - - String loggerName; - String level; - - for (int i = 0; i < loggerElements.getLength(); i++) - { - Element loggerElement = (Element) loggerElements.item(i); - loggerName = loggerElement.getAttribute("name"); - - //retrieve the logger's mandatory 'level' element's value - //It may not be the only child node, so request by tag name. - NodeList levelElements = loggerElement.getElementsByTagName("level"); - - Element levelElement = (Element) levelElements.item(0); - level = levelElement.getAttribute("value"); - - loggerLevelList.put(loggerName, level); - } - - return loggerLevelList; - } - finally - { - LOCK.unlock(); - } - } - - public synchronized TabularData viewConfigFileLoggerLevels() throws IOException - { - try - { - LOCK.lock(); - - if (_loggerLevelTabularType == null) - { - _logger.warn("TabluarData type not set up correctly"); - return null; - } - - _logger.info("Getting logger levels from log4j configuration file"); - - TabularData loggerLevelList = new TabularDataSupport(_loggerLevelTabularType); - - Map<String,String> levels = retrieveConfigFileLoggersLevels(_log4jConfigFileName); - - for (Map.Entry<String,String> entry : levels.entrySet()) - { - String loggerName = entry.getKey(); - String level = entry.getValue(); - - try - { - Object[] itemData = {loggerName, level.toUpperCase()}; - CompositeData loggerData = new CompositeDataSupport(_loggerLevelCompositeType, - COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData); - loggerLevelList.put(loggerData); - } - catch (OpenDataException e) - { - _logger.warn("Unable to create logger level list due to :" + e); - return null; - } - } - - return loggerLevelList; - } - finally - { - LOCK.unlock(); - } - } - - public synchronized boolean setConfigFileLoggerLevel(String logger, String level) throws IOException - { - try - { - LOCK.lock(); - - //check that the specified level is a valid log4j Level - try - { - getLevel(level); - } - catch (Exception e) - { - //it isnt a valid level - return false; - } - - _logger.info("Setting level to " + level + " for logger '" + logger - + "' in log4j xml configuration file: " + _log4jConfigFileName); - - Document doc = parseConfigFile(_log4jConfigFileName); - - //retrieve the 'category' and 'logger' element nodes - NodeList categoryElements = doc.getElementsByTagName("category"); - NodeList loggerElements = doc.getElementsByTagName("logger"); - - //collect them into a single elements list - List<Element> logElements = new ArrayList<Element>(); - - for (int i = 0; i < categoryElements.getLength(); i++) - { - logElements.add((Element) categoryElements.item(i)); - } - for (int i = 0; i < loggerElements.getLength(); i++) - { - logElements.add((Element) loggerElements.item(i)); - } - - //try to locate the specified logger/category in the elements retrieved - Element logElement = null; - for (Element e : logElements) - { - if (e.getAttribute("name").equals(logger)) - { - logElement = e; - break; - } - } - - if (logElement == null) - { - //no loggers/categories with given name found, does not exist to update - _logger.warn("Specified logger does not exist in the configuration file: " +logger); - return false; - } - - //retrieve the optional 'priority' or 'level' sub-element value. - //It may not be the only child node, so request by tag name. - NodeList priorityElements = logElement.getElementsByTagName("priority"); - NodeList levelElements = logElement.getElementsByTagName("level"); - - Element levelElement = null; - if (priorityElements.getLength() != 0) - { - levelElement = (Element) priorityElements.item(0); - } - else if (levelElements.getLength() != 0) - { - levelElement = (Element) levelElements.item(0); - } - else - { - //there is no exiting priority or level element to update - return false; - } - - //update the element with the new level/priority - levelElement.setAttribute("value", level.toLowerCase()); - - //output the new file - return writeUpdatedConfigFile(_log4jConfigFileName, doc); - } - finally - { - LOCK.unlock(); - } - } - - - /* The log4j XML configuration file DTD defines 2 possible element - * combinations for specifying the optional root logger level settings - * Must account for the following: - * - * <root> <priority value="y"/> </root> OR - * <root> <level value="y"/> </root> - * - * Noting also that the level/priority child element is optional too, - * and not the only possible child element. - */ - - public static synchronized String retrieveConfigFileRootLoggerLevel(String fileName) throws IOException - { - try - { - LOCK.lock(); - - Document doc = parseConfigFile(fileName); - - //retrieve the optional 'root' element node - NodeList rootElements = doc.getElementsByTagName("root"); - - if (rootElements.getLength() == 0) - { - //there is no root logger definition - return "N/A"; - } - - Element rootElement = (Element) rootElements.item(0); - - //retrieve the optional 'priority' or 'level' element value. - //It may not be the only child node, so request by tag name. - NodeList priorityElements = rootElement.getElementsByTagName("priority"); - NodeList levelElements = rootElement.getElementsByTagName("level"); - String priority = null; - - if (priorityElements.getLength() != 0) - { - Element priorityElement = (Element) priorityElements.item(0); - priority = priorityElement.getAttribute("value"); - } - else if(levelElements.getLength() != 0) - { - Element levelElement = (Element) levelElements.item(0); - priority = levelElement.getAttribute("value"); - } - - if(priority != null) - { - return priority; - } - else - { - return "N/A"; - } - } - finally - { - LOCK.unlock(); - } - } - - public synchronized String getConfigFileRootLoggerLevel() throws IOException - { - return retrieveConfigFileRootLoggerLevel(_log4jConfigFileName).toUpperCase(); - } - - public synchronized boolean setConfigFileRootLoggerLevel(String level) throws IOException - { - try - { - LOCK.lock(); - - //check that the specified level is a valid log4j Level - try - { - Level newLevel = getLevel(level); - if(newLevel == null) - { - //A null Level reference implies inheritance. Setting the config file RootLogger - //to "null" or "inherited" just ensures it defaults to DEBUG at startup as Log4J - //prevents this catastrophic situation at startup and runtime anyway. - return false; - } - } - catch (Exception e) - { - //it isnt a valid level - return false; - } - - _logger.info("Setting level to " + level + " for the Root logger in " + - "log4j xml configuration file: " + _log4jConfigFileName); - - Document doc = parseConfigFile(_log4jConfigFileName); - - //retrieve the optional 'root' element node - NodeList rootElements = doc.getElementsByTagName("root"); - - if (rootElements.getLength() == 0) - { - return false; - } - - Element rootElement = (Element) rootElements.item(0); - - //retrieve the optional 'priority' or 'level' sub-element value. - //It may not be the only child node, so request by tag name. - NodeList priorityElements = rootElement.getElementsByTagName("priority"); - NodeList levelElements = rootElement.getElementsByTagName("level"); - - Element levelElement = null; - if (priorityElements.getLength() != 0) - { - levelElement = (Element) priorityElements.item(0); - } - else if (levelElements.getLength() != 0) - { - levelElement = (Element) levelElements.item(0); - } - else - { - //there is no exiting priority/level to update - return false; - } - - //update the element with the new level/priority - levelElement.setAttribute("value", level); - - //output the new file - return writeUpdatedConfigFile(_log4jConfigFileName, doc); - } - finally - { - LOCK.unlock(); - } - } - - public synchronized void reloadConfigFile() throws IOException - { - try - { - LOCK.lock(); - - QpidLog4JConfigurator.configure(_log4jConfigFileName); - _logger.info("Applied log4j configuration from: " + _log4jConfigFileName); - } - catch (IllegalLoggerLevelException e) - { - _logger.warn("The log4j configuration reload request was aborted: " + e); - //recommended that MBeans should use standard java.* and javax.* exceptions only - throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage()); - } - catch (ParserConfigurationException e) - { - _logger.warn("The log4j configuration reload request was aborted: " + e); - throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage()); - } - catch (SAXException e) - { - _logger.warn("The log4j configuration reload request was aborted: " + e); - //recommended that MBeans should use standard java.* and javax.* exceptions only - throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage()); - } - catch (IOException e) - { - _logger.warn("The log4j configuration reload request was aborted: " + e); - throw new IOException("The log4j configuration reload request was aborted: " + e.getMessage()); - } - finally - { - LOCK.unlock(); - } - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java deleted file mode 100644 index 5c57c01f6e..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; - -import javax.management.ListenerNotFoundException; -import javax.management.NotCompliantMBeanException; -import javax.management.NotificationBroadcaster; -import javax.management.NotificationBroadcasterSupport; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; - -/** - * This class provides additinal feature of Notification Broadcaster to the - * DefaultManagedObject. - * @author Bhupendra Bhardwaj - * @version 0.1 - */ -public abstract class AMQManagedObject extends DefaultManagedObject - implements NotificationBroadcaster -{ - private NotificationBroadcasterSupport _broadcaster = new NotificationBroadcasterSupport(); - - private long _notificationSequenceNumber = 0; - - private LogActor _logActor; - - protected AMQManagedObject(Class<?> managementInterface, String typeName) - throws NotCompliantMBeanException - { - super(managementInterface, typeName); - // CurrentActor will be defined as these objects are created during - // broker startup. - _logActor = new ManagementActor(CurrentActor.get().getRootMessageLogger()); - } - - // notification broadcaster implementation - - public void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - { - _broadcaster.addNotificationListener(listener, filter, handback); - } - - public void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException - { - _broadcaster.removeNotificationListener(listener); - } - - - /** - * broadcaster support class - */ - protected NotificationBroadcasterSupport getBroadcaster() - { - return _broadcaster; - } - - /** - * sequence number for notifications - */ - protected long getNotificationSequenceNumber() - { - return _notificationSequenceNumber; - } - - protected void setNotificationSequenceNumber(long notificationSequenceNumber) - { - _notificationSequenceNumber = notificationSequenceNumber; - } - - protected long incrementAndGetSequenceNumber() - { - return ++_notificationSequenceNumber; - } - - protected LogActor getLogActor() - { - return _logActor; - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java deleted file mode 100644 index 6cfc827046..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import org.apache.qpid.management.common.mbeans.ManagedConnection; - -import javax.management.JMException; -import javax.management.MBeanNotificationInfo; -import javax.management.NotCompliantMBeanException; -import javax.management.Notification; -import javax.management.ObjectName; -import javax.management.monitor.MonitorNotification; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularType; - -public abstract class AbstractAMQManagedConnectionObject extends AMQManagedObject implements ManagedConnection -{ - private final String _name; - - protected static final OpenType[] _channelAttributeTypes = { SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER, SimpleType.BOOLEAN }; - protected static final CompositeType _channelType; - protected static final TabularType _channelsType; - - protected static final String BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION_STR = - "Broker Management Console has closed the connection."; - - static - { - try - { - _channelType = new CompositeType("Channel", "Channel Details", COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), - COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), _channelAttributeTypes); - _channelsType = new TabularType("Channels", "Channels", _channelType, (String[]) TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); - } - catch (JMException ex) - { - // This is not expected to ever occur. - throw new RuntimeException("Got JMException in static initializer.", ex); - } - } - - protected AbstractAMQManagedConnectionObject(final String remoteAddress) throws NotCompliantMBeanException - { - super(ManagedConnection.class, ManagedConnection.TYPE); - _name = "anonymous".equals(remoteAddress) ? (remoteAddress + hashCode()) : remoteAddress; - } - - public String getObjectInstanceName() - { - return ObjectName.quote(_name); - } - - public void notifyClients(String notificationMsg) - { - final Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, incrementAndGetSequenceNumber(), - System.currentTimeMillis(), notificationMsg); - getBroadcaster().sendNotification(n); - } - - @Override - public MBeanNotificationInfo[] getNotificationInfo() - { - String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED }; - String name = MonitorNotification.class.getName(); - String description = "Channel count has reached threshold value"; - MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description); - - return new MBeanNotificationInfo[] { info1 }; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java deleted file mode 100644 index 10d7503800..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.registry.ApplicationRegistry; - -import javax.management.JMException; -import javax.management.MBeanInfo; -import javax.management.MBeanNotificationInfo; -import javax.management.MalformedObjectNameException; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import javax.management.StandardMBean; - -/** - * Provides implementation of the boilerplate ManagedObject interface. Most managed objects should find it useful - * to extend this class rather than implementing ManagedObject from scratch. - * - */ -public abstract class DefaultManagedObject extends StandardMBean implements ManagedObject -{ - private static final Logger LOGGER = Logger.getLogger(DefaultManagedObject.class); - - private final Class<?> _managementInterface; - - private final String _typeName; - - private final MBeanInfo _mbeanInfo; - - private ManagedObjectRegistry _registry; - - protected DefaultManagedObject(Class<?> managementInterface, String typeName) - throws NotCompliantMBeanException - { - super(managementInterface); - _managementInterface = managementInterface; - _typeName = typeName; - _mbeanInfo = buildMBeanInfo(); - } - - @Override - public MBeanInfo getMBeanInfo() - { - return _mbeanInfo; - } - - public String getType() - { - return _typeName; - } - - public Class<?> getManagementInterface() - { - return _managementInterface; - } - - public ManagedObject getParentObject() - { - return null; - } - - public void register() throws JMException - { - _registry = ApplicationRegistry.getInstance().getManagedObjectRegistry(); - _registry.registerObject(this); - } - - public void unregister() - { - try - { - if(_registry != null) - { - _registry.unregisterObject(this); - } - } - catch (JMException e) - { - LOGGER.error("Error unregistering managed object: " + this + ": " + e, e); - } - finally - { - _registry = null; - } - } - - public String toString() - { - return getObjectInstanceName() + "[" + getType() + "]"; - } - - /** - * Created the ObjectName as per the JMX Specs - * @return ObjectName - * @throws MalformedObjectNameException - */ - public ObjectName getObjectName() throws MalformedObjectNameException - { - String name = getObjectInstanceName(); - StringBuffer objectName = new StringBuffer(ManagedObject.DOMAIN); - - objectName.append(":type="); - objectName.append(getHierarchicalType(this)); - - objectName.append(","); - objectName.append(getHierarchicalName(this)); - objectName.append("name=").append(name); - - return new ObjectName(objectName.toString()); - } - - protected ObjectName getObjectNameForSingleInstanceMBean() throws MalformedObjectNameException - { - StringBuffer objectName = new StringBuffer(ManagedObject.DOMAIN); - - objectName.append(":type="); - objectName.append(getHierarchicalType(this)); - - String hierarchyName = getHierarchicalName(this); - if (hierarchyName != null) - { - objectName.append(","); - objectName.append(hierarchyName.substring(0, hierarchyName.lastIndexOf(","))); - } - - return new ObjectName(objectName.toString()); - } - - protected String getHierarchicalType(ManagedObject obj) - { - if (obj.getParentObject() != null) - { - String parentType = getHierarchicalType(obj.getParentObject()).toString(); - return parentType + "." + obj.getType(); - } - else - { - return obj.getType(); - } - } - - protected String getHierarchicalName(ManagedObject obj) - { - if (obj.getParentObject() != null) - { - String parentName = obj.getParentObject().getType() + "=" + - obj.getParentObject().getObjectInstanceName() + ","+ - getHierarchicalName(obj.getParentObject()); - - return parentName; - } - else - { - return ""; - } - } - - private MBeanInfo buildMBeanInfo() throws NotCompliantMBeanException - { - return new MBeanInfo(this.getClass().getName(), - MBeanIntrospector.getMBeanDescription(this.getClass()), - MBeanIntrospector.getMBeanAttributesInfo(getManagementInterface()), - MBeanIntrospector.getMBeanConstructorsInfo(this.getClass()), - MBeanIntrospector.getMBeanOperationsInfo(getManagementInterface()), - this.getNotificationInfo()); - } - - public MBeanNotificationInfo[] getNotificationInfo() - { - return null; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java deleted file mode 100644 index 869a816cf1..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java +++ /dev/null @@ -1,490 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.lang.management.ManagementFactory; -import java.lang.reflect.Proxy; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.rmi.AlreadyBoundException; -import java.rmi.NoSuchObjectException; -import java.rmi.NotBoundException; -import java.rmi.registry.LocateRegistry; -import java.rmi.registry.Registry; -import java.rmi.server.RMIClientSocketFactory; -import java.rmi.server.RMIServerSocketFactory; -import java.rmi.server.UnicastRemoteObject; -import java.security.Principal; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import javax.management.JMException; -import javax.management.MBeanServer; -import javax.management.MBeanServerFactory; -import javax.management.Notification; -import javax.management.NotificationFilterSupport; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXConnectorServer; -import javax.management.remote.JMXServiceURL; -import javax.management.remote.MBeanServerForwarder; -import javax.management.remote.rmi.RMIConnection; -import javax.management.remote.rmi.RMIConnectorServer; -import javax.management.remote.rmi.RMIJRMPServerImpl; -import javax.management.remote.rmi.RMIServerImpl; -import javax.rmi.ssl.SslRMIClientSocketFactory; -import javax.rmi.ssl.SslRMIServerSocketFactory; -import javax.security.auth.Subject; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator; - -/** - * This class starts up an MBeanserver. If out of the box agent has been enabled then there are no - * security features implemented like user authentication and authorisation. - */ -public class JMXManagedObjectRegistry implements ManagedObjectRegistry -{ - private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class); - - private final MBeanServer _mbeanServer; - private JMXConnectorServer _cs; - private Registry _rmiRegistry; - private boolean _useCustomSocketFactory; - - private final int _jmxPortRegistryServer; - private final int _jmxPortConnectorServer; - - public JMXManagedObjectRegistry() throws AMQException - { - _log.info("Initialising managed object registry using platform MBean server"); - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - - // Retrieve the config parameters - _useCustomSocketFactory = appRegistry.getConfiguration().getUseCustomRMISocketFactory(); - boolean platformServer = appRegistry.getConfiguration().getPlatformMbeanserver(); - - _mbeanServer = - platformServer ? ManagementFactory.getPlatformMBeanServer() - : MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN); - - _jmxPortRegistryServer = appRegistry.getConfiguration().getJMXPortRegistryServer(); - _jmxPortConnectorServer = appRegistry.getConfiguration().getJMXConnectorServerPort(); - - } - - public void start() throws IOException, ConfigurationException - { - - CurrentActor.get().message(ManagementConsoleMessages.STARTUP()); - - //check if system properties are set to use the JVM's out-of-the-box JMXAgent - if (areOutOfTheBoxJMXOptionsSet()) - { - CurrentActor.get().message(ManagementConsoleMessages.READY(true)); - return; - } - - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - - - //Socket factories for the RMIConnectorServer, either default or SLL depending on configuration - RMIClientSocketFactory csf; - RMIServerSocketFactory ssf; - - //check ssl enabled option in config, default to true if option is not set - boolean sslEnabled = appRegistry.getConfiguration().getManagementSSLEnabled(); - - if (sslEnabled) - { - //set the SSL related system properties used by the SSL RMI socket factories to the values - //given in the configuration file, unless command line settings have already been specified - String keyStorePath; - - if(System.getProperty("javax.net.ssl.keyStore") != null) - { - keyStorePath = System.getProperty("javax.net.ssl.keyStore"); - } - else - { - keyStorePath = appRegistry.getConfiguration().getManagementKeyStorePath(); - } - - //check the keystore path value is valid - if (keyStorePath == null) - { - throw new ConfigurationException("JMX management SSL keystore path not defined, " + - "unable to start SSL protected JMX ConnectorServer"); - } - else - { - //ensure the system property is set - System.setProperty("javax.net.ssl.keyStore", keyStorePath); - - //check the file is usable - File ksf = new File(keyStorePath); - - if (!ksf.exists()) - { - throw new FileNotFoundException("Cannot find JMX management SSL keystore file: " + ksf); - } - if (!ksf.canRead()) - { - throw new FileNotFoundException("Cannot read JMX management SSL keystore file: " - + ksf + ". Check permissions."); - } - - CurrentActor.get().message(ManagementConsoleMessages.SSL_KEYSTORE(ksf.getAbsolutePath())); - } - - //check the key store password is set - if (System.getProperty("javax.net.ssl.keyStorePassword") == null) - { - - if (appRegistry.getConfiguration().getManagementKeyStorePassword() == null) - { - throw new ConfigurationException("JMX management SSL keystore password not defined, " + - "unable to start requested SSL protected JMX server"); - } - else - { - System.setProperty("javax.net.ssl.keyStorePassword", - appRegistry.getConfiguration().getManagementKeyStorePassword()); - } - } - - //create the SSL RMI socket factories - csf = new SslRMIClientSocketFactory(); - ssf = new SslRMIServerSocketFactory(); - } - else - { - //Do not specify any specific RMI socket factories, resulting in use of the defaults. - csf = null; - ssf = null; - } - - //add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server - RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator(); - rmipa.setAuthenticationManager(appRegistry.getAuthenticationManager(new InetSocketAddress(_jmxPortRegistryServer))); - HashMap<String,Object> env = new HashMap<String,Object>(); - env.put(JMXConnectorServer.AUTHENTICATOR, rmipa); - - /* - * Start a RMI registry on the management port, to hold the JMX RMI ConnectorServer stub. - * Using custom socket factory to prevent anyone (including us unfortunately) binding to the registry using RMI. - * As a result, only binds made using the object reference will succeed, thus securing it from external change. - */ - System.setProperty("java.rmi.server.randomIDs", "true"); - if(_useCustomSocketFactory) - { - _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory()); - } - else - { - _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null); - } - - CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer)); - - /* - * We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls - * to bind the ConnectorServer to the registry, which will now fail as for security we have - * locked it from any RMI based modifications, including our own. Instead, we will manually bind - * the RMIConnectorServer stub to the registry using its object reference, which will still succeed. - * - * The registry is exported on the defined management port 'port'. We will export the RMIConnectorServer - * on 'port +1'. Use of these two well-defined ports will ease any navigation through firewall's. - */ - final Map<String, String> connectionIdUsernameMap = new ConcurrentHashMap<String, String>(); - final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env) - { - - /** - * Override makeClient so we can cache the username of the client in a Map keyed by connectionId. - * ConnectionId is guaranteed to be unique per client connection, according to the JMS spec. - * An instance of NotificationListener (mapCleanupListener) will be responsible for removing these Map - * entries. - * - * @see javax.management.remote.rmi.RMIJRMPServerImpl#makeClient(java.lang.String, javax.security.auth.Subject) - */ - @Override - protected RMIConnection makeClient(String connectionId, Subject subject) throws IOException - { - final RMIConnection makeClient = super.makeClient(connectionId, subject); - final Principal principal = subject.getPrincipals().iterator().next(); - connectionIdUsernameMap.put(connectionId, principal.getName()); - return makeClient; - } - }; - - // Create a Listener responsible for removing the map entries add by the #makeClient entry above. - final NotificationListener mapCleanupListener = new NotificationListener() - { - - @Override - public void handleNotification(Notification notification, Object handback) - { - final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); - connectionIdUsernameMap.remove(connectionId); - } - }; - - String localHost; - try - { - localHost = InetAddress.getLocalHost().getHostName(); - } - catch(UnknownHostException ex) - { - localHost="127.0.0.1"; - } - final String hostname = localHost; - final JMXServiceURL externalUrl = new JMXServiceURL( - "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi"); - - final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer); - _cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer) - { - @Override - public synchronized void start() throws IOException - { - try - { - //manually bind the connector server to the registry at key 'jmxrmi', like the out-of-the-box agent - _rmiRegistry.bind("jmxrmi", rmiConnectorServerStub); - } - catch (AlreadyBoundException abe) - { - //key was already in use. shouldnt happen here as its a new registry, unbindable by normal means. - - //IOExceptions are the only checked type throwable by the method, wrap and rethrow - IOException ioe = new IOException(abe.getMessage()); - ioe.initCause(abe); - throw ioe; - } - - //now do the normal tasks - super.start(); - } - - @Override - public synchronized void stop() throws IOException - { - try - { - if (_rmiRegistry != null) - { - _rmiRegistry.unbind("jmxrmi"); - } - } - catch (NotBoundException nbe) - { - //ignore - } - - //now do the normal tasks - super.stop(); - } - - @Override - public JMXServiceURL getAddress() - { - //must return our pre-crafted url that includes the full details, inc JNDI details - return externalUrl; - } - - }; - - - //Add the custom invoker as an MBeanServerForwarder, and start the RMIConnectorServer. - MBeanServerForwarder mbsf = MBeanInvocationHandlerImpl.newProxyInstance(); - _cs.setMBeanServerForwarder(mbsf); - - - // Get the handler that is used by the above MBInvocationHandler Proxy. - // which is the MBeanInvocationHandlerImpl and so also a NotificationListener. - final NotificationListener invocationHandler = (NotificationListener) Proxy.getInvocationHandler(mbsf); - - // Install a notification listener on OPENED, CLOSED, and FAILED, - // passing the map of connection-ids to usernames as hand-back data. - final NotificationFilterSupport invocationHandlerFilter = new NotificationFilterSupport(); - invocationHandlerFilter.enableType(JMXConnectionNotification.OPENED); - invocationHandlerFilter.enableType(JMXConnectionNotification.CLOSED); - invocationHandlerFilter.enableType(JMXConnectionNotification.FAILED); - _cs.addNotificationListener(invocationHandler, invocationHandlerFilter, connectionIdUsernameMap); - - // Install a second notification listener on CLOSED AND FAILED only to remove the entry from the - // Map. Here we rely on the fact that JMX will call the listeners in the order in which they are - // installed. - final NotificationFilterSupport mapCleanupHandlerFilter = new NotificationFilterSupport(); - mapCleanupHandlerFilter.enableType(JMXConnectionNotification.CLOSED); - mapCleanupHandlerFilter.enableType(JMXConnectionNotification.FAILED); - _cs.addNotificationListener(mapCleanupListener, mapCleanupHandlerFilter, null); - - _cs.start(); - - String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer"; - CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer)); - - CurrentActor.get().message(ManagementConsoleMessages.READY(false)); - } - - /* - * Custom RMIServerSocketFactory class, used to prevent updates to the RMI registry. - * Supplied to the registry at creation, this will prevent RMI-based operations on the - * registry such as attempting to bind a new object, thereby securing it from tampering. - * This is accomplished by always returning null when attempting to determine the address - * of the caller, thus ensuring the registry will refuse the attempt. Calls to bind etc - * made using the object reference will not be affected and continue to operate normally. - */ - - private static class CustomRMIServerSocketFactory implements RMIServerSocketFactory - { - - public ServerSocket createServerSocket(int port) throws IOException - { - return new NoLocalAddressServerSocket(port); - } - - private static class NoLocalAddressServerSocket extends ServerSocket - { - NoLocalAddressServerSocket(int port) throws IOException - { - super(port); - } - - @Override - public Socket accept() throws IOException - { - Socket s = new NoLocalAddressSocket(); - super.implAccept(s); - return s; - } - } - - private static class NoLocalAddressSocket extends Socket - { - @Override - public InetAddress getInetAddress() - { - return null; - } - } - } - - - public void registerObject(ManagedObject managedObject) throws JMException - { - _mbeanServer.registerMBean(managedObject, managedObject.getObjectName()); - } - - public void unregisterObject(ManagedObject managedObject) throws JMException - { - _mbeanServer.unregisterMBean(managedObject.getObjectName()); - } - - // checks if the system properties are set which enable the JVM's out-of-the-box JMXAgent. - private boolean areOutOfTheBoxJMXOptionsSet() - { - if (System.getProperty("com.sun.management.jmxremote") != null) - { - return true; - } - - if (System.getProperty("com.sun.management.jmxremote.port") != null) - { - return true; - } - - return false; - } - - //Stops the JMXConnectorServer and RMIRegistry, then unregisters any remaining MBeans from the MBeanServer - public void close() - { - if (_cs != null) - { - // Stopping the JMX ConnectorServer - try - { - CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("JMX RMIConnectorServer", _cs.getAddress().getPort())); - _cs.stop(); - } - catch (IOException e) - { - _log.error("Exception while closing the JMX ConnectorServer: " + e.getMessage()); - } - } - - if (_rmiRegistry != null) - { - // Stopping the RMI registry - CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer)); - try - { - UnicastRemoteObject.unexportObject(_rmiRegistry, false); - } - catch (NoSuchObjectException e) - { - _log.error("Exception while closing the RMI Registry: " + e.getMessage()); - } - } - - //ObjectName query to gather all Qpid related MBeans - ObjectName mbeanNameQuery = null; - try - { - mbeanNameQuery = new ObjectName(ManagedObject.DOMAIN + ":*"); - } - catch (Exception e1) - { - _log.warn("Unable to generate MBean ObjectName query for close operation"); - } - - for (ObjectName name : _mbeanServer.queryNames(mbeanNameQuery, null)) - { - try - { - _mbeanServer.unregisterMBean(name); - } - catch (JMException e) - { - _log.error("Exception unregistering MBean '"+ name +"': " + e.getMessage()); - } - } - - CurrentActor.get().message(ManagementConsoleMessages.STOPPED()); - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java deleted file mode 100644 index 89b74f939d..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java +++ /dev/null @@ -1,399 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import org.apache.qpid.management.common.mbeans.annotations.MBeanAttribute; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation; -import org.apache.qpid.management.common.mbeans.annotations.MBeanOperationParameter; - -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanConstructorInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanParameterInfo; -import javax.management.NotCompliantMBeanException; -import java.lang.annotation.Annotation; -import java.lang.reflect.Constructor; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.List; - -/** - * This class is a utility class to introspect the MBean class and the management - * interface class for various purposes. - * @author Bhupendra Bhardwaj - * @version 0.1 - */ -class MBeanIntrospector { - - private static final String _defaultAttributeDescription = "Management attribute"; - private static final String _defaultOerationDescription = "Management operation"; - private static final String _defaultConstructorDescription = "MBean constructor"; - private static final String _defaultMbeanDescription = "Management interface of the MBean"; - - private MBeanIntrospector() - { - } - - /** - * Introspects the management interface class for MBean attributes. - * @param interfaceClass - * @return MBeanAttributeInfo[] - * @throws NotCompliantMBeanException - */ - static MBeanAttributeInfo[] getMBeanAttributesInfo(Class interfaceClass) - throws NotCompliantMBeanException - { - List<MBeanAttributeInfo> attributesList = new ArrayList<MBeanAttributeInfo>(); - - /** - * Using reflection, all methods of the managemetn interface will be analysed, - * and MBeanInfo will be created. - */ - for (Method method : interfaceClass.getMethods()) - { - String name = method.getName(); - Class<?> resultType = method.getReturnType(); - MBeanAttributeInfo attributeInfo = null; - - if (isAttributeGetterMethod(method)) - { - String desc = getAttributeDescription(method); - attributeInfo = new MBeanAttributeInfo(name.substring(3), - resultType.getName(), - desc, - true, - false, - false); - int index = getIndexIfAlreadyExists(attributeInfo, attributesList); - if (index == -1) - { - attributesList.add(attributeInfo); - } - else - { - attributeInfo = new MBeanAttributeInfo(name.substring(3), - resultType.getName(), - desc, - true, - true, - false); - attributesList.set(index, attributeInfo); - } - } - else if (isAttributeSetterMethod(method)) - { - String desc = getAttributeDescription(method); - attributeInfo = new MBeanAttributeInfo(name.substring(3), - method.getParameterTypes()[0].getName(), - desc, - false, - true, - false); - int index = getIndexIfAlreadyExists(attributeInfo, attributesList); - if (index == -1) - { - attributesList.add(attributeInfo); - } - else - { - attributeInfo = new MBeanAttributeInfo(name.substring(3), - method.getParameterTypes()[0].getName(), - desc, - true, - true, - false); - attributesList.set(index, attributeInfo); - } - } - else if (isAttributeBoolean(method)) - { - attributeInfo = new MBeanAttributeInfo(name.substring(2), - resultType.getName(), - getAttributeDescription(method), - true, - false, - true); - attributesList.add(attributeInfo); - } - } - - return attributesList.toArray(new MBeanAttributeInfo[0]); - } - - /** - * Introspects the management interface class for management operations. - * @param interfaceClass - * @return MBeanOperationInfo[] - */ - static MBeanOperationInfo[] getMBeanOperationsInfo(Class interfaceClass) - { - List<MBeanOperationInfo> operationsList = new ArrayList<MBeanOperationInfo>(); - - for (Method method : interfaceClass.getMethods()) - { - if (!isAttributeGetterMethod(method) && - !isAttributeSetterMethod(method) && - !isAttributeBoolean(method)) - { - operationsList.add(getOperationInfo(method)); - } - } - - return operationsList.toArray(new MBeanOperationInfo[0]); - } - - /** - * Checks if the method is an attribute getter method. - * @param method - * @return true if the method is an attribute getter method. - */ - private static boolean isAttributeGetterMethod(Method method) - { - if (!(method.getName().equals("get")) && - method.getName().startsWith("get") && - method.getParameterTypes().length == 0 && - !method.getReturnType().equals(void.class)) - { - return true; - } - - return false; - } - - /** - * Checks if the method is an attribute setter method. - * @param method - * @return true if the method is an attribute setter method. - */ - private static boolean isAttributeSetterMethod(Method method) - { - if (!(method.getName().equals("set")) && - method.getName().startsWith("set") && - method.getParameterTypes().length == 1 && - method.getReturnType().equals(void.class)) - { - return true; - } - - return false; - } - - /** - * Checks if the attribute is a boolean and the method is a isX kind og method. - * @param method - * @return true if the method is an attribute isX type of method - */ - private static boolean isAttributeBoolean(Method method) - { - if (!(method.getName().equals("is")) && - method.getName().startsWith("is") && - method.getParameterTypes().length == 0 && - method.getReturnType().equals(boolean.class)) - { - return true; - } - - return false; - } - - /** - * Helper method to retrieve the attribute index from the list of attributes. - * @param attribute - * @param list - * @return attribute index no. -1 if attribtue doesn't exist - * @throws NotCompliantMBeanException - */ - private static int getIndexIfAlreadyExists(MBeanAttributeInfo attribute, - List<MBeanAttributeInfo> list) - throws NotCompliantMBeanException - { - String exceptionMsg = "Conflicting attribute methods for attribute " + attribute.getName(); - - for (MBeanAttributeInfo memberAttribute : list) - { - if (attribute.getName().equals(memberAttribute.getName())) - { - if (!attribute.getType().equals(memberAttribute.getType())) - { - throw new NotCompliantMBeanException(exceptionMsg); - } - if (attribute.isReadable() && memberAttribute.isReadable()) - { - if (attribute.isIs() != memberAttribute.isIs()) - { - throw new NotCompliantMBeanException(exceptionMsg); - } - } - - return list.indexOf(memberAttribute); - } - } - - return -1; - } - - /** - * Retrieves the attribute description from annotation - * @param attributeMethod - * @return attribute description - */ - private static String getAttributeDescription(Method attributeMethod) - { - MBeanAttribute anno = attributeMethod.getAnnotation(MBeanAttribute.class); - if (anno != null) - { - return anno.description(); - } - return _defaultAttributeDescription; - } - - /** - * Introspects the method to retrieve the operation information. - * @param operation - * @return MBeanOperationInfo - */ - private static MBeanOperationInfo getOperationInfo(Method operation) - { - MBeanOperationInfo operationInfo = null; - Class<?> returnType = operation.getReturnType(); - - MBeanParameterInfo[] paramsInfo = getParametersInfo(operation.getParameterAnnotations(), - operation.getParameterTypes()); - - String operationDesc = _defaultOerationDescription; - int impact = MBeanOperationInfo.UNKNOWN; - - if (operation.getAnnotation(MBeanOperation.class) != null) - { - operationDesc = operation.getAnnotation(MBeanOperation.class).description(); - impact = operation.getAnnotation(MBeanOperation.class).impact(); - } - operationInfo = new MBeanOperationInfo(operation.getName(), - operationDesc, - paramsInfo, - returnType.getName(), - impact); - - return operationInfo; - } - - /** - * Constructs the parameter info. - * @param paramsAnno - * @param paramTypes - * @return MBeanParameterInfo[] - */ - private static MBeanParameterInfo[] getParametersInfo(Annotation[][] paramsAnno, - Class<?>[] paramTypes) - { - int noOfParams = paramsAnno.length; - - MBeanParameterInfo[] paramsInfo = new MBeanParameterInfo[noOfParams]; - - for (int i = 0; i < noOfParams; i++) - { - MBeanParameterInfo paramInfo = null; - String type = paramTypes[i].getName(); - for (Annotation anno : paramsAnno[i]) - { - String name,desc; - if (MBeanOperationParameter.class.isInstance(anno)) - { - name = MBeanOperationParameter.class.cast(anno).name(); - desc = MBeanOperationParameter.class.cast(anno).description(); - paramInfo = new MBeanParameterInfo(name, type, desc); - } - } - - - if (paramInfo == null) - { - paramInfo = new MBeanParameterInfo("p " + (i + 1), type, "parameter " + (i + 1)); - } - if (paramInfo != null) - { - paramsInfo[i] = paramInfo; - } - } - - return paramsInfo; - } - - /** - * Introspects the MBean class for constructors - * @param implClass - * @return MBeanConstructorInfo[] - */ - static MBeanConstructorInfo[] getMBeanConstructorsInfo(Class implClass) - { - List<MBeanConstructorInfo> constructors = new ArrayList<MBeanConstructorInfo>(); - - for (Constructor cons : implClass.getConstructors()) - { - MBeanConstructorInfo constructorInfo = getMBeanConstructorInfo(cons); - if (constructorInfo != null) - { - constructors.add(constructorInfo); - } - } - - return constructors.toArray(new MBeanConstructorInfo[0]); - } - - /** - * Retrieves the constructor info from given constructor. - * @param cons - * @return MBeanConstructorInfo - */ - private static MBeanConstructorInfo getMBeanConstructorInfo(Constructor cons) - { - String desc = _defaultConstructorDescription; - Annotation anno = cons.getAnnotation(MBeanConstructor.class); - if (anno != null && MBeanConstructor.class.isInstance(anno)) - { - desc = MBeanConstructor.class.cast(anno).value(); - if(desc == null) - { - desc = _defaultConstructorDescription; - } - } - - return new MBeanConstructorInfo(cons.getName(), desc, null); - } - - /** - * Retrieves the description from the annotations of given class - * @param annotatedClass - * @return class description - */ - static String getMBeanDescription(Class annotatedClass) - { - Annotation anno = annotatedClass.getAnnotation(MBeanDescription.class); - if (anno != null && MBeanDescription.class.isInstance(anno)) - { - return MBeanDescription.class.cast(anno).value(); - } - return _defaultMbeanDescription; - } - -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java deleted file mode 100644 index 651372db16..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java +++ /dev/null @@ -1,367 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import org.apache.log4j.Logger; - -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.logging.messages.ManagementConsoleMessages; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.Operation; - -import javax.management.Attribute; -import javax.management.JMException; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.MBeanServer; -import javax.management.Notification; -import javax.management.NotificationListener; -import javax.management.ObjectName; -import javax.management.remote.JMXConnectionNotification; -import javax.management.remote.JMXPrincipal; -import javax.management.remote.MBeanServerForwarder; -import javax.security.auth.Subject; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.security.AccessControlContext; -import java.security.AccessController; -import java.util.Map; -import java.util.Set; - -/** - * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. It delegates - * JMX access decisions to the SecurityPlugin. - */ -public class MBeanInvocationHandlerImpl implements InvocationHandler, NotificationListener -{ - private static final Logger _logger = Logger.getLogger(MBeanInvocationHandlerImpl.class); - - private final IApplicationRegistry _appRegistry = ApplicationRegistry.getInstance(); - private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate"; - private MBeanServer _mbs; - private final ManagementActor _logActor = new ManagementActor(_appRegistry.getRootMessageLogger()); - private final boolean _managementRightsInferAllAccess = - _appRegistry.getConfiguration().getManagementRightsInferAllAccess(); - - public static MBeanServerForwarder newProxyInstance() - { - final InvocationHandler handler = new MBeanInvocationHandlerImpl(); - final Class<?>[] interfaces = new Class[] { MBeanServerForwarder.class }; - - Object proxy = Proxy.newProxyInstance(MBeanServerForwarder.class.getClassLoader(), interfaces, handler); - return MBeanServerForwarder.class.cast(proxy); - } - - private boolean invokeDirectly(String methodName, Object[] args, Subject subject) - { - // Allow operations performed locally on behalf of the connector server itself - if (subject == null) - { - return true; - } - - if (args == null || DELEGATE.equals(args[0])) - { - return true; - } - - // Allow querying available object names and mbeans - if (methodName.equals("queryNames") || methodName.equals("queryMBeans")) - { - return true; - } - - if (args[0] instanceof ObjectName) - { - ObjectName mbean = (ObjectName) args[0]; - - if(!DefaultManagedObject.DOMAIN.equalsIgnoreCase(mbean.getDomain())) - { - return true; - } - } - - return false; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable - { - String methodName = method.getName(); - - if (methodName.equals("getMBeanServer")) - { - return _mbs; - } - - if (methodName.equals("setMBeanServer")) - { - if (args[0] == null) - { - throw new IllegalArgumentException("Null MBeanServer"); - } - if (_mbs != null) - { - throw new IllegalArgumentException("MBeanServer object already initialized"); - } - _mbs = (MBeanServer) args[0]; - return null; - } - - // Restrict access to "createMBean" and "unregisterMBean" to any user - if (methodName.equals("createMBean") || methodName.equals("unregisterMBean")) - { - _logger.debug("User trying to create or unregister an MBean"); - throw new SecurityException("Access denied: " + methodName); - } - - // Retrieve Subject from current AccessControlContext - AccessControlContext acc = AccessController.getContext(); - Subject subject = Subject.getSubject(acc); - - try - { - if(invokeDirectly(methodName, args, subject)) - { - return method.invoke(_mbs, args); - } - - // Retrieve JMXPrincipal from Subject - Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class); - if (principals == null || principals.isEmpty()) - { - throw new SecurityException("Access denied: no JMX principal"); - } - - // Save the subject - SecurityManager.setThreadSubject(subject); - - // Get the component, type and impact, which may be null - String type = getType(method, args); - String vhost = getVirtualHost(method, args); - int impact = getImpact(method, args); - - // Get the security manager for the virtual host (if set) - SecurityManager security; - if (vhost == null) - { - security = _appRegistry.getSecurityManager(); - } - else - { - security = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhost).getSecurityManager(); - } - - methodName = getMethodName(method, args); - if (isAccessMethod(methodName) || impact == MBeanOperationInfo.INFO) - { - // Check for read-only method invocation permission - if (!security.authoriseMethod(Operation.ACCESS, type, methodName)) - { - throw new SecurityException("Permission denied: Access " + methodName); - } - } - else - { - // Check for setting properties permission - if (!security.authoriseMethod(Operation.UPDATE, type, methodName)) - { - throw new SecurityException("Permission denied: Update " + methodName); - } - } - - boolean oldAccessChecksDisabled = false; - if(_managementRightsInferAllAccess) - { - oldAccessChecksDisabled = SecurityManager.setAccessChecksDisabled(true); - } - - try - { - // Actually invoke the method - return method.invoke(_mbs, args); - } - finally - { - if(_managementRightsInferAllAccess) - { - SecurityManager.setAccessChecksDisabled(oldAccessChecksDisabled); - } - } - } - catch (InvocationTargetException e) - { - throw e.getTargetException(); - } - } - - private String getType(Method method, Object[] args) - { - if (args[0] instanceof ObjectName) - { - ObjectName object = (ObjectName) args[0]; - String type = object.getKeyProperty("type"); - - return type; - } - return null; - } - - private String getVirtualHost(Method method, Object[] args) - { - if (args[0] instanceof ObjectName) - { - ObjectName object = (ObjectName) args[0]; - String vhost = object.getKeyProperty("VirtualHost"); - - if(vhost != null) - { - try - { - //if the name is quoted in the ObjectName, unquote it - vhost = ObjectName.unquote(vhost); - } - catch(IllegalArgumentException e) - { - //ignore, this just means the name is not quoted - //and can be left unchanged - } - } - - return vhost; - } - return null; - } - - private String getMethodName(Method method, Object[] args) - { - String methodName = method.getName(); - - // if arguments are set, try and work out real method name - if (args != null && args.length >= 1 && args[0] instanceof ObjectName) - { - if (methodName.equals("getAttribute")) - { - methodName = "get" + (String) args[1]; - } - else if (methodName.equals("setAttribute")) - { - methodName = "set" + ((Attribute) args[1]).getName(); - } - else if (methodName.equals("invoke")) - { - methodName = (String) args[1]; - } - } - - return methodName; - } - - private int getImpact(Method method, Object[] args) - { - //handle invocation of other methods on mbeans - if ((args[0] instanceof ObjectName) && (method.getName().equals("invoke"))) - { - //get invoked method name - String mbeanMethod = (args.length > 1) ? (String) args[1] : null; - if (mbeanMethod == null) - { - return -1; - } - - try - { - //Get the impact attribute - MBeanInfo mbeanInfo = _mbs.getMBeanInfo((ObjectName) args[0]); - if (mbeanInfo != null) - { - MBeanOperationInfo[] opInfos = mbeanInfo.getOperations(); - for (MBeanOperationInfo opInfo : opInfos) - { - if (opInfo.getName().equals(mbeanMethod)) - { - return opInfo.getImpact(); - } - } - } - } - catch (JMException ex) - { - _logger.error("Unable to determine mbean impact for method : " + mbeanMethod, ex); - } - } - - return -1; - } - - private boolean isAccessMethod(String methodName) - { - //handle standard get/query/is methods from MBeanServer - return (methodName.startsWith("query") || methodName.startsWith("get") || methodName.startsWith("is")); - } - - /** - * Receives notifications from the MBeanServer. - */ - public void handleNotification(final Notification notification, final Object handback) - { - assert notification instanceof JMXConnectionNotification; - - final String connectionId = ((JMXConnectionNotification) notification).getConnectionId(); - final String type = notification.getType(); - - if (_logger.isDebugEnabled()) - { - _logger.debug("Notification connectionId : " + connectionId + " type : " + type - + " Notification handback : " + handback); - } - - // Normally JMXManagedObjectRegistry provides a Map as handback data containing a map - // between connection id and username. - String user = null; - if (handback instanceof Map) - { - final Map<String, String> connectionIdUsernameMap = (Map<String, String>) handback; - user = connectionIdUsernameMap.get(connectionId); - } - - // If user is still null, fallback to an unordered list of Principals from the connection id. - if (user == null) - { - final String[] splitConnectionId = connectionId.split(" "); - user = splitConnectionId[1]; - } - - if (JMXConnectionNotification.OPENED.equals(type)) - { - _logActor.message(ManagementConsoleMessages.OPEN(user)); - } - else if (JMXConnectionNotification.CLOSED.equals(type) || - JMXConnectionNotification.FAILED.equals(type)) - { - _logActor.message(ManagementConsoleMessages.CLOSE(user)); - } - } -} - diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java deleted file mode 100644 index 483b325455..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import org.apache.qpid.AMQException; - -import javax.management.JMException; -import javax.management.MalformedObjectNameException; -import javax.management.ObjectName; - -/** - * This should be implemented by all Managable objects. - */ -public interface ManagedObject -{ - static final String DOMAIN = "org.apache.qpid"; - - /** - * @return the name that uniquely identifies this object instance. It must be - * unique only among objects of this type at this level in the hierarchy so - * the uniqueness should not be too difficult to ensure. - */ - String getObjectInstanceName(); - - String getType(); - - Class<?> getManagementInterface(); - - ManagedObject getParentObject(); - - void register() throws AMQException, JMException; - - void unregister() throws AMQException; - - /** - * Returns the ObjectName required for the mbeanserver registration. - * @return ObjectName - * @throws MalformedObjectNameException - */ - ObjectName getObjectName() throws MalformedObjectNameException; -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java deleted file mode 100644 index b3323c569c..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.management; - -import org.apache.commons.configuration.ConfigurationException; - -import org.apache.qpid.common.Closeable; - -import javax.management.JMException; -import java.io.IOException; - -/** - * Handles the registration (and unregistration and so on) of managed objects. - * - * Managed objects are responsible for exposting attributes, operations and notifications. They will expose - * these outside the JVM therefore it is important not to use implementation objects directly as managed objects. - * Instead, creating inner classes and exposing those is an effective way of exposing internal state in a - * controlled way. - * - * Although we do not explictly use them while targetting Java 5, the enhanced MXBean approach in Java 6 will - * be the obvious choice for managed objects. - * - */ -public interface ManagedObjectRegistry extends Closeable -{ - void start() throws IOException, ConfigurationException; - - void registerObject(ManagedObject managedObject) throws JMException; - - void unregisterObject(ManagedObject managedObject) throws JMException; -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java index faac14f8a7..63bd1e45a0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.message; +import java.util.Collection; import java.util.Set; public interface AMQMessageHeader @@ -28,6 +29,10 @@ public interface AMQMessageHeader long getExpiration(); + String getUserId(); + + String getAppId(); + String getMessageId(); String getMimeType(); @@ -52,4 +57,5 @@ public interface AMQMessageHeader boolean containsHeader(String name); + Collection<String> getHeaderNames(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java index e87b67d242..01c1021070 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.message; +import java.util.Collection; import org.apache.qpid.framing.BasicContentHeaderProperties; import org.apache.qpid.framing.ContentHeaderBody; import org.apache.qpid.framing.FieldTable; @@ -50,6 +51,16 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader return getProperties().getExpiration(); } + public String getUserId() + { + return getProperties().getUserIdAsString(); + } + + public String getAppId() + { + return getProperties().getAppIdAsString(); + } + public String getMessageId() { return getProperties().getMessageIdAsString(); @@ -117,6 +128,13 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader return true; } + @Override + public Collection<String> getHeaderNames() + { + FieldTable ft = getProperties().getHeaders(); + return ft.keys(); + } + public boolean containsHeader(String name) { FieldTable ft = getProperties().getHeaders(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java index 583f0c09a7..e890bf5ef8 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.message; +import java.util.Collection; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.BasicContentHeaderProperties; @@ -242,6 +243,16 @@ public class MessageMetaData implements StorableMessageMetaData return (BasicContentHeaderProperties) getContentHeaderBody().getProperties(); } + public String getUserId() + { + return getProperties().getUserIdAsString(); + } + + public String getAppId() + { + return getProperties().getAppIdAsString(); + } + public String getCorrelationId() { return getProperties().getCorrelationIdAsString(); @@ -318,6 +329,12 @@ public class MessageMetaData implements StorableMessageMetaData return true; } + @Override + public Collection<String> getHeaderNames() + { + return getProperties().getHeaders().keys(); + } + public boolean containsHeader(String name) { FieldTable ft = getProperties().getHeaders(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java index 7d030fe711..2cc1a92853 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java @@ -21,11 +21,7 @@ package org.apache.qpid.server.message; import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import org.apache.qpid.amqp_1_0.codec.ValueHandler; import org.apache.qpid.amqp_1_0.messaging.SectionDecoder; import org.apache.qpid.amqp_1_0.type.AmqpErrorException; @@ -486,6 +482,18 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData return null; //TODO } + public String getAppId() + { + //TODO + return null; + } + + public String getUserId() + { + // TODO + return null; + } + public Object getHeader(final String name) { return _appProperties == null ? null : _appProperties.get(name); @@ -508,6 +516,16 @@ public class MessageMetaData_1_0 implements StorableMessageMetaData return true; } + @Override + public Collection<String> getHeaderNames() + { + if(_appProperties == null) + { + return Collections.emptySet(); + } + return Collections.unmodifiableCollection(_appProperties.keySet()); + } + public boolean containsHeader(final String name) { return _appProperties != null && _appProperties.containsKey(name); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java index 126e7c28cb..91384f7c22 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java @@ -20,14 +20,11 @@ */ package org.apache.qpid.server.message; +import java.util.*; import org.apache.qpid.transport.DeliveryProperties; import org.apache.qpid.transport.MessageDeliveryPriority; import org.apache.qpid.transport.MessageProperties; -import java.util.Map; -import java.util.Set; -import java.util.UUID; - class MessageTransferHeader implements AMQMessageHeader { @@ -60,10 +57,22 @@ class MessageTransferHeader implements AMQMessageHeader return _deliveryProps == null ? 0L : _deliveryProps.getExpiration(); } + public String getUserId() + { + byte[] userIdBytes = _messageProps == null ? null : _messageProps.getUserId(); + return userIdBytes == null ? null : new String(userIdBytes); + } + + public String getAppId() + { + byte[] appIdBytes = _messageProps == null ? null : _messageProps.getAppId(); + return appIdBytes == null ? null : new String(appIdBytes); + } + public String getMessageId() { UUID id = _messageProps == null ? null : _messageProps.getMessageId(); - + return id == null ? null : String.valueOf(id); } @@ -93,7 +102,7 @@ class MessageTransferHeader implements AMQMessageHeader public String getType() { Object type = getHeader(JMS_TYPE); - return type instanceof String ? (String) type : null; + return type instanceof String ? (String) type : null; } public String getReplyTo() @@ -145,6 +154,14 @@ class MessageTransferHeader implements AMQMessageHeader } + @Override + public Collection<String> getHeaderNames() + { + Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); + return appHeaders != null ? Collections.unmodifiableCollection(appHeaders.keySet()) : Collections.EMPTY_SET ; + + } + public boolean containsHeader(String name) { Map<String, Object> appHeaders = _messageProps == null ? null : _messageProps.getApplicationHeaders(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java new file mode 100644 index 0000000000..4fccf47e0e --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java @@ -0,0 +1,199 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +public abstract class Attribute<C extends ConfiguredObject, T> +{ + private final String _name; + public Attribute(String name) + { + _name = name; + } + + public String getName() + { + return _name; + } + + abstract public Class<T> getType(); + + public T getValue(C configuredObject) + { + Object o = configuredObject.getAttribute(_name); + if(getType().isInstance(o)) + { + return (T) o; + } + return null; + } + + public T setValue(T expected, T desired, C configuredObject) + { + return (T) configuredObject.setAttribute(_name, expected, desired); + } + + abstract public T setValue(String stringValue, C configuredObject); + + static class StringAttribute<C extends ConfiguredObject> extends Attribute<C, String> + { + + public StringAttribute(String name) + { + super(name); + } + + @Override + public Class<String> getType() + { + return String.class; + } + + @Override + public String setValue(String stringValue, C configuredObject) + { + return setValue(getValue(configuredObject), stringValue, configuredObject); + } + + } + + static class IntegerAttribute<C extends ConfiguredObject> extends Attribute<C, Integer> + { + + public IntegerAttribute(String name) + { + super(name); + } + + @Override + public Class<Integer> getType() + { + return Integer.class; + } + + @Override + public Integer setValue(String stringValue, C configuredObject) + { + try + { + Integer val = Integer.valueOf(stringValue); + return setValue(getValue(configuredObject), val, configuredObject); + } + catch (NumberFormatException e) + { + throw new IllegalArgumentException(e); + } + } + } + + + static class LongAttribute<C extends ConfiguredObject> extends Attribute<C, Long> + { + + public LongAttribute(String name) + { + super(name); + } + + @Override + public Class<Long> getType() + { + return Long.class; + } + + @Override + public Long setValue(String stringValue, C configuredObject) + { + try + { + Long val = Long.valueOf(stringValue); + return setValue(getValue(configuredObject), val, configuredObject); + } + catch (NumberFormatException e) + { + throw new IllegalArgumentException(e); + } + } + } + + + static class DoubleAttribute<C extends ConfiguredObject> extends Attribute<C, Double> + { + + public DoubleAttribute(String name) + { + super(name); + } + + @Override + public Class<Double> getType() + { + return Double.class; + } + + @Override + public Double setValue(String stringValue, C configuredObject) + { + try + { + Double val = Double.valueOf(stringValue); + return setValue(getValue(configuredObject), val, configuredObject); + } + catch (NumberFormatException e) + { + throw new IllegalArgumentException(e); + } + } + } + + + static class FloatAttribute<C extends ConfiguredObject> extends Attribute<C, Float> + { + + public FloatAttribute(String name) + { + super(name); + } + + @Override + public Class<Float> getType() + { + return Float.class; + } + + @Override + public Float setValue(String stringValue, C configuredObject) + { + try + { + Float val = Float.valueOf(stringValue); + return setValue(getValue(configuredObject), val, configuredObject); + } + catch (NumberFormatException e) + { + throw new IllegalArgumentException(e); + } + } + } + + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java index 166a2a376d..7a5927a365 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java @@ -7,9 +7,9 @@ * 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 @@ -18,17 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.management; +package org.apache.qpid.server.model; -/** - * Any object that can return a related MBean should implement this interface. - * - * This enables other classes to get the managed object, which in turn is useful when - * constructing relationships between managed objects without having to maintain - * separate data structures containing MBeans. - * - */ -public interface Managable +import java.util.Collection; + +public interface AuthenticationMethod extends ConfiguredObject { - ManagedObject getManagedObject(); + // name is the SASL mech where this is a SASL authentication + + // parents + VirtualHostAlias getVirtualHostAlias(); + AuthenticationProvider getAuthenticationProvider(); + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java new file mode 100644 index 0000000000..6000886956 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface AuthenticationProvider extends ConfiguredObject +{ + + public static final String ID = "id"; + public static final String DESCRIPTION = "description"; + public static final String NAME = "name"; + public static final String STATE = "state"; + public static final String DURABLE = "durable"; + public static final String LIFETIME_POLICY = "lifetimePolicy"; + public static final String TIME_TO_LIVE = "timeToLive"; + public static final String CREATED = "created"; + public static final String UPDATED = "updated"; + public static final String TYPE = "type"; + + public static final Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList(ID, + NAME, + DESCRIPTION, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + TYPE)); + //children + Collection<VirtualHostAlias> getVirtualHostPortBindings(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java new file mode 100644 index 0000000000..ca1de0f189 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java @@ -0,0 +1,82 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.security.AccessControlException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +public interface Broker extends ConfiguredObject +{ + + String BUILD_VERSION = "buildVersion"; + String BYTES_RETAINED = "bytesRetained"; + String OPERATING_SYSTEM = "operatingSystem"; + String PLATFORM = "platform"; + String PROCESS_PID = "processPid"; + String PRODUCT_VERSION = "productVersion"; + String STATISTICS_ENABLED = "statisticsEnabled"; + String SUPPORTED_STORE_TYPES = "supportedStoreTypes"; + String CREATED = "created"; + String DURABLE = "durable"; + String ID = "id"; + String LIFETIME_POLICY = "lifetimePolicy"; + String NAME = "name"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String UPDATED = "updated"; + + // Attributes + public static final Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList(BUILD_VERSION, + BYTES_RETAINED, + OPERATING_SYSTEM, + PLATFORM, + PROCESS_PID, + PRODUCT_VERSION, + STATISTICS_ENABLED, + SUPPORTED_STORE_TYPES, + CREATED, + DURABLE, + ID, + LIFETIME_POLICY, + NAME, + STATE, + TIME_TO_LIVE, + UPDATED)); + + //children + Collection < VirtualHost > getVirtualHosts(); + + Collection<Port> getPorts(); + + Collection<AuthenticationProvider> getAuthenticationProviders(); + + VirtualHost createVirtualHost(String name, State initialState, boolean durable, + LifetimePolicy lifetime, long ttl, Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException; + + void deleteVirtualHost(VirtualHost virtualHost) + throws AccessControlException, IllegalStateException; +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java index 6477633a9b..78b98faffe 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java @@ -30,7 +30,8 @@ public interface ConfigurationChangeListener * @param newState the state after the change */ void stateChanged(ConfiguredObject object, State oldState, State newState); - + + void childAdded(ConfiguredObject object, ConfiguredObject child); void childRemoved(ConfiguredObject object, ConfiguredObject child); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java index fb47a54d0a..414b2d083a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java @@ -22,6 +22,7 @@ package org.apache.qpid.server.model; import java.security.AccessControlException; import java.util.Collection; +import java.util.Map; import java.util.UUID; public interface ConfiguredObject @@ -81,7 +82,7 @@ public interface ConfiguredObject * @param desiredState the state the caller wishes the object to attain * @return the new current state * @throws IllegalStateTransitionException the requested state tranisition is invalid - * @throws AccessControlException the current context does not have sufficeint permissions to change the state + * @throws AccessControlException the current context does not have sufficient permissions to change the state */ State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, AccessControlException; @@ -89,7 +90,7 @@ public interface ConfiguredObject /** * Get the actual state of the object. * - * This state is derived fromt the desired state of the object itself and + * This state is derived from the desired state of the object itself and * the actual state of its parents. If an object "desires" to be ACTIVE, but one of its parents is STOPPED, then * the actual state of the object will be STOPPED * @@ -126,7 +127,7 @@ public interface ConfiguredObject /** * Returns whether the the object configuration is durably stored * - * @return the durablity + * @return the durability */ boolean isDurable(); @@ -188,7 +189,7 @@ public interface ConfiguredObject /** * Get the names of attributes that are set on this object * - * Not that the returned collection is correct at the time the method is called, but will not reflect future + * Note that the returned collection is correct at the time the method is called, but will not reflect future * additions or removals when they occur * * @return the collection of attribute names @@ -226,4 +227,20 @@ public interface ConfiguredObject * @return the Statistics holder for the ConfiguredObject (or null if none exists) */ Statistics getStatistics(); + + /** + * Return children of the ConfiguredObject of the given class + * + * @param clazz the class of the children to return + * @return the children + * + * @throws NullPointerException if the supplied class null + * + */ + <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz); + + + <C extends ConfiguredObject> C createChild(Class<C> childClass, + Map<String, Object> attributes, + ConfiguredObject... otherParents); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java index e77350c3e4..6a7d6f8f7b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java @@ -7,9 +7,9 @@ * 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 @@ -18,41 +18,21 @@ * under the License. * */ -package org.apache.qpid.server.management; - -import org.apache.log4j.Logger; +package org.apache.qpid.server.model; -import javax.management.JMException; +import java.util.Collection; -/** - * This managed object registry does not actually register MBeans. This can be used in tests when management is - * not required or when management has been disabled. - * - */ -public class NoopManagedObjectRegistry implements ManagedObjectRegistry +public class ConfiguredObjectFinder { - private static final Logger _log = Logger.getLogger(NoopManagedObjectRegistry.class); - - public NoopManagedObjectRegistry() - { - _log.info("Management is disabled"); - } - - public void start() - { - //no-op - } - - public void registerObject(ManagedObject managedObject) throws JMException - { - } - - public void unregisterObject(ManagedObject managedObject) throws JMException - { - } - - public void close() + public static <C extends ConfiguredObject> C findConfiguredObjectByName(Collection<C> configuredObjects, String name) { - + for (C configuredObject : configuredObjects) + { + if (name.equals(configuredObject.getName())) + { + return configuredObject; + } + } + return null; } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java new file mode 100644 index 0000000000..aaf6007afd --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java @@ -0,0 +1,107 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface Connection extends ConfiguredObject +{ + + // Statistics + + String BYTES_IN = "bytesIn"; + String BYTES_OUT = "bytesOut"; + String LAST_IO_TIME = "lastIoTime"; + String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins"; + String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks"; + String MESSAGES_IN = "messagesIn"; + String MESSAGES_OUT = "messagesOut"; + String SESSION_COUNT = "sessionCount"; + String STATE_CHANGED = "stateChanged"; + String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds"; + String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts"; + String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends"; + + public static final Collection<String> AVAILABLE_STATISTICS = + Collections.unmodifiableCollection( + Arrays.asList(BYTES_IN, + BYTES_OUT, + LAST_IO_TIME, + LOCAL_TRANSACTION_BEGINS, + LOCAL_TRANSACTION_ROLLBACKS, + MESSAGES_IN, + MESSAGES_OUT, + SESSION_COUNT, + STATE_CHANGED, + XA_TRANSACTION_BRANCH_ENDS, + XA_TRANSACTION_BRANCH_STARTS, + XA_TRANSACTION_BRANCH_SUSPENDS)); + + // Attributes + + public static final String ID = "id"; + public static final String NAME = "name"; + public static final String STATE = "state"; + public static final String DURABLE = "durable"; + public static final String LIFETIME_POLICY = "lifetimePolicy"; + public static final String TIME_TO_LIVE = "timeToLive"; + public static final String CREATED = "created"; + public static final String UPDATED = "updated"; + + public static final String CLIENT_ID = "clientId"; + public static final String CLIENT_VERSION = "clientVersion"; + public static final String INCOMING = "incoming"; + public static final String LOCAL_ADDRESS = "localAddress"; + public static final String PRINCIPAL = "principal"; + public static final String PROPERTIES = "properties"; + public static final String REMOTE_ADDRESS = "remoteAddress"; + public static final String REMOTE_PROCESS_NAME = "remoteProcessName"; + public static final String REMOTE_PROCESS_PID = "remoteProcessPid"; + public static final String SESSION_COUNT_LIMIT = "sessionCountLimit"; + + public static final Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableCollection( + Arrays.asList( ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + CLIENT_ID, + CLIENT_VERSION, + INCOMING, + LOCAL_ADDRESS, + PRINCIPAL, + PROPERTIES, + REMOTE_ADDRESS, + REMOTE_PROCESS_NAME, + REMOTE_PROCESS_PID, + SESSION_COUNT_LIMIT)); + + //children + Collection<Session> getSessions(); + + void delete(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Event.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Event.java new file mode 100644 index 0000000000..91b684f06e --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Event.java @@ -0,0 +1,27 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +abstract public class Event<T extends EventType> +{ + abstract public T getEventType(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java new file mode 100644 index 0000000000..edd5ce4250 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java @@ -0,0 +1,60 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.util.HashMap; +import java.util.Map; + +/** + * A type of event generated by a ConfiguredObject. + */ +public abstract class EventType<T extends EventType<T>> +{ + private static final Map<Class<? extends EventType>, Integer> EVENT_TYPES = + new HashMap<Class<? extends EventType>, Integer>(); + + private final int _classId; + + protected EventType() + { + synchronized (EVENT_TYPES) + { + if(EVENT_TYPES.containsKey(getClass())) + { + throw new IllegalArgumentException("Cannot define more one instance of the same EventType " + + getClass().getName()); + } + else + { + _classId = EVENT_TYPES.size(); + EVENT_TYPES.put(getClass(), _classId); + } + } + } + + public final int getId() + { + return _classId; + } + + abstract public Event<T> newEvent(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java index e872273d05..e63c71e955 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java @@ -77,7 +77,7 @@ public interface Exchange extends ConfiguredObject //children Collection<Binding> getBindings(); Collection<Publisher> getPublishers(); - + //operations Binding createBinding(String bindingKey, Queue queue, diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java new file mode 100644 index 0000000000..fd429321c8 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Model.java @@ -0,0 +1,97 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +public class Model +{ + private static final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>> + PARENTS = new HashMap<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>(); + + + private static final Map<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>> + CHILDREN = new HashMap<Class<? extends ConfiguredObject>, Collection<Class<? extends ConfiguredObject>>>(); + + static void addRelationship(Class<? extends ConfiguredObject> parent, Class<? extends ConfiguredObject> child) + { + Collection<Class<? extends ConfiguredObject>> parents = PARENTS.get(child); + if(parents == null) + { + parents = new ArrayList<Class<? extends ConfiguredObject>>(); + PARENTS.put(child, parents); + } + parents.add(parent); + + Collection<Class<? extends ConfiguredObject>> children = CHILDREN.get(parent); + if(children == null) + { + children = new ArrayList<Class<? extends ConfiguredObject>>(); + CHILDREN.put(parent, children); + } + children.add(child); + } + + static + { + addRelationship(Broker.class, VirtualHost.class); + addRelationship(Broker.class, Port.class); + addRelationship(Broker.class, AuthenticationProvider.class); + + addRelationship(VirtualHost.class, Exchange.class); + addRelationship(VirtualHost.class, Queue.class); + addRelationship(VirtualHost.class, Connection.class); + addRelationship(VirtualHost.class, VirtualHostAlias.class); + + addRelationship(AuthenticationProvider.class, User.class); + + addRelationship(Connection.class, Session.class); + + addRelationship(Exchange.class, Binding.class); + addRelationship(Exchange.class, Publisher.class); + + addRelationship(Queue.class, Binding.class); + addRelationship(Queue.class, Consumer.class); + + addRelationship(Session.class, Consumer.class); + addRelationship(Session.class, Publisher.class); + + } + + public static Collection<Class<? extends ConfiguredObject>> getParentTypes(Class<? extends ConfiguredObject> child) + { + Collection<Class<? extends ConfiguredObject>> parentTypes = PARENTS.get(child); + return parentTypes == null ? Collections.EMPTY_LIST + : Collections.unmodifiableCollection(parentTypes); + } + + public static Collection<Class<? extends ConfiguredObject>> getChildTypes(Class<? extends ConfiguredObject> parent) + { + Collection<Class<? extends ConfiguredObject>> childTypes = CHILDREN.get(parent); + return childTypes == null ? Collections.EMPTY_LIST + : Collections.unmodifiableCollection(childTypes); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java new file mode 100644 index 0000000000..1027e5ce8c --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java @@ -0,0 +1,46 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.io.IOException; +import java.util.Map; + +import javax.security.auth.login.AccountNotFoundException; + +public interface PasswordCredentialManagingAuthenticationProvider extends AuthenticationProvider +{ + boolean createUser(String username, String password, Map<String, String> attributes); + + void deleteUser(String user) throws AccountNotFoundException; + + void setPassword(String username, String password) throws AccountNotFoundException; + + Map<String, Map<String,String>> getUsers(); + + /** + * Refreshes the cache of user and password data from the underlying storage. + * + * If there is a failure whilst reloading the data, the implementation must + * throw an {@link IOException} and revert to using the previous cached username + * and password data. In this way, the broker will remain usable. + */ + void reload() throws IOException; +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java new file mode 100644 index 0000000000..50c0ebcd14 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Port.java @@ -0,0 +1,91 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.security.AccessControlException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface Port extends ConfiguredObject +{ + String CREATED = "created"; + String DURABLE = "durable"; + String ID = "id"; + String LIFETIME_POLICY = "lifetimePolicy"; + String NAME = "name"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String UPDATED = "updated"; + String BINDING_ADDRESS = "bindingAddress"; + String PORT = "port"; + String PROTOCOLS = "protocols"; + String TRANSPORTS = "transports"; + + // Attributes + public static final Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + BINDING_ADDRESS, + PORT, + PROTOCOLS, + TRANSPORTS + )); + + + String getBindingAddress(); + + int getPort(); + + Collection<Transport> getTransports(); + + void addTransport(Transport transport) throws IllegalStateException, + AccessControlException, + IllegalArgumentException; + + Transport removeTransport(Transport transport) throws IllegalStateException, + AccessControlException, + IllegalArgumentException; + + + Collection<Protocol> getProtocols(); + + void addProtocol(Protocol protocol) throws IllegalStateException, + AccessControlException, + IllegalArgumentException; + + Protocol removeProtocol(Protocol protocol) throws IllegalStateException, + AccessControlException, + IllegalArgumentException; + + + //children + Collection<VirtualHostAlias> getVirtualHostBindings(); + Collection<Connection> getConnections(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java new file mode 100644 index 0000000000..fecbcec194 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java @@ -0,0 +1,32 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +public enum Protocol +{ + AMQP_0_8, + AMQP_0_9, + AMQP_0_9_1, + AMQP_0_10, + AMQP_1_0, + JMX, + HTTP +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java index 7c4f0de22b..5dda4d66cd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java @@ -25,7 +25,6 @@ import java.util.Collection; import java.util.Collections; import org.apache.qpid.server.queue.QueueEntryVisitor; - public interface Queue extends ConfiguredObject { public static final String BINDING_COUNT = "bindingCount"; @@ -71,6 +70,7 @@ public interface Queue extends ConfiguredObject public static final String ID = "id"; + public static final String DESCRIPTION = "description"; public static final String NAME = "name"; public static final String STATE = "state"; public static final String DURABLE = "durable"; @@ -78,6 +78,7 @@ public interface Queue extends ConfiguredObject public static final String TIME_TO_LIVE = "timeToLive"; public static final String CREATED = "created"; public static final String UPDATED = "updated"; + public static final String ARGUMENTS = "arguments"; public static final String ALERT_REPEAT_GAP = "alertRepeatGap"; public static final String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge"; @@ -106,6 +107,7 @@ public interface Queue extends ConfiguredObject Collections.unmodifiableList( Arrays.asList(ID, NAME, + DESCRIPTION, STATE, DURABLE, LIFETIME_POLICY, @@ -143,4 +145,6 @@ public interface Queue extends ConfiguredObject void visit(QueueEntryVisitor visitor); void delete(); + + void setNotificationListener(QueueNotificationListener listener); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java index 959ca03c80..ab601f685c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java @@ -18,10 +18,11 @@ * under the License.
*
*/
-package org.apache.qpid.server.queue;
+package org.apache.qpid.server.model;
+import org.apache.qpid.server.queue.NotificationCheck;
public interface QueueNotificationListener
{
- void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg);
+ void notifyClients(NotificationCheck notification, Queue queue, String notificationMsg);
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Session.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Session.java new file mode 100644 index 0000000000..e813d0c129 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Session.java @@ -0,0 +1,82 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface Session extends ConfiguredObject +{ + // Statistics + + public static final String BYTES_IN = "bytesIn"; + public static final String BYTES_OUT = "bytesOut"; + public static final String CONSUMER_COUNT = "consumerCount"; + public static final String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins"; + public static final String LOCAL_TRANSACTION_OPEN = "localTransactionOpen"; + public static final String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks"; + public static final String STATE_CHANGED = "stateChanged"; + public static final String UNACKNOWLEDGED_BYTES = "unacknowledgedBytes"; + public static final String UNACKNOWLEDGED_MESSAGES = "unacknowledgedMessages"; + public static final String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds"; + public static final String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts"; + public static final String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends"; + + public static final Collection<String> AVAILABLE_STATISTICS = + Collections.unmodifiableCollection(Arrays.asList(BYTES_IN, BYTES_OUT, CONSUMER_COUNT, + LOCAL_TRANSACTION_BEGINS, + LOCAL_TRANSACTION_OPEN, + LOCAL_TRANSACTION_ROLLBACKS, STATE_CHANGED, + UNACKNOWLEDGED_BYTES, UNACKNOWLEDGED_MESSAGES, + XA_TRANSACTION_BRANCH_ENDS, XA_TRANSACTION_BRANCH_STARTS, + XA_TRANSACTION_BRANCH_SUSPENDS)); + + + public static final String ID = "id"; + public static final String NAME = "name"; + public static final String STATE = "state"; + public static final String DURABLE = "durable"; + public static final String LIFETIME_POLICY = "lifetimePolicy"; + public static final String TIME_TO_LIVE = "timeToLive"; + public static final String CREATED = "created"; + public static final String UPDATED = "updated"; + + public static final String CHANNEL_ID = "channelId"; + // PRODUCER_FLOW_BLOCKED is exposed as an interim step. We will expose attribute(s) that exposing + // available credit of both producer and consumer sides. + public static final String PRODUCER_FLOW_BLOCKED = "producerFlowBlocked"; + + public static final Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableCollection(Arrays.asList(ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + CHANNEL_ID, + PRODUCER_FLOW_BLOCKED)); + + Collection<Consumer> getSubscriptions(); + Collection<Publisher> getPublishers(); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java index 2cb81eae82..92d6f47741 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java @@ -1,8 +1,4 @@ -package org.apache.qpid.server.model; - -import java.util.Collection; - -/** +/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. @@ -18,6 +14,11 @@ import java.util.Collection; * See the License for the specific language governing permissions and * limitations under the License. */ + +package org.apache.qpid.server.model; + +import java.util.Collection; + public interface Statistics { Collection<String> getStatisticNames(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java new file mode 100644 index 0000000000..03cd46be01 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java @@ -0,0 +1,27 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +public enum Transport +{ + TCP, + SSL +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java index d8493c6df4..920088d61c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java @@ -40,11 +40,11 @@ public class UUIDGenerator return UUID.nameUUIDFromBytes(sb.toString().getBytes()); } - public static UUID generateExchangeUUID(String echangeName, String virtualHostName) + public static UUID generateExchangeUUID(String exchangeName, String virtualHostName) { - if(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(echangeName) || echangeName.startsWith("amq.") || echangeName.startsWith("qpid.")) + if(ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(exchangeName) || exchangeName.startsWith("amq.") || exchangeName.startsWith("qpid.")) { - return generateUUID(echangeName, virtualHostName); + return generateUUID(exchangeName, virtualHostName); } else { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java new file mode 100644 index 0000000000..d97bf46d31 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/User.java @@ -0,0 +1,59 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +public interface User extends ConfiguredObject +{ + String CREATED = "created"; + String DURABLE = "durable"; + String ID = "id"; + String LIFETIME_POLICY = "lifetimePolicy"; + String NAME = "name"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String UPDATED = "updated"; + String PASSWORD = "password"; + + // Attributes + public static final Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + PASSWORD + )); + + public String getPassword(); + + public void setPassword(String password); + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java new file mode 100644 index 0000000000..53faefc954 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -0,0 +1,154 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import org.apache.qpid.server.queue.QueueEntry; +import java.security.AccessControlException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; + +public interface VirtualHost extends ConfiguredObject +{ + // Statistics + + public static final String BYTES_IN = "bytesIn"; + public static final String BYTES_OUT = "bytesOut"; + public static final String BYTES_RETAINED = "bytesRetained"; + public static final String LOCAL_TRANSACTION_BEGINS = "localTransactionBegins"; + public static final String LOCAL_TRANSACTION_ROLLBACKS = "localTransactionRollbacks"; + public static final String MESSAGES_IN = "messagesIn"; + public static final String MESSAGES_OUT = "messagesOut"; + public static final String MESSAGES_RETAINED = "messagesRetained"; + public static final String STATE_CHANGED = "stateChanged"; + public static final String XA_TRANSACTION_BRANCH_ENDS = "xaTransactionBranchEnds"; + public static final String XA_TRANSACTION_BRANCH_STARTS = "xaTransactionBranchStarts"; + public static final String XA_TRANSACTION_BRANCH_SUSPENDS = "xaTransactionBranchSuspends"; + public static final String QUEUE_COUNT = "queueCount"; + public static final String EXCHANGE_COUNT = "exchangeCount"; + public static final String CONNECTION_COUNT = "connectionCount"; + + public static final Collection<String> AVAILABLE_STATISTICS = + Collections.unmodifiableList( + Arrays.asList(BYTES_IN, BYTES_OUT, BYTES_RETAINED, LOCAL_TRANSACTION_BEGINS, + LOCAL_TRANSACTION_ROLLBACKS, MESSAGES_IN, MESSAGES_OUT, MESSAGES_RETAINED, STATE_CHANGED, + XA_TRANSACTION_BRANCH_ENDS, XA_TRANSACTION_BRANCH_STARTS, XA_TRANSACTION_BRANCH_SUSPENDS, + QUEUE_COUNT, EXCHANGE_COUNT, CONNECTION_COUNT)); + + String ALERT_REPEAT_GAP = "alertRepeatGap"; + String ALERT_THRESHOLD_MESSAGE_AGE = "alertThresholdMessageAge"; + String ALERT_THRESHOLD_MESSAGE_SIZE = "alertThresholdMessageSize"; + String ALERT_THRESHOLD_QUEUE_DEPTH_BYTES = "alertThresholdQueueDepthBytes"; + String ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES = "alertThresholdQueueDepthMessages"; + String DEAD_LETTER_QUEUE_ENABLED = "deadLetterQueueEnabled"; + String FEDERATION_TAG = "federationTag"; + String HOUSEKEEPING_CHECK_PERIOD = "housekeepingCheckPeriod"; + String MAXIMUM_DELIVERY_ATTEMPTS = "maximumDeliveryAttempts"; + String QUEUE_FLOW_CONTROL_SIZE_BYTES = "queueFlowControlSizeBytes"; + String QUEUE_FLOW_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes"; + String STORE_CONFIGURATION = "storeConfiguration"; + String STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE = "storeTransactionIdleTimeoutClose"; + String STORE_TRANSACTION_IDLE_TIMEOUT_WARN = "storeTransactionIdleTimeoutWarn"; + String STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE = "storeTransactionOpenTimeoutClose"; + String STORE_TRANSACTION_OPEN_TIMEOUT_WARN = "storeTransactionOpenTimeoutWarn"; + String STORE_TYPE = "storeType"; + String SUPPORTED_EXCHANGE_TYPES = "supportedExchangeTypes"; + String SUPPORTED_QUEUE_TYPES = "supportedQueueTypes"; + String CREATED = "created"; + String DURABLE = "durable"; + String ID = "id"; + String LIFETIME_POLICY = "lifetimePolicy"; + String NAME = "name"; + String STATE = "state"; + String TIME_TO_LIVE = "timeToLive"; + String UPDATED = "updated"; + // Attributes + public static final Collection<String> AVAILABLE_ATTRIBUTES = + Collections.unmodifiableList( + Arrays.asList( + ID, + NAME, + STATE, + DURABLE, + LIFETIME_POLICY, + TIME_TO_LIVE, + CREATED, + UPDATED, + SUPPORTED_EXCHANGE_TYPES, + SUPPORTED_QUEUE_TYPES, + DEAD_LETTER_QUEUE_ENABLED, + FEDERATION_TAG, + HOUSEKEEPING_CHECK_PERIOD, + MAXIMUM_DELIVERY_ATTEMPTS, + QUEUE_FLOW_CONTROL_SIZE_BYTES, + QUEUE_FLOW_RESUME_SIZE_BYTES, + STORE_TYPE, + STORE_CONFIGURATION, + STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE, + STORE_TRANSACTION_IDLE_TIMEOUT_WARN, + STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE, + STORE_TRANSACTION_OPEN_TIMEOUT_WARN, + ALERT_REPEAT_GAP, + ALERT_THRESHOLD_MESSAGE_AGE, + ALERT_THRESHOLD_MESSAGE_SIZE, + ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, + ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES)); + + + + String getReplicationGroupName(); + + //children + Collection<VirtualHostAlias> getAliases(); + Collection<Connection> getConnections(); + Collection<Queue> getQueues(); + Collection<Exchange> getExchanges(); + + Exchange createExchange(String name, State initialState, boolean durable, + LifetimePolicy lifetime, long ttl, String type, Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException; + + Queue createQueue(String name, State initialState, boolean durable, + boolean exclusive, LifetimePolicy lifetime, long ttl, Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException; + + void deleteQueue(Queue queue) throws AccessControlException, IllegalStateException; + + Collection<String> getExchangeTypes(); + + public static interface Transaction + { + void dequeue(QueueEntry entry); + + void copy(QueueEntry entry, Queue queue); + + void move(QueueEntry entry, Queue queue); + + } + + public static interface TransactionalOperation + { + void withinTransaction(Transaction txn); + } + + void executeTransaction(TransactionalOperation op); +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java new file mode 100644 index 0000000000..31403d78e5 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java @@ -0,0 +1,37 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model; + +import java.security.AccessControlException; +import java.util.Collection; + +public interface VirtualHostAlias extends ConfiguredObject +{ + // parents + Port getPort(); + VirtualHost getVirtualHost(); + + // children + Collection<AuthenticationMethod> getAuthenticationMethods(); + + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java new file mode 100644 index 0000000000..78880c232d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java @@ -0,0 +1,293 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import org.apache.qpid.server.model.ConfigurationChangeListener; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.IllegalStateTransitionException; +import org.apache.qpid.server.model.State; + +abstract class AbstractAdapter implements ConfiguredObject +{ + private final Map<String,Object> _attributes = new HashMap<String, Object>(); + private final Map<Class<? extends ConfiguredObject>, ConfiguredObject> _parents = + new HashMap<Class<? extends ConfiguredObject>, ConfiguredObject>(); + private final Collection<ConfigurationChangeListener> _changeListeners = + new ArrayList<ConfigurationChangeListener>(); + + private final UUID _id; + + protected AbstractAdapter(String... names) + { + StringBuilder sb = new StringBuilder(); + for(String name : names) + { + sb.append('/').append(name); + } + _id = UUID.nameUUIDFromBytes(sb.toString().getBytes()); + } + + protected AbstractAdapter() + { + _id = UUID.randomUUID(); + } + + static String getStringAttribute(String name, Map<String,Object> attributes, String defaultVal) + { + final Object value = attributes.get(name); + return value == null ? defaultVal : String.valueOf(value); + } + + static Map getMapAttribute(String name, Map<String,Object> attributes, Map defaultVal) + { + final Object value = attributes.get(name); + if(value == null) + { + return defaultVal; + } + else if(value instanceof Map) + { + return (Map) value; + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Map"); + } + } + + + static <E extends Enum> E getEnumAttribute(Class<E> clazz, String name, Map<String,Object> attributes, E defaultVal) + { + Object obj = attributes.get(name); + if(obj == null) + { + return defaultVal; + } + else if(clazz.isInstance(obj)) + { + return (E) obj; + } + else if(obj instanceof String) + { + return (E) Enum.valueOf(clazz, (String)obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type " + clazz.getSimpleName()); + } + } + + static Boolean getBooleanAttribute(String name, Map<String,Object> attributes, Boolean defaultValue) + { + Object obj = attributes.get(name); + if(obj == null) + { + return defaultValue; + } + else if(obj instanceof Boolean) + { + return (Boolean) obj; + } + else if(obj instanceof String) + { + return Boolean.parseBoolean((String) obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Boolean"); + } + } + + static Integer getIntegerAttribute(String name, Map<String,Object> attributes, Integer defaultValue) + { + Object obj = attributes.get(name); + if(obj == null) + { + return defaultValue; + } + else if(obj instanceof Number) + { + return ((Number) obj).intValue(); + } + else if(obj instanceof String) + { + return Integer.valueOf((String) obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Integer"); + } + } + + static Long getLongAttribute(String name, Map<String,Object> attributes, Long defaultValue) + { + Object obj = attributes.get(name); + if(obj == null) + { + return defaultValue; + } + else if(obj instanceof Number) + { + return ((Number) obj).longValue(); + } + else if(obj instanceof String) + { + return Long.valueOf((String) obj); + } + else + { + throw new IllegalArgumentException("Value for attribute " + name + " is not of required type Long"); + } + } + + public final UUID getId() + { + return _id; + } + + public State getDesiredState() + { + return null; //TODO + } + + public State setDesiredState(final State currentState, final State desiredState) + throws IllegalStateTransitionException, AccessControlException + { + return null; //TODO + } + + public void addChangeListener(final ConfigurationChangeListener listener) + { + if(listener == null) + { + throw new NullPointerException("Cannot add a null listener"); + } + synchronized (this) + { + if(!_changeListeners.contains(listener)) + { + _changeListeners.add(listener); + } + } + } + + public boolean removeChangeListener(final ConfigurationChangeListener listener) + { + if(listener == null) + { + throw new NullPointerException("Cannot remove a null listener"); + } + synchronized (this) + { + return _changeListeners.remove(listener); + } + } + + + protected void childAdded(ConfiguredObject child) + { + synchronized (this) + { + for(ConfigurationChangeListener listener : _changeListeners) + { + listener.childAdded(this, child); + } + } + } + + + protected void childRemoved(ConfiguredObject child) + { + synchronized (this) + { + for(ConfigurationChangeListener listener : _changeListeners) + { + listener.childRemoved(this, child); + } + } + } + + public Object getAttribute(final String name) + { + synchronized (this) + { + return _attributes.get(name); + } + } + + public Object setAttribute(final String name, final Object expected, final Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + synchronized (this) + { + Object currentValue = _attributes.get(name); + if((currentValue == null && expected == null) + || (currentValue != null && currentValue.equals(expected))) + { + _attributes.put(name, desired); + return desired; + } + else + { + return currentValue; + } + } + } + + public <T extends ConfiguredObject> T getParent(final Class<T> clazz) + { + synchronized (this) + { + return (T) _parents.get(clazz); + } + } + + protected <T extends ConfiguredObject> void addParent(Class<T> clazz, T parent) + { + synchronized (this) + { + _parents.put(clazz, parent); + } + } + + protected <T extends ConfiguredObject> void removeParent(Class<T> clazz) + { + synchronized (this) + { + _parents.remove(clazz); + } + } + + public Collection<String> getAttributeNames() + { + synchronized(_attributes) + { + return new ArrayList<String>(_attributes.keySet()); + } + } + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java new file mode 100644 index 0000000000..8a75818f04 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java @@ -0,0 +1,487 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.io.IOException; +import java.security.AccessControlException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.security.auth.login.AccountNotFoundException; + +import org.apache.log4j.Logger; +import org.apache.qpid.server.model.*; +import org.apache.qpid.server.registry.ApplicationRegistry; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.auth.database.PrincipalDatabase; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; + +public abstract class AuthenticationProviderAdapter<T extends AuthenticationManager> extends AbstractAdapter implements AuthenticationProvider +{ + private static final Logger LOGGER = Logger.getLogger(AuthenticationProviderAdapter.class); + + private final BrokerAdapter _broker; + private final T _authManager; + + private AuthenticationProviderAdapter(BrokerAdapter brokerAdapter, + final T authManager) + { + _broker = brokerAdapter; + _authManager = authManager; + } + + public static AuthenticationProviderAdapter createAuthenticationProviderAdapter(BrokerAdapter brokerAdapter, + final AuthenticationManager authManager) + { + return authManager instanceof PrincipalDatabaseAuthenticationManager + ? new PrincipalDatabaseAuthenticationManagerAdapter(brokerAdapter, (PrincipalDatabaseAuthenticationManager) authManager) + : new SimpleAuthenticationProviderAdapter(brokerAdapter, authManager); + } + + T getAuthManager() + { + return _authManager; + } + + @Override + public Collection<VirtualHostAlias> getVirtualHostPortBindings() + { + return Collections.emptyList(); + } + + @Override + public String getName() + { + return _authManager.getClass().getSimpleName(); + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + return null; + } + + @Override + public State getActualState() + { + return null; + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public Collection<String> getAttributeNames() + { + return AuthenticationProvider.AVAILABLE_ATTRIBUTES; + } + + @Override + public Object getAttribute(String name) + { + if(TYPE.equals(name)) + { + return _authManager.getClass().getSimpleName(); + } + else if(CREATED.equals(name)) + { + // TODO + } + else if(DURABLE.equals(name)) + { + return true; + } + else if(ID.equals(name)) + { + return getId(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.PERMANENT; + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + return State.ACTIVE; // TODO + } + else if(TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if(UPDATED.equals(name)) + { + // TODO + } + return super.getAttribute(name); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + return null; + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, + Map<String, Object> attributes, + ConfiguredObject... otherParents) + { + return null; + } + + private static class SimpleAuthenticationProviderAdapter extends AuthenticationProviderAdapter<AuthenticationManager> + { + public SimpleAuthenticationProviderAdapter( + BrokerAdapter brokerAdapter, AuthenticationManager authManager) + { + super(brokerAdapter,authManager); + } + } + + private static class PrincipalDatabaseAuthenticationManagerAdapter + extends AuthenticationProviderAdapter<PrincipalDatabaseAuthenticationManager> + implements PasswordCredentialManagingAuthenticationProvider + { + public PrincipalDatabaseAuthenticationManagerAdapter( + BrokerAdapter brokerAdapter, PrincipalDatabaseAuthenticationManager authManager) + { + super(brokerAdapter, authManager); + } + + @Override + public boolean createUser(String username, String password, Map<String, String> attributes) + { + return getPrincipalDatabase().createPrincipal(new UsernamePrincipal(username), password.toCharArray()); + } + + @Override + public void deleteUser(String username) throws AccountNotFoundException + { + if(getSecurityManager().authoriseMethod(Operation.DELETE, + "UserManagement", + "deleteUser")) + { + + getPrincipalDatabase().deletePrincipal(new UsernamePrincipal(username)); + } + else + { + throw new AccessControlException("Cannot delete user " + username); + } + } + + private org.apache.qpid.server.security.SecurityManager getSecurityManager() + { + return ApplicationRegistry.getInstance().getSecurityManager(); + } + + private PrincipalDatabase getPrincipalDatabase() + { + return getAuthManager().getPrincipalDatabase(); + } + + @Override + public void setPassword(String username, String password) throws AccountNotFoundException + { + getPrincipalDatabase().updatePassword(new UsernamePrincipal(username), password.toCharArray()); + } + + public void reload() throws IOException + { + if(getSecurityManager().authoriseMethod(Operation.UPDATE, "UserManagement", "reload")) + { + getPrincipalDatabase().reload(); + } + else + { + throw new AccessControlException("Do not have permission to reload principal database"); + } + } + + @Override + public Map<String, Map<String, String>> getUsers() + { + + Map<String, Map<String,String>> users = new HashMap<String, Map<String, String>>(); + for(Principal principal : getPrincipalDatabase().getUsers()) + { + users.put(principal.getName(), Collections.EMPTY_MAP); + } + return users; + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, + Map<String, Object> attributes, + ConfiguredObject... otherParents) + { + if(childClass == User.class) + { + Principal p = new UsernamePrincipal((String) attributes.get("name")); + if(getSecurityManager().authoriseMethod(Operation.UPDATE, "UserManagement", "createUser")) + { + if(getPrincipalDatabase().createPrincipal(p, ((String)attributes.get("password")).toCharArray())) + { + return (C) new PrincipalAdapter(p); + } + } + else + { + throw new AccessControlException("Do not have permission to create a new user"); + } + + } + + return super.createChild(childClass, attributes, otherParents); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == User.class) + { + List<Principal> users = getPrincipalDatabase().getUsers(); + Collection<User> principals = new ArrayList<User>(users.size()); + for(Principal user : users) + { + principals.add(new PrincipalAdapter(user)); + } + return (Collection<C>) Collections.unmodifiableCollection(principals); + } + else + { + return super.getChildren(clazz); + } + } + + private class PrincipalAdapter extends AbstractAdapter implements User + { + private final Principal _user; + + + public PrincipalAdapter(Principal user) + { + super(PrincipalDatabaseAuthenticationManagerAdapter.this.getName(), user.getName()); + _user = user; + + } + + @Override + public String getPassword() + { + return null; + } + + @Override + public void setPassword(String password) + { + try + { + PrincipalDatabaseAuthenticationManagerAdapter.this.setPassword(_user.getName(), password); + } + catch (AccountNotFoundException e) + { + throw new IllegalStateException(e); + } + } + + @Override + public String getName() + { + return _user.getName(); + } + + @Override + public String setName(String currentName, String desiredName) + throws IllegalStateException, AccessControlException + { + throw new IllegalStateException("Names cannot be updated"); + } + + @Override + public State getActualState() + { + return State.ACTIVE; + } + + @Override + public boolean isDurable() + { + return true; + } + + @Override + public void setDurable(boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException("Durability cannot be updated"); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException("LifetimePolicy cannot be updated"); + } + + @Override + public long getTimeToLive() + { + return 0; + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException("ttl cannot be updated"); + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + return null; + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, + Map<String, Object> attributes, + ConfiguredObject... otherParents) + { + return null; + } + + @Override + public Collection<String> getAttributeNames() + { + return User.AVAILABLE_ATTRIBUTES; + } + + @Override + public Object getAttribute(String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + return super.getAttribute(name); + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + if(name.equals(PASSWORD)) + { + setPassword((String)desired); + } + return super.setAttribute(name, + expected, + desired); + } + + @Override + public State setDesiredState(State currentState, State desiredState) + throws IllegalStateTransitionException, AccessControlException + { + if(desiredState == State.DELETED) + { + try + { + deleteUser(_user.getName()); + } + catch (AccountNotFoundException e) + { + LOGGER.warn("Failed to delete user " + _user, e); + } + return State.DELETED; + } + return super.setDesiredState(currentState, desiredState); + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java new file mode 100644 index 0000000000..d3d04be70f --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java @@ -0,0 +1,222 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.apache.qpid.AMQInternalException; +import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.server.model.Binding; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; + +final class BindingAdapter extends AbstractAdapter implements Binding +{ + private final org.apache.qpid.server.binding.Binding _binding; + private Statistics _statistics = NoStatistics.getInstance(); + private final ExchangeAdapter _exchange; + private QueueAdapter _queue; + + public BindingAdapter(final org.apache.qpid.server.binding.Binding binding, + ExchangeAdapter exchangeAdapter, + QueueAdapter queueAdapter) + { + super(exchangeAdapter.getExchange().getVirtualHost().getName(), + exchangeAdapter.getName(), + queueAdapter.getName(), + binding.getBindingKey()); + _binding = binding; + _exchange = exchangeAdapter; + _queue = queueAdapter; + addParent(Queue.class, queueAdapter); + addParent(Exchange.class, exchangeAdapter); + } + + + public ExchangeAdapter getExchange() + { + return _exchange; + } + + public QueueAdapter getQueue() + { + return _queue; + } + + public String getName() + { + return _binding.getBindingKey(); + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + return null; //TODO + } + + public State getActualState() + { + return null; //TODO + } + + public boolean isDurable() + { + return _binding.getQueue().isDurable() && _binding.getExchange().isDurable(); + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + //TODO + } + + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public long getTimeToLive() + { + return 0; //TODO + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; //TODO + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + return Collections.emptySet(); + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + throw new IllegalArgumentException("Cannot add children to a binding"); + } + + public Map<String, Object> getArguments() + { + return new HashMap<String, Object> (_binding.getArguments()); + } + + public void delete() + { + try + { + _queue.getAMQQueue().getVirtualHost().getBindingFactory().removeBinding(_binding); + } + catch(AMQSecurityException e) + { + throw new AccessControlException(e.getMessage()); + } + catch(AMQInternalException e) + { + throw new IllegalStateException(e); + } + } + + @Override + public Object getAttribute(final String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + + } + else if(DURABLE.equals(name)) + { + return _queue.isDurable() && _exchange.isDurable(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return _queue.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE || _exchange.getLifetimePolicy() == LifetimePolicy.AUTO_DELETE ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT; + } + else if(TIME_TO_LIVE.equals(name)) + { + + } + else if(CREATED.equals(name)) + { + + } + else if(UPDATED.equals(name)) + { + + } + else if(EXCHANGE.equals(name)) + { + return _exchange.getName(); + } + else if(QUEUE.equals(name)) + { + return _queue.getName(); + } + else if(ARGUMENTS.equals(name)) + { + return getArguments(); + } + + return super.getAttribute(name); //TODO + } + + @Override + public Object setAttribute(final String name, final Object expected, final Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO + } + + @Override + public Collection<String> getAttributeNames() + { + return Binding.AVAILABLE_ATTRIBUTES; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java new file mode 100644 index 0000000000..ad88dbc613 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -0,0 +1,484 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.net.InetSocketAddress; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.apache.qpid.common.QpidProperties; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; +import org.apache.qpid.server.transport.QpidAcceptor; +import org.apache.qpid.server.virtualhost.VirtualHostRegistry; + +public class BrokerAdapter extends AbstractAdapter implements Broker, VirtualHostRegistry.RegistryChangeListener, + IApplicationRegistry.PortBindingListener, + IAuthenticationManagerRegistry.RegistryChangeListener +{ + + + private final IApplicationRegistry _applicationRegistry; + private String _name; + private final Map<org.apache.qpid.server.virtualhost.VirtualHost, VirtualHostAdapter> _vhostAdapters = + new HashMap<org.apache.qpid.server.virtualhost.VirtualHost, VirtualHostAdapter>(); + private final StatisticsAdapter _statistics; + private final Map<QpidAcceptor, PortAdapter> _portAdapters = new HashMap<QpidAcceptor, PortAdapter>(); + private HTTPPortAdapter _httpManagementPort; + private final Map<AuthenticationManager, AuthenticationProviderAdapter> _authManagerAdapters = + new HashMap<AuthenticationManager, AuthenticationProviderAdapter>(); + + + public BrokerAdapter(final IApplicationRegistry instance) + { + _applicationRegistry = instance; + _name = "Broker"; + _statistics = new StatisticsAdapter(instance); + + instance.getVirtualHostRegistry().addRegistryChangeListener(this); + populateVhosts(); + instance.addPortBindingListener(this); + populatePorts(); + instance.addRegistryChangeListener(this); + populateAuthenticationManagers(); + } + + private void populateVhosts() + { + synchronized(_vhostAdapters) + { + Collection<org.apache.qpid.server.virtualhost.VirtualHost> actualVhosts = + _applicationRegistry.getVirtualHostRegistry().getVirtualHosts(); + for(org.apache.qpid.server.virtualhost.VirtualHost vh : actualVhosts) + { + if(!_vhostAdapters.containsKey(vh)) + { + _vhostAdapters.put(vh, new VirtualHostAdapter(this, vh)); + } + } + + } + } + + + public Collection<VirtualHost> getVirtualHosts() + { + synchronized(_vhostAdapters) + { + return new ArrayList<VirtualHost>(_vhostAdapters.values()); + } + + } + private void populatePorts() + { + synchronized (_portAdapters) + { + Map<InetSocketAddress, QpidAcceptor> acceptors = _applicationRegistry.getAcceptors(); + + for(Map.Entry<InetSocketAddress, QpidAcceptor> entry : acceptors.entrySet()) + { + if(!_portAdapters.containsKey(entry.getValue())) + { + _portAdapters.put(entry.getValue(), new PortAdapter(this, entry.getValue(), entry.getKey())); + } + } + if(_applicationRegistry.useHTTPManagement()) + { + _httpManagementPort = new HTTPPortAdapter(this, _applicationRegistry.getHTTPManagementPort()); + } + + } + } + + public Collection<Port> getPorts() + { + synchronized (_portAdapters) + { + final ArrayList<Port> ports = new ArrayList<Port>(_portAdapters.values()); + if(_httpManagementPort != null) + { + ports.add(_httpManagementPort); + } + return ports; + } + } + + private void populateAuthenticationManagers() + { + synchronized (_authManagerAdapters) + { + IAuthenticationManagerRegistry authenticationManagerRegistry = + _applicationRegistry.getAuthenticationManagerRegistry(); + if(authenticationManagerRegistry != null) + { + Map<String, AuthenticationManager> authenticationManagers = + authenticationManagerRegistry.getAvailableAuthenticationManagers(); + + for(Map.Entry<String, AuthenticationManager> entry : authenticationManagers.entrySet()) + { + if(!_authManagerAdapters.containsKey(entry.getValue())) + { + _authManagerAdapters.put(entry.getValue(), + AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this, + entry.getValue())); + } + } + } + } + } + + public Collection<AuthenticationProvider> getAuthenticationProviders() + { + synchronized (_authManagerAdapters) + { + final ArrayList<AuthenticationProvider> authManagers = + new ArrayList<AuthenticationProvider>(_authManagerAdapters.values()); + return authManagers; + } + + } + + public VirtualHost createVirtualHost(final String name, + final State initialState, + final boolean durable, + final LifetimePolicy lifetime, + final long ttl, + final Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public VirtualHost createVirtualHost(final Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public void deleteVirtualHost(final VirtualHost vhost) + throws AccessControlException, IllegalStateException + { + //TODO + throw new UnsupportedOperationException("Not yet implemented"); + } + + public String getName() + { + return _name; + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + return null; //TODO + } + + + public State getActualState() + { + return null; //TODO + } + + + public boolean isDurable() + { + return true; + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + public long getTimeToLive() + { + return 0; + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == VirtualHost.class) + { + return (Collection<C>) getVirtualHosts(); + } + else if(clazz == Port.class) + { + return (Collection<C>) getPorts(); + } + else if(clazz == AuthenticationProvider.class) + { + return (Collection<C>) getAuthenticationProviders(); + } + + return Collections.emptySet(); + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + if(childClass == VirtualHost.class) + { + return (C) createVirtualHost(attributes); + } + else if(childClass == Port.class) + { + return (C) createPort(attributes); + } + else if(childClass == AuthenticationProvider.class) + { + return (C) createAuthenticationProvider(attributes); + } + else + { + throw new IllegalArgumentException("Cannot create child of class " + childClass.getSimpleName()); + } + } + + private Port createPort(Map<String, Object> attributes) + { + // TODO + return null; + } + + private AuthenticationProvider createAuthenticationProvider(Map<String,Object> attributes) + { + // TODO + return null; + } + + + public void virtualHostRegistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost) + { + VirtualHostAdapter adapter = null; + synchronized (_vhostAdapters) + { + if(!_vhostAdapters.containsKey(virtualHost)) + { + adapter = new VirtualHostAdapter(this, virtualHost); + _vhostAdapters.put(virtualHost, adapter); + } + } + if(adapter != null) + { + childAdded(adapter); + } + } + + public void virtualHostUnregistered(org.apache.qpid.server.virtualhost.VirtualHost virtualHost) + { + VirtualHostAdapter adapter = null; + + synchronized (_vhostAdapters) + { + adapter = _vhostAdapters.remove(virtualHost); + } + if(adapter != null) + { + childRemoved(adapter); + } + } + + @Override + public void authenticationManagerRegistered(AuthenticationManager authenticationManager) + { + AuthenticationProviderAdapter adapter = null; + synchronized (_authManagerAdapters) + { + if(!_authManagerAdapters.containsKey(authenticationManager)) + { + adapter = + AuthenticationProviderAdapter.createAuthenticationProviderAdapter(this, authenticationManager); + _authManagerAdapters.put(authenticationManager, adapter); + } + } + if(adapter != null) + { + childAdded(adapter); + } + } + + @Override + public void authenticationManagerUnregistered(AuthenticationManager authenticationManager) + { + AuthenticationProviderAdapter adapter; + synchronized (_authManagerAdapters) + { + adapter = _authManagerAdapters.remove(authenticationManager); + } + if(adapter != null) + { + childRemoved(adapter); + } + } + + + @Override + public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress) + { + synchronized (_portAdapters) + { + if(!_portAdapters.containsKey(acceptor)) + { + PortAdapter adapter = new PortAdapter(this, acceptor, bindAddress); + _portAdapters.put(acceptor, adapter); + childAdded(adapter); + } + } + } + + @Override + public void unbound(QpidAcceptor acceptor) + { + PortAdapter adapter = null; + + synchronized (_portAdapters) + { + adapter = _portAdapters.remove(acceptor); + } + if(adapter != null) + { + childRemoved(adapter); + } + } + + @Override + public Collection<String> getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + @Override + public Object getAttribute(String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + return State.ACTIVE; + } + else if(DURABLE.equals(name)) + { + return isDurable(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.PERMANENT; + } + else if(TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if(CREATED.equals(name)) + { + // TODO + } + else if(UPDATED.equals(name)) + { + // TODO + } + else if(BUILD_VERSION.equals(name)) + { + return QpidProperties.getBuildVersion(); + } + else if(BYTES_RETAINED.equals(name)) + { + // TODO + } + else if(OPERATING_SYSTEM.equals(name)) + { + return System.getProperty("os.name") + " " + + System.getProperty("os.version") + " " + + System.getProperty("os.arch"); + } + else if(PLATFORM.equals(name)) + { + return System.getProperty("java.vendor") + " " + + System.getProperty("java.runtime.version", System.getProperty("java.version")); + } + else if(PROCESS_PID.equals(name)) + { + // TODO + } + else if(PRODUCT_VERSION.equals(name)) + { + return QpidProperties.getReleaseVersion(); + } + else if(STATISTICS_ENABLED.equals(name)) + { + // TODO + } + else if(SUPPORTED_STORE_TYPES.equals(name)) + { + // TODO + } + + return super.getAttribute(name); //TODO - Implement. + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO - Implement. + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java new file mode 100644 index 0000000000..8114156e3a --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java @@ -0,0 +1,315 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import org.apache.qpid.AMQException; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Session; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.stats.StatisticsGatherer; + +final class ConnectionAdapter extends AbstractAdapter implements Connection +{ + + + + + private AMQConnectionModel _connection; + + private final Map<AMQSessionModel, SessionAdapter> _sessionAdapters = + new HashMap<AMQSessionModel, SessionAdapter>(); + private final Statistics _statistics; + + public ConnectionAdapter(final AMQConnectionModel conn) + { + _connection = conn; + _statistics = new ConnectionStatisticsAdapter(conn); + } + + public Collection<Session> getSessions() + { + List<AMQSessionModel> actualSessions = _connection.getSessionModels(); + + synchronized (_sessionAdapters) + { + for(AMQSessionModel session : _sessionAdapters.keySet()) + { + if(!actualSessions.contains(session)) + { + _sessionAdapters.remove(session); + } + } + for(AMQSessionModel session : actualSessions) + { + if(!_sessionAdapters.containsKey(session)) + { + _sessionAdapters.put(session, new SessionAdapter(session)); + } + } + return new ArrayList<Session>(_sessionAdapters.values()); + } + } + + public void delete() + { + try + { + _connection.close(AMQConstant.CONNECTION_FORCED, "Connection closed by external action"); + } + catch(AMQException e) + { + throw new IllegalStateException(e); + } + } + + public String getName() + { + final String remoteAddressString = _connection.getRemoteAddressString(); + return remoteAddressString.replaceAll("/",""); + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + return null; //TODO + } + + public State getActualState() + { + return null; //TODO + } + + public boolean isDurable() + { + return false; //TODO + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + //TODO + } + + public LifetimePolicy getLifetimePolicy() + { + return null; //TODO + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public long getTimeToLive() + { + return 0; //TODO + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; //TODO + } + + @Override + public Object getAttribute(String name) + { + + if(name.equals(ID)) + { + return getId(); + } + else if (name.equals(NAME)) + { + return getName(); + } + else if(name.equals(CLIENT_ID)) + { + return _connection.getClientId(); + } + else if(name.equals(CLIENT_VERSION)) + { + return _connection.getClientVersion(); + } + else if(name.equals(INCOMING)) + { + + } + else if(name.equals(LOCAL_ADDRESS)) + { + + } + else if(name.equals(PRINCIPAL)) + { + return _connection.getPrincipalAsString(); + } + else if(name.equals(PROPERTIES)) + { + + } + else if(name.equals(REMOTE_ADDRESS)) + { + return _connection.getRemoteAddressString(); + } + else if(name.equals(REMOTE_PROCESS_NAME)) + { + + } + else if(name.equals(REMOTE_PROCESS_PID)) + { + + } + else if(name.equals(SESSION_COUNT_LIMIT)) + { + return _connection.getSessionCountLimit(); + } + return super.getAttribute(name); + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException + { + if(name.equals(CLIENT_ID)) + { + + } + else if(name.equals(CLIENT_VERSION)) + { + + } + else if(name.equals(INCOMING)) + { + + } + else if(name.equals(LOCAL_ADDRESS)) + { + + } + else if(name.equals(PRINCIPAL)) + { + + } + else if(name.equals(PROPERTIES)) + { + + } + else if(name.equals(REMOTE_ADDRESS)) + { + + } + else if(name.equals(REMOTE_PROCESS_NAME)) + { + + } + else if(name.equals(REMOTE_PROCESS_PID)) + { + + } + else if(name.equals(SESSION_COUNT_LIMIT)) + { + + } + return super.setAttribute(name, expected, desired); + } + + @Override + public Collection<String> getAttributeNames() + { + final HashSet<String> attrNames = new HashSet<String>(super.getAttributeNames()); + attrNames.addAll(Connection.AVAILABLE_ATTRIBUTES); + return Collections.unmodifiableCollection(attrNames); + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == Session.class) + { + return (Collection<C>) getSessions(); + } + else + { + return Collections.emptySet(); + } + } + + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + if(childClass == Session.class) + { + throw new IllegalStateException(); + } + else + { + throw new IllegalArgumentException("Cannot create a child of class " + childClass.getSimpleName()); + } + + } + + private class ConnectionStatisticsAdapter extends StatisticsAdapter + { + public ConnectionStatisticsAdapter(StatisticsGatherer applicationRegistry) + { + super(applicationRegistry); + } + + @Override + public Collection<String> getStatisticNames() + { + return Connection.AVAILABLE_STATISTICS; + } + + @Override + public Object getStatistic(String name) + { + if(LAST_IO_TIME.equals(name)) + { + return _connection.getLastIoTime(); + } + else if(SESSION_COUNT.equals(name)) + { + return _connection.getSessionModels().size(); + } + return super.getStatistic(name); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java new file mode 100644 index 0000000000..6fb6f4971d --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java @@ -0,0 +1,225 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.util.Map; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Consumer; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.subscription.Subscription; + +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; + +public class ConsumerAdapter extends AbstractAdapter implements Consumer +{ + private final Subscription _subscription; + private final QueueAdapter _queue; + private final ConsumerStatistics _statistics; + + public ConsumerAdapter(final QueueAdapter queueAdapter, final Subscription subscription) + { + super(queueAdapter.getVirtualHost().getName(), + queueAdapter.getName(), + subscription.getSessionModel().getConnectionModel().getRemoteAddressString(), + String.valueOf(subscription.getSessionModel().getChannelId()), + subscription.getConsumerName() ); + + _subscription = subscription; + _queue = queueAdapter; + _statistics = new ConsumerStatistics(); + //TODO + } + + public String getName() + { + return _subscription.getConsumerName(); + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + return null; //TODO + } + + public State getActualState() + { + return null; //TODO + } + + public boolean isDurable() + { + return false; //TODO + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + //TODO + } + + public LifetimePolicy getLifetimePolicy() + { + return null; //TODO + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public long getTimeToLive() + { + return 0; //TODO + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; //TODO + } + + @Override + public Collection<String> getAttributeNames() + { + return Consumer.AVAILABLE_ATTRIBUTES; + } + + @Override + public Object setAttribute(final String name, final Object expected, final Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO + } + + @Override + public Object getAttribute(final String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + + } + else if(DURABLE.equals(name)) + { + return false; + } + else if(LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.AUTO_DELETE; + } + else if(TIME_TO_LIVE.equals(name)) + { + + } + else if(CREATED.equals(name)) + { + + } + else if(UPDATED.equals(name)) + { + + } + else if(DISTRIBUTION_MODE.equals(name)) + { + return _subscription.acquires() ? "MOVE" : "COPY"; + } + else if(SETTLEMENT_MODE.equals(name)) + { + + } + else if(EXCLUSIVE.equals(name)) + { + + } + else if(NO_LOCAL.equals(name)) + { + + } + else if(SELECTOR.equals(name)) + { + + } + return super.getAttribute(name); //TODO + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + return Collections.emptySet(); + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + throw new IllegalArgumentException(); + } + + private class ConsumerStatistics implements Statistics + { + + public Collection<String> getStatisticNames() + { + return AVAILABLE_STATISTICS; + } + + public Object getStatistic(String name) + { + if(name.equals(BYTES_OUT)) + { + return _subscription.getBytesOut(); + } + else if(name.equals(MESSAGES_OUT)) + { + return _subscription.getMessagesOut(); + } + else if(name.equals(STATE_CHANGED)) + { + + } + else if(name.equals(UNACKNOWLEDGED_BYTES)) + { + return _subscription.getUnacknowledgedBytes(); + } + else if(name.equals(UNACKNOWLEDGED_MESSAGES)) + { + return _subscription.getUnacknowledgedMessages(); + } + return null; // TODO - Implement + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java new file mode 100644 index 0000000000..dd22804355 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java @@ -0,0 +1,409 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQInternalException; +import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Publisher; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.virtualhost.VirtualHost; + +final class ExchangeAdapter extends AbstractAdapter implements Exchange, org.apache.qpid.server.exchange.Exchange.BindingListener +{ + + private final org.apache.qpid.server.exchange.Exchange _exchange; + private final Map<Binding, BindingAdapter> _bindingAdapters = + new HashMap<Binding, BindingAdapter>(); + private VirtualHostAdapter _vhost; + private final ExchangeStatistics _statistics; + + + public ExchangeAdapter(final VirtualHostAdapter virtualHostAdapter, + final org.apache.qpid.server.exchange.Exchange exchange) + { + super(virtualHostAdapter.getName(), exchange.getName()); + _statistics = new ExchangeStatistics(); + _vhost = virtualHostAdapter; + _exchange = exchange; + addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter); + + exchange.addBindingListener(this); + populateBindings(); + } + + private void populateBindings() + { + Collection<Binding> actualBindings = _exchange.getBindings(); + synchronized (_bindingAdapters) + { + for(Binding binding : actualBindings) + { + if(!_bindingAdapters.containsKey(binding)) + { + QueueAdapter queueAdapter = _vhost.getQueueAdapter(binding.getQueue()); + BindingAdapter adapter = new BindingAdapter(binding, this, queueAdapter); + _bindingAdapters.put(binding, adapter); + + queueAdapter.bindingRegistered(binding, adapter); + } + } + } + + } + + public String getExchangeType() + { + return _exchange.getType().getName().toString(); + } + + public Collection<org.apache.qpid.server.model.Binding> getBindings() + { + synchronized (_bindingAdapters) + { + return new ArrayList<org.apache.qpid.server.model.Binding>(_bindingAdapters.values()); + } + + } + + public Collection<Publisher> getPublishers() + { + // TODO + return Collections.emptyList(); + } + + + public org.apache.qpid.server.model.Binding createBinding(Queue queue, + Map<String, Object> attributes) + throws AccessControlException, IllegalStateException + { + attributes = new HashMap<String, Object>(attributes); + String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, ""); + Map<String, Object> bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP); + + attributes.remove(org.apache.qpid.server.model.Binding.NAME); + attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS); + + return createBinding(bindingKey, queue, bindingArgs, attributes); + + } + + public org.apache.qpid.server.model.Binding createBinding(String bindingKey, Queue queue, + Map<String, Object> bindingArguments, + Map<String, Object> attributes) + throws AccessControlException, IllegalStateException + { + VirtualHost virtualHost = _vhost.getVirtualHost(); + + + AMQQueue amqQueue = ((QueueAdapter)queue).getAMQQueue(); + + try + { + if(!virtualHost.getBindingFactory().addBinding(bindingKey, amqQueue, _exchange, bindingArguments)) + { + Binding oldBinding = virtualHost.getBindingFactory().getBinding(bindingKey, amqQueue, _exchange, + bindingArguments); + + Map<String, Object> oldArgs = oldBinding.getArguments(); + if((oldArgs == null && !bindingArguments.isEmpty()) || (oldArgs != null && !oldArgs.equals(bindingArguments))) + { + //TODO: generate deterministic UUID + virtualHost.getBindingFactory().replaceBinding(UUIDGenerator.generateUUID(), bindingKey, amqQueue, _exchange, bindingArguments); + } + } + Binding binding = virtualHost.getBindingFactory().getBinding(bindingKey, amqQueue, _exchange, bindingArguments); + + synchronized (_bindingAdapters) + { + return binding == null ? null : _bindingAdapters.get(binding); + } + } + catch(AMQSecurityException e) + { + throw new AccessControlException(e.toString()); + } + catch(AMQInternalException e) + { + throw new IllegalStateException(e); + } + } + + public void delete() + { + try + { + _vhost.getVirtualHost().getExchangeRegistry().unregisterExchange(getName(), false); + } + catch(AMQException e) + { + throw new IllegalStateException(e); + } + } + + public String getName() + { + return _exchange.getName(); + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + return null; //TODO + } + + public State getActualState() + { + return null; //TODO + } + + public boolean isDurable() + { + return _exchange.isDurable(); + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + //TODO + } + + public LifetimePolicy getLifetimePolicy() + { + return _exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT; + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public long getTimeToLive() + { + return 0; //TODO + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; //TODO + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == org.apache.qpid.server.model.Binding.class) + { + return (Collection<C>) getBindings(); + } + else + { + return Collections.emptySet(); + } + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + if(childClass == org.apache.qpid.server.model.Binding.class) + { + if(otherParents != null && otherParents.length == 1 && otherParents[0] instanceof Queue) + { + Queue queue = (Queue) otherParents[0]; + if(queue.getParent(org.apache.qpid.server.model.VirtualHost.class) == getParent(org.apache.qpid.server.model.VirtualHost.class)) + { + return (C) createBinding(queue, attributes); + } + else + { + throw new IllegalArgumentException("Queue and Exchange parents of a binding must be on same virtual host"); + } + } + else + { + throw new IllegalArgumentException("Other parent must be a queue"); + } + } + else + { + throw new IllegalArgumentException(); + } + } + + public void bindingAdded(org.apache.qpid.server.exchange.Exchange exchange, Binding binding) + { + BindingAdapter adapter = null; + synchronized (_bindingAdapters) + { + if(!_bindingAdapters.containsKey(binding)) + { + QueueAdapter queueAdapter = _vhost.getQueueAdapter(binding.getQueue()); + adapter = new BindingAdapter(binding, this, queueAdapter); + _bindingAdapters.put(binding,adapter); + queueAdapter.bindingRegistered(binding,adapter); + } + } + if(adapter != null) + { + childAdded(adapter); + } + } + + public void bindingRemoved(org.apache.qpid.server.exchange.Exchange exchange, Binding binding) + { + BindingAdapter adapter = null; + synchronized (_bindingAdapters) + { + adapter = _bindingAdapters.remove(binding); + } + if(adapter != null) + { + _vhost.getQueueAdapter(binding.getQueue()).bindingUnregistered(binding); + childRemoved(adapter); + } + } + + org.apache.qpid.server.exchange.Exchange getExchange() + { + return _exchange; + } + + @Override + public Object getAttribute(String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + return State.ACTIVE; + } + else if(DURABLE.equals(name)) + { + return isDurable(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return _exchange.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT; + } + else if(TIME_TO_LIVE.equals(name)) + { + + } + else if(CREATED.equals(name)) + { + + } + else if(UPDATED.equals(name)) + { + + } + else if(ALTERNATE_EXCHANGE.equals(name)) + { + return _exchange.getAlternateExchange(); + } + else if(TYPE.equals(name)) + { + return _exchange.getType().getName().asString(); + } + return super.getAttribute(name); + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO - Implement + } + + @Override + public Collection<String> getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + private class ExchangeStatistics implements Statistics + { + + public Collection<String> getStatisticNames() + { + return AVAILABLE_STATISTICS; + } + + public Object getStatistic(String name) + { + if(BINDING_COUNT.equals(name)) + { + return _exchange.getBindingCount(); + } + else if(BYTES_DROPPED.equals(name)) + { + return _exchange.getByteDrops(); + } + else if(BYTES_IN.equals(name)) + { + return _exchange.getByteReceives(); + } + else if(MESSAGES_DROPPED.equals(name)) + { + return _exchange.getMsgDrops(); + } + else if(MESSAGES_IN.equals(name)) + { + return _exchange.getMsgReceives(); + } + else if(PRODUCER_COUNT.equals(name)) + { + + } + else if(STATE_CHANGED.equals(name)) + { + + } + return null; // TODO - Implement + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java new file mode 100644 index 0000000000..fdcc5e0184 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java @@ -0,0 +1,262 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.VirtualHostAlias; + +public class HTTPPortAdapter extends AbstractAdapter implements Port +{ + private final BrokerAdapter _broker; + private int _port; + public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port) + { + _broker = brokerAdapter; + _port = port; + + } + + @Override + public String getBindingAddress() + { + return "0.0.0.0"; + } + + @Override + public int getPort() + { + return _port; + } + + @Override + public Collection<Transport> getTransports() + { + return Collections.singleton(Transport.TCP); + } + + @Override + public void addTransport(Transport transport) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Transport removeTransport(Transport transport) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Collection<Protocol> getProtocols() + { + return Collections.singleton(Protocol.HTTP); + } + + @Override + public void addProtocol(Protocol protocol) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Protocol removeProtocol(Protocol protocol) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Collection<VirtualHostAlias> getVirtualHostBindings() + { + return Collections.emptySet(); + } + + @Override + public Collection<Connection> getConnections() + { + return Collections.emptySet(); // TODO - Implement + } + + @Override + public String getName() + { + return getBindingAddress() + ":" + getPort(); // TODO - Implement + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public State getActualState() + { + return State.ACTIVE; + } + + @Override + public boolean isDurable() + { + return false; // TODO - Implement + } + + @Override + public void setDurable(boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public long getTimeToLive() + { + return 0; // TODO - Implement + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == Connection.class) + { + return (Collection<C>) getConnections(); + } + else + { + return Collections.emptySet(); + } + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAttribute(String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + return getActualState(); + } + else if(DURABLE.equals(name)) + { + return isDurable(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return getLifetimePolicy(); + } + else if(TIME_TO_LIVE.equals(name)) + { + return getTimeToLive(); + } + else if(CREATED.equals(name)) + { + + } + else if(UPDATED.equals(name)) + { + + } + else if(BINDING_ADDRESS.equals(name)) + { + return getBindingAddress(); + } + else if(PORT.equals(name)) + { + return getPort(); + } + else if(PROTOCOLS.equals(name)) + { + return getProtocols(); + } + else if(TRANSPORTS.equals(name)) + { + return getTransports(); + } + + return super.getAttribute(name); //TODO - Implement + } + + @Override + public Collection<String> getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO - Implement + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java new file mode 100644 index 0000000000..b83887ffe5 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java @@ -0,0 +1,46 @@ +package org.apache.qpid.server.model.adapter; + +import org.apache.qpid.server.model.Statistics; + +import java.util.Collection; +import java.util.Collections; + +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 + * <p/> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p/> + * 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. + */ +public class NoStatistics implements Statistics +{ + private static final NoStatistics INSTANCE = new NoStatistics(); + + private NoStatistics() + { + } + + public Collection<String> getStatisticNames() + { + return Collections.emptyList(); + } + + public Object getStatistic(String name) + { + return null; + } + + public static NoStatistics getInstance() + { + return INSTANCE; + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java new file mode 100644 index 0000000000..0021431ee3 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java @@ -0,0 +1,318 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.util.Map; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.transport.QpidAcceptor; + +import java.net.InetSocketAddress; +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +public class PortAdapter extends AbstractAdapter implements Port +{ + private final BrokerAdapter _broker; + private final QpidAcceptor _acceptor; + private final InetSocketAddress _address; + private final Collection<Protocol> _protocols; + + public PortAdapter(BrokerAdapter brokerAdapter, QpidAcceptor acceptor, InetSocketAddress address) + { + _broker = brokerAdapter; + _acceptor = acceptor; + _address = address; + + List<Protocol> protocols = new ArrayList<Protocol>(); + + for(AmqpProtocolVersion pv : _acceptor.getSupported()) + { + switch(pv) + { + case v0_8: + protocols.add(Protocol.AMQP_0_8); + break; + case v0_9: + protocols.add(Protocol.AMQP_0_9); + break; + case v0_9_1: + protocols.add(Protocol.AMQP_0_9_1); + break; + case v0_10: + protocols.add(Protocol.AMQP_0_10); + break; + case v1_0_0: + protocols.add(Protocol.AMQP_1_0); + break; + } + } + + _protocols = Collections.unmodifiableCollection(protocols); + + } + + @Override + public String getBindingAddress() + { + return _address.getHostName(); + } + + @Override + public int getPort() + { + return _address.getPort(); + } + + @Override + public Collection<Transport> getTransports() + { + switch (_acceptor.getTransport()) + { + case TCP: + return Collections.singleton(Transport.TCP); + case SSL: + return Collections.singleton(Transport.SSL); + } + + return null; // TODO - Implement + } + + @Override + public void addTransport(Transport transport) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Transport removeTransport(Transport transport) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Collection<Protocol> getProtocols() + { + return _protocols; + } + + @Override + public void addProtocol(Protocol protocol) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Protocol removeProtocol(Protocol protocol) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Collection<VirtualHostAlias> getVirtualHostBindings() + { + List<VirtualHostAlias> aliases = new ArrayList<VirtualHostAlias>(); + for(VirtualHost vh : _broker.getVirtualHosts()) + { + for(VirtualHostAlias alias : vh.getAliases()) + { + if(alias.getPort().equals(this)) + { + aliases.add(alias); + } + } + } + return Collections.unmodifiableCollection(aliases); + } + + @Override + public Collection<Connection> getConnections() + { + return null; // TODO - Implement + } + + @Override + public String getName() + { + return getBindingAddress() + ":" + getPort(); // TODO - Implement + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public State getActualState() + { + return State.ACTIVE; + } + + @Override + public boolean isDurable() + { + return false; // TODO - Implement + } + + @Override + public void setDurable(boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public long getTimeToLive() + { + return 0; // TODO - Implement + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == Connection.class) + { + return (Collection<C>) getConnections(); + } + else + { + return Collections.emptySet(); + } + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + throw new UnsupportedOperationException(); + } + + @Override + public Object getAttribute(String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + return getActualState(); + } + else if(DURABLE.equals(name)) + { + return isDurable(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return getLifetimePolicy(); + } + else if(TIME_TO_LIVE.equals(name)) + { + return getTimeToLive(); + } + else if(CREATED.equals(name)) + { + + } + else if(UPDATED.equals(name)) + { + + } + else if(BINDING_ADDRESS.equals(name)) + { + return getBindingAddress(); + } + else if(PORT.equals(name)) + { + return getPort(); + } + else if(PROTOCOLS.equals(name)) + { + return getProtocols(); + } + else if(TRANSPORTS.equals(name)) + { + return getTransports(); + } + + return super.getAttribute(name); //TODO - Implement + } + + @Override + public Collection<String> getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO - Implement + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java new file mode 100644 index 0000000000..5c35fe5f7b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java @@ -0,0 +1,702 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.apache.qpid.AMQException; +import org.apache.qpid.AMQStoreException; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.ConfiguredObjectFinder; +import org.apache.qpid.server.model.Consumer; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.QueueNotificationListener; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.queue.*; +import org.apache.qpid.server.subscription.Subscription; + +final class QueueAdapter extends AbstractAdapter implements Queue, AMQQueue.SubscriptionRegistrationListener, AMQQueue.NotificationListener +{ + + static final Map<String, String> ATTRIBUTE_MAPPINGS = new HashMap<String, String>(); + static + { + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_REPEAT_GAP, "x-qpid-minimum-alert-repeat-gap"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_AGE, "x-qpid-maximum-message-size"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, "x-qpid-maximum-message-age"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, "x-qpid-maximum-message-count"); + + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.MAXIMUM_DELIVERY_ATTEMPTS, "x-qpid-maximum-delivery-count"); + + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_CONTROL_SIZE_BYTES, "x-qpid-capacity"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.QUEUE_FLOW_RESUME_SIZE_BYTES, "x-qpid-flow-resume-capacity"); + + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.SORT_KEY, "qpid.sort_key"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.LVQ_KEY, "qpid.last_value_queue_key"); + + } + + private final AMQQueue _queue; + private final Map<Binding, BindingAdapter> _bindingAdapters = + new HashMap<Binding, BindingAdapter>(); + private Map<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter> _consumerAdapters = + new HashMap<org.apache.qpid.server.subscription.Subscription, ConsumerAdapter>(); + + + private final VirtualHostAdapter _vhost; + private QueueStatisticsAdapter _statistics; + private QueueNotificationListener _queueNotificationListener; + + public QueueAdapter(final VirtualHostAdapter virtualHostAdapter, final AMQQueue queue) + { + super(virtualHostAdapter.getName(), queue.getName()); + _vhost = virtualHostAdapter; + addParent(org.apache.qpid.server.model.VirtualHost.class, virtualHostAdapter); + + _queue = queue; + _queue.addSubscriptionRegistrationListener(this); + populateConsumers(); + _statistics = new QueueStatisticsAdapter(queue); + _queue.setNotificationListener(this); + } + + private void populateConsumers() + { + Collection<org.apache.qpid.server.subscription.Subscription> actualSubscriptions = _queue.getConsumers(); + + synchronized (_consumerAdapters) + { + Iterator<org.apache.qpid.server.subscription.Subscription> iter = _consumerAdapters.keySet().iterator(); + for(org.apache.qpid.server.subscription.Subscription subscription : actualSubscriptions) + { + if(!_consumerAdapters.containsKey(subscription)) + { + _consumerAdapters.put(subscription, new ConsumerAdapter(this, subscription)); + } + } + } + } + + public Collection<org.apache.qpid.server.model.Binding> getBindings() + { + synchronized (_bindingAdapters) + { + return new ArrayList<org.apache.qpid.server.model.Binding>(_bindingAdapters.values()); + } + } + + public Collection<Consumer> getConsumers() + { + synchronized (_consumerAdapters) + { + return new ArrayList<Consumer>(_consumerAdapters.values()); + } + + } + + public void visit(final QueueEntryVisitor visitor) + { + _queue.visit(visitor); + } + + public void delete() + { + try + { + _queue.delete(); + if (_queue.isDurable()) + { + + _queue.getVirtualHost().getMessageStore().removeQueue(_queue); + } + } + catch(AMQException e) + { + throw new IllegalStateException(e); + } + } + + public String getName() + { + return _queue.getName(); + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + return null; //TODO + } + + public State getActualState() + { + return null; //TODO + } + + public boolean isDurable() + { + return _queue.isDurable(); + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + //TODO + } + + public LifetimePolicy getLifetimePolicy() + { + return _queue.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT; + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public long getTimeToLive() + { + return 0; //TODO + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; //TODO + } + + + @Override + public Collection<String> getAttributeNames() + { + return Queue.AVAILABLE_ATTRIBUTES; + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) throws IllegalStateException, AccessControlException, IllegalArgumentException + { + try + { + if(ALERT_REPEAT_GAP.equals(name)) + { + _queue.setMinimumAlertRepeatGap((Long)desired); + return desired; + } + else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name)) + { + _queue.setMaximumMessageAge((Long)desired); + return desired; + } + else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name)) + { + _queue.setMaximumMessageSize((Long)desired); + return desired; + } + else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name)) + { + _queue.setMaximumQueueDepth((Long)desired); + return desired; + } + else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name)) + { + _queue.setMaximumMessageCount((Long)desired); + return desired; + } + else if(ALTERNATE_EXCHANGE.equals(name)) + { + // In future we may want to accept a UUID as an alternative way to identifying the exchange + ExchangeAdapter alternateExchange = (ExchangeAdapter) desired; + _queue.setAlternateExchange(alternateExchange == null ? null : alternateExchange.getExchange()); + return desired; + } + else if(EXCLUSIVE.equals(name)) + { + Boolean exclusiveFlag = (Boolean) desired; + _queue.setExclusive(exclusiveFlag); + return desired; + } + else if(MESSAGE_GROUP_KEY.equals(name)) + { + // TODO + } + else if(MESSAGE_GROUP_DEFAULT_GROUP.equals(name)) + { + // TODO + } + else if(MESSAGE_GROUP_SHARED_GROUPS.equals(name)) + { + // TODO + } + else if(LVQ_KEY.equals(name)) + { + // TODO + } + else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name)) + { + _queue.setMaximumDeliveryCount((Integer)desired); + return desired; + } + else if(NO_LOCAL.equals(name)) + { + // TODO + } + else if(OWNER.equals(name)) + { + // TODO + } + else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name)) + { + _queue.setCapacity((Long)desired); + return desired; + } + else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name)) + { + _queue.setFlowResumeCapacity((Long)desired); + return desired; + } + else if(QUEUE_FLOW_STOPPED.equals(name)) + { + // TODO + } + else if(SORT_KEY.equals(name)) + { + // TODO + } + else if(TYPE.equals(name)) + { + // TODO + } + else if (DESCRIPTION.equals(name)) + { + _queue.setDescription((String) desired); + return desired; + } + + return super.setAttribute(name, expected, desired); + } + finally + { + if (_queue.isDurable()) + { + try + { + _queue.getVirtualHost().getMessageStore().updateQueue(_queue); + } + catch (AMQStoreException e) + { + throw new IllegalStateException(e); + } + } + } + } + + @Override + public Object getAttribute(String name) + { + + if(ALERT_REPEAT_GAP.equals(name)) + { + return _queue.getMinimumAlertRepeatGap(); + } + else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name)) + { + return _queue.getMaximumMessageAge(); + } + else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name)) + { + return _queue.getMaximumMessageSize(); + } + else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name)) + { + return _queue.getMaximumQueueDepth(); + } + else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name)) + { + return _queue.getMaximumMessageCount(); + } + else if(ALTERNATE_EXCHANGE.equals(name)) + { + org.apache.qpid.server.exchange.Exchange alternateExchange = _queue.getAlternateExchange(); + return alternateExchange == null ? null : + ConfiguredObjectFinder.findConfiguredObjectByName(_vhost.getExchanges(), + alternateExchange.getName()); + } + else if(EXCLUSIVE.equals(name)) + { + return _queue.isExclusive(); + } + else if(MESSAGE_GROUP_KEY.equals(name)) + { + // TODO + } + else if(MESSAGE_GROUP_DEFAULT_GROUP.equals(name)) + { + // TODO + } + else if(MESSAGE_GROUP_SHARED_GROUPS.equals(name)) + { + // TODO + } + else if(LVQ_KEY.equals(name)) + { + if(_queue instanceof ConflationQueue) + { + return ((ConflationQueue)_queue).getConflationKey(); + } + } + else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name)) + { + return _queue.getMaximumDeliveryCount(); + } + else if(NO_LOCAL.equals(name)) + { + // TODO + } + else if(OWNER.equals(name)) + { + return _queue.getOwner() == null ? null : _queue.getOwner().asString(); + } + else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name)) + { + return _queue.getCapacity(); + } + else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name)) + { + return _queue.getFlowResumeCapacity(); + } + else if(QUEUE_FLOW_STOPPED.equals(name)) + { + return _queue.isOverfull(); + } + else if(SORT_KEY.equals(name)) + { + if(_queue instanceof SortedQueue) + { + return ((SortedQueue)_queue).getSortedPropertyName(); + } + } + else if(TYPE.equals(name)) + { + if(_queue instanceof SortedQueue) + { + return "sorted"; + } + if(_queue instanceof ConflationQueue) + { + return "lvq"; + } + if(_queue instanceof AMQPriorityQueue) + { + return "priority"; + } + return "standard"; + } + else if(CREATED.equals(name)) + { + // TODO + } + else if(DURABLE.equals(name)) + { + return _queue.isDurable(); + } + else if(ID.equals(name)) + { + return getId(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return _queue.isAutoDelete() ? LifetimePolicy.AUTO_DELETE : LifetimePolicy.PERMANENT; + } + else if(NAME.equals(name)) + { + return _queue.getName(); + } + else if(STATE.equals(name)) + { + return State.ACTIVE; // TODO + } + else if(TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if(UPDATED.equals(name)) + { + // TODO + } + else if (DESCRIPTION.equals(name)) + { + return _queue.getDescription(); + } + + return super.getAttribute(name); + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == Consumer.class) + { + return (Collection<C>) getConsumers(); + } + else if(clazz == org.apache.qpid.server.model.Binding.class) + { + return (Collection<C>) getBindings(); + } + else + { + return Collections.emptySet(); + } + } + + public org.apache.qpid.server.model.Binding createBinding(Exchange exchange, Map<String, Object> attributes) + throws AccessControlException, IllegalStateException + { + attributes = new HashMap<String, Object>(attributes); + String bindingKey = getStringAttribute(org.apache.qpid.server.model.Binding.NAME, attributes, ""); + Map<String, Object> bindingArgs = getMapAttribute(org.apache.qpid.server.model.Binding.ARGUMENTS, attributes, Collections.EMPTY_MAP); + + attributes.remove(org.apache.qpid.server.model.Binding.NAME); + attributes.remove(org.apache.qpid.server.model.Binding.ARGUMENTS); + + return exchange.createBinding(bindingKey, this, bindingArgs, attributes); + + } + + + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + if(childClass == org.apache.qpid.server.model.Binding.class) + { + if(otherParents != null && otherParents.length == 1 && otherParents[0] instanceof Exchange) + { + Exchange exchange = (Exchange) otherParents[0]; + if(exchange.getParent(org.apache.qpid.server.model.VirtualHost.class) == getParent(org.apache.qpid.server.model.VirtualHost.class)) + { + return (C) createBinding(exchange, attributes); + } + else + { + throw new IllegalArgumentException("Queue and Exchange parents of a binding must be on same virtual host"); + } + } + else + { + throw new IllegalArgumentException("Other parent must be an exchange"); + } + } + else + { + throw new IllegalArgumentException(); + } + } + + void bindingRegistered(Binding binding, BindingAdapter adapter) + { + synchronized (_bindingAdapters) + { + _bindingAdapters.put(binding, adapter); + } + childAdded(adapter); + } + + void bindingUnregistered(Binding binding) + { + BindingAdapter adapter = null; + synchronized (_bindingAdapters) + { + adapter = _bindingAdapters.remove(binding); + } + if(adapter != null) + { + childRemoved(adapter); + } + } + + AMQQueue getAMQQueue() + { + return _queue; + } + + public void subscriptionRegistered(final AMQQueue queue, final Subscription subscription) + { + ConsumerAdapter adapter = null; + synchronized (_consumerAdapters) + { + if(!_consumerAdapters.containsKey(subscription)) + { + adapter = new ConsumerAdapter(this, subscription); + _consumerAdapters.put(subscription,adapter); + // TODO - register with session + } + } + if(adapter != null) + { + childAdded(adapter); + } + } + + public void subscriptionUnregistered(final AMQQueue queue, final Subscription subscription) + { + ConsumerAdapter adapter = null; + + synchronized (_consumerAdapters) + { + adapter = _consumerAdapters.remove(subscription); + // TODO - register with session + } + if(adapter != null) + { + childRemoved(adapter); + } + } + + VirtualHostAdapter getVirtualHost() + { + return _vhost; + } + + + private static class QueueStatisticsAdapter implements Statistics + { + + private final AMQQueue _queue; + + public QueueStatisticsAdapter(AMQQueue queue) + { + _queue = queue; + } + + public Collection<String> getStatisticNames() + { + return Queue.AVAILABLE_STATISTICS; + } + + public Object getStatistic(String name) + { + if(BINDING_COUNT.equals(name)) + { + return _queue.getBindingCount(); + } + else if(CONSUMER_COUNT.equals(name)) + { + return _queue.getConsumerCount(); + } + else if(CONSUMER_COUNT_WITH_CREDIT.equals(name)) + { + return _queue.getActiveConsumerCount(); + } + else if(DISCARDS_TTL_BYTES.equals(name)) + { + return null; // TODO + } + else if(DISCARDS_TTL_MESSAGES.equals(name)) + { + return null; // TODO + } + else if(PERSISTENT_DEQUEUED_BYTES.equals(name)) + { + return _queue.getPersistentByteDequeues(); + } + else if(PERSISTENT_DEQUEUED_MESSAGES.equals(name)) + { + return _queue.getPersistentMsgDequeues(); + } + else if(PERSISTENT_ENQUEUED_BYTES.equals(name)) + { + return _queue.getPersistentByteEnqueues(); + } + else if(PERSISTENT_ENQUEUED_MESSAGES.equals(name)) + { + return _queue.getPersistentMsgEnqueues(); + } + else if(QUEUE_DEPTH_BYTES.equals(name)) + { + return _queue.getQueueDepth(); + } + else if(QUEUE_DEPTH_MESSAGES.equals(name)) + { + return _queue.getMessageCount(); + } + else if(STATE_CHANGED.equals(name)) + { + return null; // TODO + } + else if(TOTAL_DEQUEUED_BYTES.equals(name)) + { + return _queue.getTotalDequeueSize(); + } + else if(TOTAL_DEQUEUED_MESSAGES.equals(name)) + { + return _queue.getTotalDequeueCount(); + } + else if(TOTAL_ENQUEUED_BYTES.equals(name)) + { + return _queue.getTotalEnqueueSize(); + } + else if(TOTAL_ENQUEUED_MESSAGES.equals(name)) + { + return _queue.getTotalEnqueueCount(); + } + else if(UNACKNOWLEDGED_BYTES.equals(name)) + { + return _queue.getUnackedMessageBytes(); + } + else if(UNACKNOWLEDGED_MESSAGES.equals(name)) + { + return _queue.getUnackedMessageCount(); + } + + return null; + } + } + + @Override + public void setNotificationListener(QueueNotificationListener listener) + { + _queueNotificationListener = listener; + } + + @Override + public void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg) + { + QueueNotificationListener listener = _queueNotificationListener; + if(listener != null) + { + listener.notifyClients(notification, this, notificationMsg); + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java new file mode 100644 index 0000000000..25d9c6feb1 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java @@ -0,0 +1,239 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; + +import java.util.Map; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Publisher; +import org.apache.qpid.server.model.Session; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.Consumer; +import org.apache.qpid.server.protocol.AMQSessionModel; + +final class SessionAdapter extends AbstractAdapter implements Session +{ + // Attributes + + + private AMQSessionModel _session; + private SessionStatistics _statistics; + + public SessionAdapter(final AMQSessionModel session) + { + _session = session; + _statistics = new SessionStatistics(); + } + + public Collection<Consumer> getSubscriptions() + { + return null; //TODO + } + + public Collection<Publisher> getPublishers() + { + return null; //TODO + } + + public String getName() + { + return String.valueOf(_session.getChannelId()); + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + return null; //TODO + } + + public State getActualState() + { + return null; //TODO + } + + public boolean isDurable() + { + return false; //TODO + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + //TODO + } + + public LifetimePolicy getLifetimePolicy() + { + return null; //TODO + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return null; //TODO + } + + public long getTimeToLive() + { + return 0; //TODO + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return 0; //TODO + } + + @Override + public Collection<String> getAttributeNames() + { + Collection<String> names = new HashSet<String>(super.getAttributeNames()); + names.addAll(AVAILABLE_ATTRIBUTES); + + return Collections.unmodifiableCollection(names); + } + + @Override + public Object getAttribute(String name) + { + if(name.equals(ID)) + { + return getId(); + } + else if (name.equals(NAME)) + { + return getName(); + } + else if(name.equals(CHANNEL_ID)) + { + return _session.getChannelId(); + } + else if(name.equals(PRODUCER_FLOW_BLOCKED)) + { + return _session.getBlocking(); + } + return super.getAttribute(name); //TODO - Implement + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO - Implement + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == Consumer.class) + { + return (Collection<C>) getSubscriptions(); + } + else if(clazz == Publisher.class) + { + return (Collection<C>) getPublishers(); + } + else + { + return Collections.emptySet(); + } + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + throw new UnsupportedOperationException(); + } + + private class SessionStatistics implements Statistics + { + + public SessionStatistics() + { + } + + public Collection<String> getStatisticNames() + { + return AVAILABLE_STATISTICS; + } + + public Object getStatistic(String name) + { + if(name.equals(BYTES_IN)) + { + } + else if(name.equals(BYTES_OUT)) + { + } + else if(name.equals(CONSUMER_COUNT)) + { + final Collection<Consumer> subscriptions = getSubscriptions(); + return subscriptions == null ? 0 : subscriptions.size(); + } + else if(name.equals(LOCAL_TRANSACTION_BEGINS)) + { + return _session.getTxnStart(); + } + else if(name.equals(LOCAL_TRANSACTION_OPEN)) + { + long open = _session.getTxnCount() - (_session.getTxnCommits() + _session.getTxnRejects()); + return (Boolean) (open > 0l); + } + else if(name.equals(LOCAL_TRANSACTION_ROLLBACKS)) + { + return _session.getTxnCommits(); + } + else if(name.equals(STATE_CHANGED)) + { + } + else if(name.equals(UNACKNOWLEDGED_BYTES)) + { + } + else if(name.equals(UNACKNOWLEDGED_MESSAGES)) + { + return _session.getUnacknowledgedMessageCount(); + } + else if(name.equals(XA_TRANSACTION_BRANCH_ENDS)) + { + } + else if(name.equals(XA_TRANSACTION_BRANCH_STARTS)) + { + } + else if(name.equals(XA_TRANSACTION_BRANCH_SUSPENDS)) + { + + } + + return null; // TODO - Implement + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java new file mode 100644 index 0000000000..f98e46c911 --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java @@ -0,0 +1,67 @@ +package org.apache.qpid.server.model.adapter; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.stats.StatisticsCounter; +import org.apache.qpid.server.stats.StatisticsGatherer; + +/** +* Licensed to the Apache Software Foundation (ASF) under one or more +* contributor license agreements. See the NOTICE file distributed with +* this work for additional information regarding copyright ownership. +* The ASF 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 +* <p/> +* http://www.apache.org/licenses/LICENSE-2.0 +* <p/> +* 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. +*/ +class StatisticsAdapter implements Statistics +{ + + private final Map<String, StatisticsCounter> _statistics = + new HashMap<String, StatisticsCounter>(); + + + private static final String BYTES_IN = "bytesIn"; + private static final String BYTES_OUT = "bytesOut"; + private static final String MESSAGES_IN = "messagesIn"; + private static final String MESSAGES_OUT = "messagesOut"; + + private static final Collection<String> STATISTIC_NAMES = + Collections.unmodifiableCollection(Arrays.asList(BYTES_IN, BYTES_OUT, MESSAGES_IN, MESSAGES_OUT)); + + + + public StatisticsAdapter(StatisticsGatherer statGatherer) + { + _statistics.put(BYTES_OUT, statGatherer.getDataDeliveryStatistics()); + _statistics.put(BYTES_IN, statGatherer.getDataReceiptStatistics()); + _statistics.put(MESSAGES_OUT, statGatherer.getMessageDeliveryStatistics()); + _statistics.put(MESSAGES_IN, statGatherer.getMessageReceiptStatistics()); + } + + + public Collection<String> getStatisticNames() + { + return STATISTIC_NAMES; + } + + public Object getStatistic(String name) + { + StatisticsCounter counter = _statistics.get(name); + return counter == null ? null : counter.getTotal(); + + } + + +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java new file mode 100644 index 0000000000..204054c8cb --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -0,0 +1,844 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.security.AccessControlException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import org.apache.qpid.AMQException; +import org.apache.qpid.framing.FieldTable; +import org.apache.qpid.server.connection.IConnectionRegistry; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.exchange.ExchangeType; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Connection; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostAlias; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.AMQQueueFactory; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.QueueRegistry; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.txn.LocalTransaction; +import org.apache.qpid.server.txn.ServerTransaction; + +final class VirtualHostAdapter extends AbstractAdapter implements VirtualHost, ExchangeRegistry.RegistryChangeListener, + QueueRegistry.RegistryChangeListener, + IConnectionRegistry.RegistryChangeListener +{ + + private final org.apache.qpid.server.virtualhost.VirtualHost _virtualHost; + + private final Map<AMQConnectionModel, ConnectionAdapter> _connectionAdapters = + new HashMap<AMQConnectionModel, ConnectionAdapter>(); + + private final Map<AMQQueue, QueueAdapter> _queueAdapters = + new HashMap<AMQQueue, QueueAdapter>(); + + private final Map<org.apache.qpid.server.exchange.Exchange, ExchangeAdapter> _exchangeAdapters = + new HashMap<org.apache.qpid.server.exchange.Exchange, ExchangeAdapter>(); + + private final StatisticsAdapter _statistics; + + private final BrokerAdapter _broker; + + private final List<VirtualHostAlias> _aliases = new ArrayList<VirtualHostAlias>(); + + + VirtualHostAdapter(BrokerAdapter brokerAdapter, + final org.apache.qpid.server.virtualhost.VirtualHost virtualHost) + { + super(virtualHost.getName()); + _broker = brokerAdapter; + _virtualHost = virtualHost; + _statistics = new VirtualHostStatisticsAdapter(virtualHost); + virtualHost.getQueueRegistry().addRegistryChangeListener(this); + populateQueues(); + virtualHost.getExchangeRegistry().addRegistryChangeListener(this); + populateExchanges(); + virtualHost.getConnectionRegistry().addRegistryChangeListener(this); + populateConnections(); + + + + for(Port port :_broker.getPorts()) + { + _aliases.add(new VirtualHostAliasAdapter(this, port)); + } + } + + + private void populateExchanges() + { + Collection<org.apache.qpid.server.exchange.Exchange> actualExchanges = + _virtualHost.getExchangeRegistry().getExchanges(); + + synchronized (_exchangeAdapters) + { + for(org.apache.qpid.server.exchange.Exchange exchange : actualExchanges) + { + if(!_exchangeAdapters.containsKey(exchange)) + { + _exchangeAdapters.put(exchange, new ExchangeAdapter(this,exchange)); + } + } + } + } + + + private void populateQueues() + { + Collection<AMQQueue> actualQueues = _virtualHost.getQueueRegistry().getQueues(); + + synchronized(_queueAdapters) + { + for(AMQQueue queue : actualQueues) + { + if(!_queueAdapters.containsKey(queue)) + { + _queueAdapters.put(queue, new QueueAdapter(this,queue)); + } + } + } + } + + private void populateConnections() + { + + List<AMQConnectionModel> actualConnections = _virtualHost.getConnectionRegistry().getConnections(); + + synchronized(_connectionAdapters) + { + for(AMQConnectionModel conn : actualConnections) + { + if(!_connectionAdapters.containsKey(conn)) + { + _connectionAdapters.put(conn, new ConnectionAdapter(conn)); + } + } + } + + } + + public String getReplicationGroupName() + { + return null; //TODO + } + + public Collection<VirtualHostAlias> getAliases() + { + return Collections.unmodifiableCollection(_aliases); + } + + public Collection<Connection> getConnections() + { + synchronized(_connectionAdapters) + { + return new ArrayList<Connection>(_connectionAdapters.values()); + } + + } + + public Collection<Queue> getQueues() + { + synchronized(_queueAdapters) + { + return new ArrayList<Queue>(_queueAdapters.values()); + } + } + + public Collection<Exchange> getExchanges() + { + synchronized (_exchangeAdapters) + { + return new ArrayList<Exchange>(_exchangeAdapters.values()); + } + } + + + public Exchange createExchange(Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException + { + attributes = new HashMap<String, Object>(attributes); + + String name = getStringAttribute(Exchange.NAME, attributes, null); + State state = getEnumAttribute(State.class, Exchange.STATE, attributes, State.ACTIVE); + boolean durable = getBooleanAttribute(Exchange.DURABLE, attributes, false); + LifetimePolicy lifetime = getEnumAttribute(LifetimePolicy.class, Exchange.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT); + String type = getStringAttribute(Exchange.TYPE, attributes, null); + long ttl = getLongAttribute(Exchange.TIME_TO_LIVE, attributes, 0l); + + attributes.remove(Exchange.NAME); + attributes.remove(Exchange.STATE); + attributes.remove(Exchange.DURABLE); + attributes.remove(Exchange.LIFETIME_POLICY); + attributes.remove(Exchange.TYPE); + attributes.remove(Exchange.TIME_TO_LIVE); + + return createExchange(name, state, durable, lifetime, ttl, type, attributes); + } + + + public Exchange createExchange(final String name, + final State initialState, + final boolean durable, + final LifetimePolicy lifetime, + final long ttl, + final String type, + final Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException + { + try + { + org.apache.qpid.server.exchange.Exchange exchange = + _virtualHost.getExchangeFactory().createExchange(name, type, durable, + lifetime == LifetimePolicy.AUTO_DELETE); + _virtualHost.getExchangeRegistry().registerExchange(exchange); + if(durable) + { + _virtualHost.getMessageStore().createExchange(exchange); + } + + synchronized (_exchangeAdapters) + { + return _exchangeAdapters.get(exchange); + } + } + catch(AMQException e) + { + throw new IllegalArgumentException(e); + } + } + + public Queue createQueue(Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException + { + attributes = new HashMap<String, Object>(attributes); + + String name = getStringAttribute(Queue.NAME, attributes, null); + State state = getEnumAttribute(State.class, Queue.STATE, attributes, State.ACTIVE); + boolean durable = getBooleanAttribute(Queue.DURABLE, attributes, false); + LifetimePolicy lifetime = getEnumAttribute(LifetimePolicy.class, Queue.LIFETIME_POLICY, attributes, LifetimePolicy.PERMANENT); + long ttl = getLongAttribute(Queue.TIME_TO_LIVE, attributes, 0l); + boolean exclusive= getBooleanAttribute(Queue.EXCLUSIVE, attributes, false); + + attributes.remove(Queue.NAME); + attributes.remove(Queue.STATE); + attributes.remove(Queue.DURABLE); + attributes.remove(Queue.LIFETIME_POLICY); + attributes.remove(Queue.TIME_TO_LIVE); + + List<String> attrNames = new ArrayList<String>(attributes.keySet()); + for(String attr : attrNames) + { + if(QueueAdapter.ATTRIBUTE_MAPPINGS.containsKey(attr)) + { + attributes.put(QueueAdapter.ATTRIBUTE_MAPPINGS.get(attr),attributes.remove(attr)); + } + } + + return createQueue(name, state, durable, exclusive, lifetime, ttl, attributes); + } + + public Queue createQueue(final String name, + final State initialState, + final boolean durable, + boolean exclusive, + final LifetimePolicy lifetime, + final long ttl, + final Map<String, Object> attributes) + throws AccessControlException, IllegalArgumentException + { + String owner = null; + if(exclusive) + { + Set<Principal> principals = + SecurityManager.getThreadSubject().getPrincipals(); + if(principals != null && !principals.isEmpty()) + { + owner = principals.iterator().next().getName(); + } + } + try + { + if(_virtualHost.getQueueRegistry().getQueue(name)!=null) + { + throw new IllegalArgumentException("Queue with name "+name+" already exists"); + } + AMQQueue queue = + AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(name, _virtualHost.getName()), name, + durable, owner, lifetime == LifetimePolicy.AUTO_DELETE, + exclusive, _virtualHost, attributes); + _virtualHost.getBindingFactory().addBinding(name, queue, _virtualHost.getExchangeRegistry().getDefaultExchange(), null); + + if(durable) + { + _virtualHost.getMessageStore().createQueue(queue, FieldTable.convertToFieldTable(attributes)); + } + synchronized (_queueAdapters) + { + return _queueAdapters.get(queue); + } + + } + catch(AMQException e) + { + throw new IllegalArgumentException(e); + } + + } + + public String getName() + { + return _virtualHost.getName(); + } + + public String setName(final String currentName, final String desiredName) + throws IllegalStateException, AccessControlException + { + throw new IllegalStateException(); + } + + public State getActualState() + { + return getDesiredState(); + } + + public boolean isDurable() + { + return true; + } + + public void setDurable(final boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; + } + + public LifetimePolicy setLifetimePolicy(final LifetimePolicy expected, final LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + public long getTimeToLive() + { + return 0; + } + + public long setTimeToLive(final long expected, final long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + public Statistics getStatistics() + { + return _statistics; + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + if(clazz == Exchange.class) + { + return (Collection<C>) getExchanges(); + } + else if(clazz == Queue.class) + { + return (Collection<C>) getQueues(); + } + else if(clazz == Connection.class) + { + return (Collection<C>) getConnections(); + } + else if(clazz == VirtualHostAlias.class) + { + return (Collection<C>) getAliases(); + } + else + { + return Collections.emptySet(); + } + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + if(childClass == Exchange.class) + { + return (C) createExchange(attributes); + } + else if(childClass == Queue.class) + { + return (C) createQueue(attributes); + } + else if(childClass == VirtualHostAlias.class) + { + throw new UnsupportedOperationException(); + } + else if(childClass == Connection.class) + { + throw new UnsupportedOperationException(); + } + throw new IllegalArgumentException("Cannot create a child of class " + childClass.getSimpleName()); + } + + public void exchangeRegistered(org.apache.qpid.server.exchange.Exchange exchange) + { + ExchangeAdapter adapter = null; + synchronized (_exchangeAdapters) + { + if(!_exchangeAdapters.containsKey(exchange)) + { + adapter = new ExchangeAdapter(this, exchange); + _exchangeAdapters.put(exchange, adapter); + + } + + } + if(adapter != null) + { + childAdded(adapter); + } + + } + + + public void exchangeUnregistered(org.apache.qpid.server.exchange.Exchange exchange) + { + ExchangeAdapter adapter; + synchronized (_exchangeAdapters) + { + adapter = _exchangeAdapters.remove(exchange); + + } + + if(adapter != null) + { + childRemoved(adapter); + } + } + + public void queueRegistered(AMQQueue queue) + { + QueueAdapter adapter = null; + synchronized (_queueAdapters) + { + if(!_queueAdapters.containsKey(queue)) + { + adapter = new QueueAdapter(this, queue); + _queueAdapters.put(queue, adapter); + + } + + } + if(adapter != null) + { + childAdded(adapter); + } + + } + + public void queueUnregistered(AMQQueue queue) + { + + QueueAdapter adapter; + synchronized (_queueAdapters) + { + adapter = _queueAdapters.remove(queue); + + } + + if(adapter != null) + { + childRemoved(adapter); + } + } + + public void connectionRegistered(AMQConnectionModel connection) + { + ConnectionAdapter adapter = null; + synchronized (_connectionAdapters) + { + if(!_connectionAdapters.containsKey(connection)) + { + adapter = new ConnectionAdapter(connection); + _connectionAdapters.put(connection, adapter); + + } + + } + if(adapter != null) + { + childAdded(adapter); + } + } + + public void connectionUnregistered(AMQConnectionModel connection) + { + + ConnectionAdapter adapter; + synchronized (_connectionAdapters) + { + adapter = _connectionAdapters.remove(connection); + + } + + if(adapter != null) + { + childRemoved(adapter); + } + } + + QueueAdapter getQueueAdapter(AMQQueue queue) + { + synchronized (_queueAdapters) + { + return _queueAdapters.get(queue); + } + } + + public void deleteQueue(Queue queue) + throws AccessControlException, IllegalStateException + { + // TODO + throw new UnsupportedOperationException("Not Yet Implemented"); + } + + public Collection<String> getExchangeTypes() + { + Collection<ExchangeType<? extends org.apache.qpid.server.exchange.Exchange>> types = + _virtualHost.getExchangeFactory().getRegisteredTypes(); + + Collection<String> exchangeTypes = new ArrayList<String>(); + + for(ExchangeType<? extends org.apache.qpid.server.exchange.Exchange> type : types) + { + exchangeTypes.add(type.getName().asString()); + } + return Collections.unmodifiableCollection(exchangeTypes); + } + + public void executeTransaction(TransactionalOperation op) + { + MessageStore store = _virtualHost.getMessageStore(); + final LocalTransaction txn = new LocalTransaction(store); + + op.withinTransaction(new Transaction() + { + public void dequeue(final QueueEntry entry) + { + if(entry.acquire()) + { + txn.dequeue(entry.getQueue(), entry.getMessage(), new ServerTransaction.Action() + { + public void postCommit() + { + entry.discard(); + } + + public void onRollback() + { + } + }); + } + } + + public void copy(QueueEntry entry, Queue queue) + { + final ServerMessage message = entry.getMessage(); + final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue(); + + txn.enqueue(toQueue, message, new ServerTransaction.Action() + { + public void postCommit() + { + try + { + toQueue.enqueue(message); + } + catch(AMQException e) + { + throw new RuntimeException(e); + } + } + + public void onRollback() + { + } + }); + + } + + public void move(final QueueEntry entry, Queue queue) + { + final ServerMessage message = entry.getMessage(); + final AMQQueue toQueue = ((QueueAdapter)queue).getAMQQueue(); + if(entry.acquire()) + { + txn.enqueue(toQueue, message, + new ServerTransaction.Action() + { + + public void postCommit() + { + try + { + toQueue.enqueue(message); + } + catch (AMQException e) + { + throw new RuntimeException(e); + } + } + + public void onRollback() + { + entry.release(); + } + }); + txn.dequeue(entry.getQueue(), message, + new ServerTransaction.Action() + { + + public void postCommit() + { + entry.discard(); + } + + public void onRollback() + { + + } + }); + } + } + + }); + txn.commit(); + } + + org.apache.qpid.server.virtualhost.VirtualHost getVirtualHost() + { + return _virtualHost; + } + + @Override + public Object getAttribute(String name) + { + if(ID.equals(name)) + { + return getId(); + } + else if(NAME.equals(name)) + { + return getName(); + } + else if(STATE.equals(name)) + { + return State.ACTIVE; + } + else if(DURABLE.equals(name)) + { + return isDurable(); + } + else if(LIFETIME_POLICY.equals(name)) + { + return LifetimePolicy.PERMANENT; + } + else if(TIME_TO_LIVE.equals(name)) + { + // TODO + } + else if(CREATED.equals(name)) + { + // TODO + } + else if(UPDATED.equals(name)) + { + // TODO + } + else if(SUPPORTED_EXCHANGE_TYPES.equals(name)) + { + List<String> types = new ArrayList<String>(); + for(ExchangeType type : _virtualHost.getExchangeFactory().getRegisteredTypes()) + { + types.add(type.getName().asString()); + } + return Collections.unmodifiableCollection(types); + } + else if(SUPPORTED_QUEUE_TYPES.equals(name)) + { + // TODO + } + else if(DEAD_LETTER_QUEUE_ENABLED.equals(name)) + { + return _virtualHost.getConfiguration().isDeadLetterQueueEnabled(); + } + else if(FEDERATION_TAG.equals(name)) + { + return _virtualHost.getFederationTag(); + } + else if(HOUSEKEEPING_CHECK_PERIOD.equals(name)) + { + return _virtualHost.getConfiguration().getHousekeepingCheckPeriod(); + } + else if(MAXIMUM_DELIVERY_ATTEMPTS.equals(name)) + { + return _virtualHost.getConfiguration().getMaxDeliveryCount(); + } + else if(QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name)) + { + return _virtualHost.getConfiguration().getCapacity(); + } + else if(QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name)) + { + return _virtualHost.getConfiguration().getFlowResumeCapacity(); + } + else if(STORE_TYPE.equals(name)) + { + return _virtualHost.getMessageStore().getStoreType(); + } + else if(STORE_CONFIGURATION.equals(name)) + { + // TODO + } + else if(STORE_TRANSACTION_IDLE_TIMEOUT_CLOSE.equals(name)) + { + return _virtualHost.getConfiguration().getTransactionTimeoutIdleClose(); + } + else if(STORE_TRANSACTION_IDLE_TIMEOUT_WARN.equals(name)) + { + return _virtualHost.getConfiguration().getTransactionTimeoutIdleWarn(); + } + else if(STORE_TRANSACTION_OPEN_TIMEOUT_CLOSE.equals(name)) + { + return _virtualHost.getConfiguration().getTransactionTimeoutOpenClose(); + } + else if(STORE_TRANSACTION_OPEN_TIMEOUT_WARN.equals(name)) + { + return _virtualHost.getConfiguration().getTransactionTimeoutOpenWarn(); + } + else if(ALERT_REPEAT_GAP.equals(name)) + { + return _virtualHost.getConfiguration().getMinimumAlertRepeatGap(); + } + else if(ALERT_THRESHOLD_MESSAGE_AGE.equals(name)) + { + return _virtualHost.getConfiguration().getMaximumMessageAge(); + } + else if(ALERT_THRESHOLD_MESSAGE_SIZE.equals(name)) + { + return _virtualHost.getConfiguration().getMaximumMessageSize(); + } + else if(ALERT_THRESHOLD_QUEUE_DEPTH_BYTES.equals(name)) + { + return _virtualHost.getConfiguration().getMaximumQueueDepth(); + } + else if(ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES.equals(name)) + { + return _virtualHost.getConfiguration().getMaximumMessageCount(); + } + return super.getAttribute(name); + } + + @Override + public Object setAttribute(String name, Object expected, Object desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + return super.setAttribute(name, expected, desired); //TODO - Implement + } + + @Override + public Collection<String> getAttributeNames() + { + return AVAILABLE_ATTRIBUTES; + } + + private static class VirtualHostStatisticsAdapter extends StatisticsAdapter + { + private final org.apache.qpid.server.virtualhost.VirtualHost _vhost; + + private static final Collection<String> VHOST_STATS = Arrays.asList( + VirtualHost.QUEUE_COUNT, + VirtualHost.EXCHANGE_COUNT, + VirtualHost.CONNECTION_COUNT); + + public VirtualHostStatisticsAdapter(org.apache.qpid.server.virtualhost.VirtualHost virtualHost) + { + super(virtualHost); + _vhost = virtualHost; + } + + @Override + public Collection<String> getStatisticNames() + { + Set<String> stats = new HashSet<String>(super.getStatisticNames()); + stats.addAll(VHOST_STATS); + return stats; + } + + @Override + public Object getStatistic(String name) + { + if(VirtualHost.QUEUE_COUNT.equals(name)) + { + return _vhost.getQueueRegistry().getQueues().size(); + } + else if(VirtualHost.EXCHANGE_COUNT.equals(name)) + { + return _vhost.getExchangeRegistry().getExchanges().size(); + } + else if(VirtualHost.CONNECTION_COUNT.equals(name)) + { + return _vhost.getConnectionRegistry().getConnections().size(); + } + else + { + return super.getStatistic(name); + } + } + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java new file mode 100644 index 0000000000..22ea2e612b --- /dev/null +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java @@ -0,0 +1,142 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.qpid.server.model.adapter; + +import java.util.Map; +import org.apache.qpid.server.model.AuthenticationMethod; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.State; +import org.apache.qpid.server.model.Statistics; +import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.server.model.VirtualHostAlias; + +import java.security.AccessControlException; +import java.util.Collection; +import java.util.Collections; + +public class VirtualHostAliasAdapter extends AbstractAdapter implements VirtualHostAlias +{ + private VirtualHostAdapter _vhost; + private Port _port; + + public VirtualHostAliasAdapter(VirtualHostAdapter virtualHostAdapter, Port port) + { + super(virtualHostAdapter.getName(), port.getName()); + _vhost = virtualHostAdapter; + _port = port; + } + + @Override + public Port getPort() + { + return _port; + } + + @Override + public VirtualHost getVirtualHost() + { + return _vhost; + } + + @Override + public Collection<AuthenticationMethod> getAuthenticationMethods() + { + return Collections.emptySet(); // TODO - Implement + } + + @Override + public String getName() + { + return _vhost.getName(); + } + + @Override + public String setName(String currentName, String desiredName) throws IllegalStateException, AccessControlException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public State getActualState() + { + return State.ACTIVE; // TODO - Implement + } + + @Override + public boolean isDurable() + { + return true; // TODO - Implement + } + + @Override + public void setDurable(boolean durable) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); + } + + @Override + public LifetimePolicy getLifetimePolicy() + { + return LifetimePolicy.PERMANENT; // TODO - Implement + } + + @Override + public LifetimePolicy setLifetimePolicy(LifetimePolicy expected, LifetimePolicy desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public long getTimeToLive() + { + return 0; // TODO - Implement + } + + @Override + public long setTimeToLive(long expected, long desired) + throws IllegalStateException, AccessControlException, IllegalArgumentException + { + throw new IllegalStateException(); // TODO - Implement + } + + @Override + public Statistics getStatistics() + { + return NoStatistics.getInstance(); + } + + @Override + public <C extends ConfiguredObject> Collection<C> getChildren(Class<C> clazz) + { + return Collections.emptySet(); + } + + @Override + public <C extends ConfiguredObject> C createChild(Class<C> childClass, Map<String, Object> attributes, ConfiguredObject... otherParents) + { + throw new UnsupportedOperationException(); + } +} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties index badeffca05..4677d4b9e6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties @@ -31,12 +31,24 @@ javax.management.openmbean=1.0.0 javax.management=1.0.0 +javax.management.remote.rmi=1.0.0 +javax.management.remote=1.0.0 +javax.management.monitor=1.0.0 + +javax.crypto=1 +javax.crypto.spec=1 + +javax.servlet=2 +javax.servlet.http=2 javax.security.auth=1.0.0 javax.security.auth.callback=1.0.0 +javax.security.auth.login=1.0.0 javax.security.sasl=1.0.0 javax.security=1.0.0 +javax.rmi.ssl=1.0.0 + org.xml.sax=1.0.0 org.xml.sax.helpers=1.0.0 @@ -46,37 +58,57 @@ org.osgi.service.startlevel=1.0.0 org.osgi.service.url=1.0.0 org.osgi.util.tracker=1.0.0 +org.apache.commons.codec=1.3.0 +org.apache.commons.codec.binary=1.3.0 + org.apache.commons.configuration=1.0.0 org.apache.commons.lang=1.0.0 org.apache.commons.lang.builder=1.0.0 +org.apache.commons.lang.time=1.0.0 org.apache.commons.logging=1.0.0 -org.apache.log4j=1.2.12 +org.apache.log4j=1.2.16 org.slf4j=1.6.1 +org.eclipse.jetty=7.6.3 +org.eclipse.jetty.http=7.6.3 +org.eclipse.jetty.io=7.6.3 +org.eclipse.jetty.io.nio=7.6.3 +org.eclipse.jetty.security=7.6.3 +org.eclipse.jetty.server=7.6.3 +org.eclipse.jetty.server.session=7.6.3 +org.eclipse.jetty.servlet=7.6.3 + +org.codehaus.jackson=1.9.0 +org.codehaus.jackson.map=1.9.0 + # For Qpid packages (org.apache.qpid), the version number is automatically overridden by QpidPropertis#getReleaseVersion() -org.apache.qpid.junit.extensions.util=0.0.0 org.apache.qpid=0.0.0 org.apache.qpid.common=0.0.0 org.apache.qpid.exchange=0.0.0 org.apache.qpid.framing=0.0.0 org.apache.qpid.management.common.mbeans.annotations=0.0.0 +org.apache.qpid.management.common.mbeans=0.0.0 org.apache.qpid.protocol=0.0.0 org.apache.qpid.transport=0.0.0 org.apache.qpid.transport.codec=0.0.0 org.apache.qpid.server.binding=0.0.0 +org.apache.qpid.server.model=0.0.0 +org.apache.qpid.server.model.adapter=0.0.0 +org.apache.qpid.server.model.impl=0.0.0 org.apache.qpid.server.configuration=0.0.0 org.apache.qpid.server.configuration.plugins=0.0.0 org.apache.qpid.server.configuration.management=0.0.0 +org.apache.qpid.server.connection=0.0.0 org.apache.qpid.server.exchange=0.0.0 org.apache.qpid.server.logging=0.0.0 org.apache.qpid.server.logging.actors=0.0.0 +org.apache.qpid.server.logging.messages=0.0.0 org.apache.qpid.server.logging.subjects=0.0.0 org.apache.qpid.server.message=0.0.0 -org.apache.qpid.server.management=0.0.0 org.apache.qpid.server.persistent=0.0.0 org.apache.qpid.server.plugins=0.0.0 org.apache.qpid.server.protocol=0.0.0 @@ -88,7 +120,10 @@ org.apache.qpid.server.security.access.plugins=0.0.0 org.apache.qpid.server.security.auth=0.0.0 org.apache.qpid.server.security.auth.sasl=0.0.0 org.apache.qpid.server.security.auth.manager=0.0.0 +org.apache.qpid.server.security.auth.rmi=0.0.0 +org.apache.qpid.server.stats=0.0.0 org.apache.qpid.server.virtualhost=0.0.0 org.apache.qpid.server.virtualhost.plugins=0.0.0 org.apache.qpid.util=0.0.0 +org.apache.qpid.server.store.berkeleydb=0.0.0 diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java index b7fd2387a5..69ba7279bc 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java @@ -77,4 +77,16 @@ public interface AMQConnectionModel extends StatisticsGatherer public String getUserName(); public boolean isSessionNameUnique(byte[] name); + + String getRemoteAddressString(); + + String getClientId(); + + String getClientVersion(); + + String getPrincipalAsString(); + + long getSessionCountLimit(); + + long getLastIoTime(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index 5db336649f..850e293c3b 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -34,7 +34,6 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.atomic.AtomicBoolean; -import javax.management.JMException; import javax.security.auth.Subject; import javax.security.sasl.SaslServer; import org.apache.log4j.Logger; @@ -62,8 +61,6 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.ManagementActor; import org.apache.qpid.server.logging.messages.ConnectionMessages; import org.apache.qpid.server.logging.subjects.ConnectionLogSubject; -import org.apache.qpid.server.management.Managable; -import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.output.ProtocolOutputConverterRegistry; import org.apache.qpid.server.queue.QueueEntry; @@ -81,7 +78,7 @@ import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.util.BytesDataOutput; -public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig +public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession, ConnectionConfig { private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class); @@ -106,8 +103,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr private AMQCodecFactory _codecFactory; - private AMQProtocolSessionMBean _managedObject; - private SaslServer _saslServer; private Object _lastReceived; @@ -148,8 +143,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr private final ConfigStore _configStore; private long _createTime = System.currentTimeMillis(); - private ApplicationRegistry _registry; - private boolean _statisticsEnabled = false; private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; private NetworkConnection _network; @@ -159,11 +152,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr private long _lastReceivedTime; private boolean _blocking; - public ManagedObject getManagedObject() - { - return _managedObject; - } - public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkConnection network, final long connectionId) { _stateManager = new AMQStateManager(virtualHostRegistry, this); @@ -181,8 +169,8 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _actor.message(ConnectionMessages.OPEN(null, null, null, false, false, false)); - _registry = virtualHostRegistry.getApplicationRegistry(); initialiseStatistics(); + } public void setNetworkConnection(NetworkConnection network) @@ -196,11 +184,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _sender = sender; } - private AMQProtocolSessionMBean createMBean() throws JMException - { - return new AMQProtocolSessionMBean(this); - } - public long getSessionID() { return _connectionID; @@ -649,17 +632,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr { _cachedChannels[channelId] = channel; } - - checkForNotification(); - } - - private void checkForNotification() - { - int channelsCount = _channelMap.size(); - if (_managedObject != null && channelsCount >= _maxNoOfChannels) - { - _managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value"); - } } public Long getMaximumNumberOfChannels() @@ -811,13 +783,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr getConfigStore().removeConfiguredObject(this); - if (_managedObject != null) - { - _managedObject.unregister(); - // Ensure we only do this once. - _managedObject = null; - } - for (Task task : _taskList) { task.doTask(this); @@ -1004,16 +969,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _virtualHost.getConnectionRegistry().registerConnection(this); _configStore.addConfiguredObject(this); - - try - { - _managedObject = createMBean(); - _managedObject.register(); - } - catch (JMException e) - { - _logger.error(e); - } } public void addSessionCloseTask(Task task) @@ -1170,6 +1125,16 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr return _clientVersion; } + public String getPrincipalAsString() + { + return getAuthId(); + } + + public long getSessionCountLimit() + { + return getMaximumNumberOfChannels(); + } + public Boolean isIncoming() { return true; @@ -1400,12 +1365,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr public List<AMQSessionModel> getSessionModels() { - List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>(); - for (AMQChannel channel : getChannels()) - { - sessions.add((AMQSessionModel) channel); - } - return sessions; + return new ArrayList<AMQSessionModel>(getChannels()); } public LogSubject getLogSubject() @@ -1415,21 +1375,15 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr public void registerMessageDelivered(long messageSize) { - if (isStatisticsEnabled()) - { - _messagesDelivered.registerEvent(1L); - _dataDelivered.registerEvent(messageSize); - } + _messagesDelivered.registerEvent(1L); + _dataDelivered.registerEvent(messageSize); _virtualHost.registerMessageDelivered(messageSize); } public void registerMessageReceived(long messageSize, long timestamp) { - if (isStatisticsEnabled()) - { - _messagesReceived.registerEvent(1L, timestamp); - _dataReceived.registerEvent(messageSize, timestamp); - } + _messagesReceived.registerEvent(1L, timestamp); + _dataReceived.registerEvent(messageSize, timestamp); _virtualHost.registerMessageReceived(messageSize, timestamp); } @@ -1463,29 +1417,26 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr public void initialiseStatistics() { - setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS && - _registry.getConfiguration().isStatisticsGenerationConnectionsEnabled()); - _messagesDelivered = new StatisticsCounter("messages-delivered-" + getSessionID()); _dataDelivered = new StatisticsCounter("data-delivered-" + getSessionID()); _messagesReceived = new StatisticsCounter("messages-received-" + getSessionID()); _dataReceived = new StatisticsCounter("data-received-" + getSessionID()); } - public boolean isStatisticsEnabled() + public boolean isSessionNameUnique(byte[] name) { - return _statisticsEnabled; + // 0-8/0-9/0-9-1 sessions don't have names + return true; } - public void setStatisticsEnabled(boolean enabled) + public String getRemoteAddressString() { - _statisticsEnabled = enabled; + return String.valueOf(getRemoteAddress()); } - public boolean isSessionNameUnique(byte[] name) + public String getClientId() { - // 0-8/0-9/0-9-1 sessions don't have names - return true; + return String.valueOf(getContextKey()); } public void setDeferFlush(boolean deferFlush) diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java deleted file mode 100644 index e70720600e..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java +++ /dev/null @@ -1,344 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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. - * - */ -/* - * - * Copyright (c) 2006 The Apache Software Foundation - * - * 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.apache.qpid.server.protocol; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.ConnectionCloseBody; -import org.apache.qpid.framing.MethodRegistry; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.protocol.AMQConstant; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.management.AbstractAMQManagedConnectionObject; -import org.apache.qpid.server.management.ManagedObject; - -import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.NotCompliantMBeanException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import java.util.Date; -import java.util.List; - -/** - * This MBean class implements the management interface. In order to make more attributes, operations and notifications - * available over JMX simply augment the ManagedConnection interface and add the appropriate implementation here. - */ -@MBeanDescription("Management Bean for an AMQ Broker 0-9-1/0-9/0-8 Connections") -public class AMQProtocolSessionMBean extends AbstractAMQManagedConnectionObject -{ - private AMQProtocolSession _protocolSession = null; - - private static final AMQShortString BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION = - new AMQShortString(BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION_STR); - - @MBeanConstructor("Creates an MBean exposing an AMQ Broker 0-9-1/0-9/0-8 Connection") - public AMQProtocolSessionMBean(AMQProtocolSession amqProtocolSession) throws NotCompliantMBeanException, OpenDataException - { - super(amqProtocolSession.getRemoteAddress().toString()); - _protocolSession = amqProtocolSession; - } - - public String getClientId() - { - return String.valueOf(_protocolSession.getContextKey()); - } - - public String getAuthorizedId() - { - return (_protocolSession.getAuthorizedPrincipal() != null ) ? _protocolSession.getAuthorizedPrincipal().getName() : null; - } - - public String getVersion() - { - return _protocolSession.getClientVersion(); - } - - public Date getLastIoTime() - { - return new Date(_protocolSession.getLastIoTime()); - } - - public String getRemoteAddress() - { - return _protocolSession.getRemoteAddress().toString(); - } - - public ManagedObject getParentObject() - { - return _protocolSession.getVirtualHost().getManagedObject(); - } - - public Long getWrittenBytes() - { - return _protocolSession.getWrittenBytes(); - } - - public Long getReadBytes() - { - return _protocolSession.getWrittenBytes(); - } - - public Long getMaximumNumberOfChannels() - { - return _protocolSession.getMaximumNumberOfChannels(); - } - - /** - * commits transactions for a transactional channel - * - * @param channelId - * @throws JMException if channel with given id doesn't exist or if commit fails - */ - public void commitTransactions(int channelId) throws JMException - { - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - AMQChannel channel = _protocolSession.getChannel(channelId); - if (channel == null) - { - throw new JMException("The channel (channel Id = " + channelId + ") does not exist"); - } - - _protocolSession.commitTransactions(channel); - } - catch (AMQException ex) - { - throw new MBeanException(ex, ex.toString()); - } - finally - { - CurrentActor.remove(); - } - } - - /** - * rollsback the transactions for a transactional channel - * - * @param channelId - * @throws JMException if channel with given id doesn't exist or if rollback fails - */ - public void rollbackTransactions(int channelId) throws JMException - { - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - AMQChannel channel = _protocolSession.getChannel(channelId); - if (channel == null) - { - throw new JMException("The channel (channel Id = " + channelId + ") does not exist"); - } - - _protocolSession.rollbackTransactions(channel); - } - catch (AMQException ex) - { - throw new MBeanException(ex, ex.toString()); - } - finally - { - CurrentActor.remove(); - } - } - - /** - * Creates the list of channels in tabular form from the _channelMap. - * - * @return list of channels in tabular form. - * @throws OpenDataException - */ - public TabularData channels() throws OpenDataException - { - TabularDataSupport channelsList = new TabularDataSupport(_channelsType); - List<AMQChannel> list = _protocolSession.getChannels(); - - for (AMQChannel channel : list) - { - Object[] itemValues = - { - channel.getChannelId(), channel.isTransactional(), - (channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getNameShortString().asString() : null, - channel.getUnacknowledgedMessageMap().size(), channel.getBlocking() - }; - - CompositeData channelData = new CompositeDataSupport(_channelType, - COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues); - channelsList.put(channelData); - } - - return channelsList; - } - - /** - * closes the connection. The administrator can use this management operation to close connection to free up - * resources. - * @throws JMException - */ - public void closeConnection() throws JMException - { - - MethodRegistry methodRegistry = _protocolSession.getMethodRegistry(); - ConnectionCloseBody responseBody = - methodRegistry.createConnectionCloseBody(AMQConstant.REPLY_SUCCESS.getCode(), - // replyCode - BROKER_MANAGEMENT_CONSOLE_HAS_CLOSED_THE_CONNECTION, - // replyText, - 0, - 0); - - // This seems ugly but because we use closeConnection in both normal - // broker operation and as part of the management interface it cannot - // be avoided. The Current Actor will be null when this method is - // called via the Management interface. This is because we allow the - // Local API connection with JConsole. If we did not allow that option - // then the CurrentActor could be set in our JMX Proxy object. - // As it is we need to set the CurrentActor on all MBean methods - // Ideally we would not have a single method that can be called from - // two contexts. - boolean removeActor = false; - if (CurrentActor.get() == null) - { - removeActor = true; - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - } - - try - { - _protocolSession.writeFrame(responseBody.generateFrame(0)); - - try - { - - _protocolSession.closeSession(); - } - catch (AMQException ex) - { - throw new MBeanException(ex, ex.toString()); - } - } - finally - { - if (removeActor) - { - CurrentActor.remove(); - } - } - } - - public void resetStatistics() throws Exception - { - _protocolSession.resetStatistics(); - } - - public double getPeakMessageDeliveryRate() - { - return _protocolSession.getMessageDeliveryStatistics().getPeak(); - } - - public double getPeakDataDeliveryRate() - { - return _protocolSession.getDataDeliveryStatistics().getPeak(); - } - - public double getMessageDeliveryRate() - { - return _protocolSession.getMessageDeliveryStatistics().getRate(); - } - - public double getDataDeliveryRate() - { - return _protocolSession.getDataDeliveryStatistics().getRate(); - } - - public long getTotalMessagesDelivered() - { - return _protocolSession.getMessageDeliveryStatistics().getTotal(); - } - - public long getTotalDataDelivered() - { - return _protocolSession.getDataDeliveryStatistics().getTotal(); - } - - public double getPeakMessageReceiptRate() - { - return _protocolSession.getMessageReceiptStatistics().getPeak(); - } - - public double getPeakDataReceiptRate() - { - return _protocolSession.getDataReceiptStatistics().getPeak(); - } - - public double getMessageReceiptRate() - { - return _protocolSession.getMessageReceiptStatistics().getRate(); - } - - public double getDataReceiptRate() - { - return _protocolSession.getDataReceiptStatistics().getRate(); - } - - public long getTotalMessagesReceived() - { - return _protocolSession.getMessageReceiptStatistics().getTotal(); - } - - public long getTotalDataReceived() - { - return _protocolSession.getDataReceiptStatistics().getTotal(); - } - - public boolean isStatisticsEnabled() - { - return _protocolSession.isStatisticsEnabled(); - } - - public void setStatisticsEnabled(boolean enabled) - { - _protocolSession.setStatisticsEnabled(enabled); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java index 0896499cda..efc64d9d91 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java @@ -55,7 +55,7 @@ public interface AMQSessionModel extends Comparable<AMQSessionModel> * is logged or the connection is closed, depending on the configuration. An open * transaction is one that has recent activity. The transaction age is counted * from the time the transaction was started. An idle transaction is one that - * has had no activity, such as publishing or acknowledgeing messages. + * has had no activity, such as publishing or acknowledging messages. * * @param openWarn time in milliseconds before alerting on open transaction * @param openClose time in milliseconds before closing connection with open transaction @@ -72,6 +72,16 @@ public interface AMQSessionModel extends Comparable<AMQSessionModel> void unblock(); + boolean getBlocking(); boolean onSameConnection(InboundMessage inbound); + + int getUnacknowledgedMessageCount(); + + Long getTxnCount(); + Long getTxnStart(); + Long getTxnCommits(); + Long getTxnRejects(); + + int getChannelId(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java index 08926d000d..b4195d7e5a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java @@ -49,6 +49,7 @@ import org.apache.qpid.amqp_1_0.type.transport.Transfer; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; import org.apache.qpid.server.subscription.Subscription; @@ -631,4 +632,46 @@ class Subscription_1_0 implements Subscription { _filters = filters; } + + @Override + public AMQSessionModel getSessionModel() + { + // TODO + return null; + } + + @Override + public long getBytesOut() + { + // TODO + return 0; + } + + @Override + public long getMessagesOut() + { + // TODO + return 0; + } + + @Override + public long getUnacknowledgedBytes() + { + // TODO + return 0; + } + + @Override + public long getUnacknowledgedMessages() + { + // TODO + return 0; + } + + @Override + public String getConsumerName() + { + //TODO + return "TODO"; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index e643338c3d..d3efd63ee0 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -28,21 +28,25 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeReferrer; import org.apache.qpid.server.logging.LogSubject; -import org.apache.qpid.server.management.Managable; -import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.security.AuthorizationHolder; import org.apache.qpid.server.store.TransactionLogResource; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; -public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue, +public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue, QueueConfig { + public interface NotificationListener + { + void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg); + } + boolean getDeleteOnNoConsumers(); void setDeleteOnNoConsumers(boolean b); @@ -57,6 +61,12 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer LogSubject getLogSubject(); + long getUnackedMessageBytes(); + + long getTotalDequeueCount(); + + long getTotalEnqueueCount(); + public interface Context { QueueEntry getLastSeenEntry(); @@ -79,6 +89,17 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer void unregisterSubscription(final Subscription subscription) throws AMQException; + Collection<Subscription> getConsumers(); + + interface SubscriptionRegistrationListener + { + void subscriptionRegistered(AMQQueue queue, Subscription subscription); + void subscriptionUnregistered(AMQQueue queue, Subscription subscription); + } + + void addSubscriptionRegistrationListener(SubscriptionRegistrationListener listener); + void removeSubscriptionRegistrationListener(SubscriptionRegistrationListener listener); + int getConsumerCount(); @@ -109,7 +130,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer void dequeue(QueueEntry entry, Subscription sub); - void decrementUnackedMsgCount(); + void decrementUnackedMsgCount(QueueEntry queueEntry); boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException; @@ -139,20 +160,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer */ public List<QueueEntry> getMessagesRangeOnTheQueue(final long fromPosition, final long toPosition); + void visit(QueueEntryVisitor visitor); - void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName); - - void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName); - - void removeMessagesFromQueue(long fromMessageId, long toMessageId); - - static interface Visitor - { - boolean visit(QueueEntry entry); - } - - void visit(Visitor visitor); - long getMaximumMessageSize(); @@ -216,8 +225,6 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer void setAlternateExchange(Exchange exchange); - void setAlternateExchange(String exchangeName); - Map<String, Object> getArguments(); void checkCapacity(AMQSessionModel channel); @@ -245,12 +252,12 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer } /** - * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusize subscription, as a subscription + * ExistingSubscriptionPreventsExclusive signals a failure to create an exclusive subscription, as a subscription * already exists. * * <p/><table id="crc"><caption>CRC Card</caption> * <tr><th> Responsibilities <th> Collaborations - * <tr><td> Represent failure to create an exclusize subscription, as a subscription already exists. + * <tr><td> Represent failure to create an exclusive subscription, as a subscription already exists. * </table> * * @todo Not an AMQP exception as no status code. @@ -274,9 +281,7 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer ConfigurationPlugin getConfiguration(); - ManagedObject getManagedObject(); - - void setExclusive(boolean exclusive) throws AMQException; + void setExclusive(boolean exclusive); /** * Gets the maximum delivery count. If a message on this queue @@ -295,4 +300,19 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer */ public void setMaximumDeliveryCount(final int maximumDeliveryCount); + void setNotificationListener(NotificationListener listener); + + /** + * Sets the free text description of this queue. + * + * @param description + * + */ + void setDescription(String description); + + /** + * Gets the free text description of this queue. + */ + String getDescription(); + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index f2b7d7c56b..d93af2fc25 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.queue; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -41,6 +42,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost; public class AMQQueueFactory { public static final String X_QPID_PRIORITIES = "x-qpid-priorities"; + public static final String X_QPID_DESCRIPTION = "x-qpid-description"; public static final String QPID_LVQ_KEY = "qpid.LVQ_key"; public static final String QPID_LAST_VALUE_QUEUE = "qpid.last_value_queue"; public static final String QPID_LAST_VALUE_QUEUE_KEY = "qpid.last_value_queue_key"; @@ -350,32 +352,7 @@ public class AMQQueueFactory boolean autodelete = config.getAutoDelete(); boolean exclusive = config.getExclusive(); String owner = config.getOwner(); - Map<String,Object> arguments = null; - - if(config.isLVQ() || config.getLVQKey() != null) - { - arguments = new HashMap<String,Object>(); - arguments.put(QPID_LAST_VALUE_QUEUE, 1); - arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey()); - } - else if (config.getPriority() || config.getPriorities() > 0) - { - arguments = new HashMap<String,Object>(); - arguments.put(X_QPID_PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities()); - } - else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey())) - { - arguments = new HashMap<String,Object>(); - arguments.put(QPID_QUEUE_SORT_KEY, config.getQueueSortKey()); - } - if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled()) - { - if (arguments == null) - { - arguments = new HashMap<String,Object>(); - } - arguments.put(X_QPID_DLQ_ENABLED, true); - } + Map<String, Object> arguments = createQueueArgumentsFromConfig(config); // we need queues that are defined in config to have deterministic ids. UUID id = UUIDGenerator.generateUUID(queueName, host.getName()); @@ -385,7 +362,6 @@ public class AMQQueueFactory return q; } - /** * Validates DLQ and DLE names * <p> @@ -475,4 +451,43 @@ public class AMQQueueFactory String dlExchangeName = name + serverConfig.getDeadLetterExchangeSuffix(); return dlExchangeName; } + + private static Map<String, Object> createQueueArgumentsFromConfig(QueueConfiguration config) + { + Map<String,Object> arguments = new HashMap<String,Object>(); + + if(config.isLVQ() || config.getLVQKey() != null) + { + arguments.put(QPID_LAST_VALUE_QUEUE, 1); + arguments.put(QPID_LAST_VALUE_QUEUE_KEY, config.getLVQKey() == null ? QPID_LVQ_KEY : config.getLVQKey()); + } + else if (config.getPriority() || config.getPriorities() > 0) + { + arguments.put(X_QPID_PRIORITIES, config.getPriorities() < 0 ? 10 : config.getPriorities()); + } + else if (config.getQueueSortKey() != null && !"".equals(config.getQueueSortKey())) + { + arguments.put(QPID_QUEUE_SORT_KEY, config.getQueueSortKey()); + } + + if (!config.getAutoDelete() && config.isDeadLetterQueueEnabled()) + { + arguments.put(X_QPID_DLQ_ENABLED, true); + } + + if (config.getDescription() != null && !"".equals(config.getDescription())) + { + arguments.put(X_QPID_DESCRIPTION, config.getDescription()); + } + + if (arguments.isEmpty()) + { + return Collections.emptyMap(); + } + else + { + return arguments; + } + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java deleted file mode 100644 index b0d4cb3486..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java +++ /dev/null @@ -1,664 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.queue; - -import org.apache.commons.lang.time.FastDateFormat; -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.AMQMessageHeader; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.transport.MessageProperties; - -import javax.management.JMException; -import javax.management.MBeanException; -import javax.management.MBeanNotificationInfo; -import javax.management.Notification; -import javax.management.ObjectName; -import javax.management.OperationsException; -import javax.management.monitor.MonitorNotification; -import javax.management.openmbean.ArrayType; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import javax.management.openmbean.TabularType; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - - -/** - * AMQQueueMBean is the management bean for an {@link AMQQueue}. - * - * <p/><table id="crc"><caption>CRC Caption</caption> - * <tr><th> Responsibilities <th> Collaborations - * </table> - */ -@MBeanDescription("Management Interface for AMQQueue") -public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, QueueNotificationListener -{ - - /** Used for debugging purposes. */ - private static final Logger LOGGER = Logger.getLogger(AMQQueueMBean.class); - - /** Date/time format used for message expiration and message timestamp formatting */ - public static final String JMSTIMESTAMP_DATETIME_FORMAT = "MM-dd-yy HH:mm:ss.SSS z"; - - private static final FastDateFormat FAST_DATE_FORMAT = FastDateFormat.getInstance(JMSTIMESTAMP_DATETIME_FORMAT); - - private final AMQQueue _queue; - private final String _queueName; - // OpenMBean data types for viewMessages method - - private static OpenType[] _msgAttributeTypes = new OpenType[6]; // AMQ message attribute types. - private static CompositeType _messageDataType = null; // Composite type for representing AMQ Message data. - private static TabularType _messagelistDataType = null; // Datatype for representing AMQ messages list. - - // OpenMBean data types for viewMessageContent method - private static CompositeType _msgContentType = null; - private static OpenType[] _msgContentAttributeTypes = new OpenType[4]; - - private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length]; - private Notification _lastNotification = null; - - - - - @MBeanConstructor("Creates an MBean exposing an AMQQueue") - public AMQQueueMBean(AMQQueue queue) throws JMException - { - super(ManagedQueue.class, ManagedQueue.TYPE); - _queue = queue; - _queueName = queue.getName(); - } - - public ManagedObject getParentObject() - { - return _queue.getVirtualHost().getManagedObject(); - } - - static - { - try - { - init(); - } - catch (JMException ex) - { - // This is not expected to ever occur. - throw new RuntimeException("Got JMException in static initializer.", ex); - } - } - - /** - * initialises the openmbean data types - */ - private static void init() throws OpenDataException - { - _msgContentAttributeTypes[0] = SimpleType.LONG; // For message id - _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType - _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding - _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content - _msgContentType = new CompositeType("Message Content", "AMQ Message Content", - VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]), - VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]), - _msgContentAttributeTypes); - - _msgAttributeTypes[0] = SimpleType.LONG; // For message id - _msgAttributeTypes[1] = new ArrayType(1, SimpleType.STRING); // For header attributes - _msgAttributeTypes[2] = SimpleType.LONG; // For size - _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered - _msgAttributeTypes[4] = SimpleType.LONG; // For queue position - _msgAttributeTypes[5] = SimpleType.INTEGER; // For delivery count - - _messageDataType = new CompositeType("Message", "AMQ Message", - VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]), - VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]), _msgAttributeTypes); - _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType, - VIEW_MSGS_TABULAR_UNIQUE_INDEX.toArray(new String[VIEW_MSGS_TABULAR_UNIQUE_INDEX.size()])); - } - - public String getObjectInstanceName() - { - return ObjectName.quote(_queueName); - } - - public String getName() - { - return _queueName; - } - - public boolean isDurable() - { - return _queue.isDurable(); - } - - public String getOwner() - { - return String.valueOf(_queue.getOwner()); - } - - public boolean isAutoDelete() - { - return _queue.isAutoDelete(); - } - - public Integer getMessageCount() - { - return _queue.getMessageCount(); - } - - public Integer getMaximumDeliveryCount() - { - return _queue.getMaximumDeliveryCount(); - } - - public Long getMaximumMessageSize() - { - return _queue.getMaximumMessageSize(); - } - - public Long getMaximumMessageAge() - { - return _queue.getMaximumMessageAge(); - } - - public void setMaximumMessageAge(Long maximumMessageAge) - { - _queue.setMaximumMessageAge(maximumMessageAge); - } - - public void setMaximumMessageSize(Long value) - { - _queue.setMaximumMessageSize(value); - } - - public Integer getConsumerCount() - { - return _queue.getConsumerCount(); - } - - public Integer getActiveConsumerCount() - { - return _queue.getActiveConsumerCount(); - } - - public Long getReceivedMessageCount() - { - return _queue.getReceivedMessageCount(); - } - - public Long getMaximumMessageCount() - { - return _queue.getMaximumMessageCount(); - } - - public void setMaximumMessageCount(Long value) - { - _queue.setMaximumMessageCount(value); - } - - /** - * returns the maximum total size of messages(bytes) in the queue. - */ - public Long getMaximumQueueDepth() - { - return _queue.getMaximumQueueDepth(); - } - - public void setMaximumQueueDepth(Long value) - { - _queue.setMaximumQueueDepth(value); - } - - /** - * returns the total size of messages(bytes) in the queue. - */ - public Long getQueueDepth() throws JMException - { - return _queue.getQueueDepth(); - } - - public Long getCapacity() - { - return _queue.getCapacity(); - } - - public void setCapacity(Long capacity) throws IllegalArgumentException - { - if( _queue.getFlowResumeCapacity() > capacity ) - { - throw new IllegalArgumentException("Capacity must not be less than FlowResumeCapacity"); - } - - _queue.setCapacity(capacity); - } - - public Long getFlowResumeCapacity() - { - return _queue.getFlowResumeCapacity(); - } - - public void setFlowResumeCapacity(Long flowResumeCapacity) throws IllegalArgumentException - { - if( _queue.getCapacity() < flowResumeCapacity ) - { - throw new IllegalArgumentException("FlowResumeCapacity must not exceed Capacity"); - } - - _queue.setFlowResumeCapacity(flowResumeCapacity); - } - - public boolean isFlowOverfull() - { - return _queue.isOverfull(); - } - - public boolean isExclusive() - { - return _queue.isExclusive(); - } - - public void setExclusive(boolean exclusive) throws JMException - { - try - { - _queue.setExclusive(exclusive); - } - catch (AMQException e) - { - throw new JMException(e.toString()); - } - } - - public void setAlternateExchange(String exchangeName) - { - _queue.setAlternateExchange(exchangeName); - } - - public String getAlternateExchange() - { - Exchange exchange = _queue.getAlternateExchange(); - String name = exchange == null ? null : exchange.getName(); - return name == null ? null : name; - } - - /** - * Checks if there is any notification to be send to the listeners - */ - public void checkForNotification(ServerMessage msg) throws AMQException - { - - final Set<NotificationCheck> notificationChecks = _queue.getNotificationChecks(); - - if(!notificationChecks.isEmpty()) - { - final long currentTime = System.currentTimeMillis(); - final long thresholdTime = currentTime - _queue.getMinimumAlertRepeatGap(); - - for (NotificationCheck check : notificationChecks) - { - if (check.isMessageSpecific() || (_lastNotificationTimes[check.ordinal()] < thresholdTime)) - { - if (check.notifyIfNecessary(msg, _queue, this)) - { - _lastNotificationTimes[check.ordinal()] = currentTime; - } - } - } - } - - } - - /** - * Sends the notification to the listeners - */ - public void notifyClients(NotificationCheck notification, AMQQueue queue, String notificationMsg) - { - // important : add log to the log file - monitoring tools may be looking for this - LOGGER.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg); - notificationMsg = notification.name() + " " + notificationMsg; - - _lastNotification = - new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this, incrementAndGetSequenceNumber(), - System.currentTimeMillis(), notificationMsg); - - getBroadcaster().sendNotification(_lastNotification); - } - - public Notification getLastNotification() - { - return _lastNotification; - } - - /** - * @see AMQQueue#deleteMessageFromTop - */ - public void deleteMessageFromTop() throws JMException - { - _queue.deleteMessageFromTop(); - } - - /** - * Clears the queue of non-acquired messages - * - * @return the number of messages deleted - * @see AMQQueue#clearQueue - */ - public Long clearQueue() throws JMException - { - try - { - return _queue.clearQueue(); - } - catch (AMQException ex) - { - throw new MBeanException(ex, "Error clearing queue " + _queueName); - } - } - - /** - * returns message content as byte array and related attributes for the given message id. - */ - public CompositeData viewMessageContent(long msgId) throws JMException - { - QueueEntry entry = _queue.getMessageOnTheQueue(msgId); - - if (entry == null) - { - throw new OperationsException("AMQMessage with message id = " + msgId + " is not in the " + _queueName); - } - - ServerMessage serverMsg = entry.getMessage(); - final int bodySize = (int) serverMsg.getSize(); - - - List<Byte> msgContent = new ArrayList<Byte>(); - - java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(bodySize); - int position = 0; - - while(position < bodySize) - { - position += serverMsg.getContent(buf, position); - buf.flip(); - for(int i = 0; i < buf.limit(); i++) - { - msgContent.add(buf.get(i)); - } - buf.clear(); - } - - AMQMessageHeader header = serverMsg.getMessageHeader(); - - String mimeType = null, encoding = null; - if (header != null) - { - mimeType = header.getMimeType(); - - encoding = header.getEncoding(); - } - - - Object[] itemValues = { msgId, mimeType, encoding, msgContent.toArray(new Byte[0]) }; - - return new CompositeDataSupport(_msgContentType, - VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.toArray( - new String[VIEW_MSG_CONTENT_COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues); - - } - - /** - * Returns the header contents of the messages stored in this queue in tabular form. - * Deprecated as of Qpid JMX API 1.3 - */ - @Deprecated - public TabularData viewMessages(int beginIndex, int endIndex) throws JMException - { - return viewMessages((long)beginIndex,(long)endIndex); - } - - - /** - * Returns the header contents of the messages stored in this queue in tabular form. - * @param startPosition The queue position of the first message to be viewed - * @param endPosition The queue position of the last message to be viewed - */ - public TabularData viewMessages(long startPosition, long endPosition) throws JMException - { - if ((startPosition > endPosition) || (startPosition < 1)) - { - throw new OperationsException("From Index = " + startPosition + ", To Index = " + endPosition - + "\n\"From Index\" should be greater than 0 and less than \"To Index\""); - } - - if ((endPosition - startPosition) > Integer.MAX_VALUE) - { - throw new OperationsException("Specified MessageID interval is too large. Intervals must be less than 2^31 in size"); - } - - List<QueueEntry> list = _queue.getMessagesRangeOnTheQueue(startPosition,endPosition); - TabularDataSupport _messageList = new TabularDataSupport(_messagelistDataType); - - try - { - // Create the tabular list of message header contents - int size = list.size(); - - for (int i = 0; i < size ; i++) - { - long position = startPosition + i; - final QueueEntry queueEntry = list.get(i); - ServerMessage serverMsg = queueEntry.getMessage(); - - String[] headerAttributes = null; - Object[] itemValues = null; - - if(serverMsg instanceof AMQMessage) - { - AMQMessage msg = (AMQMessage) serverMsg; - ContentHeaderBody headerBody = msg.getContentHeaderBody(); - // Create header attributes list - headerAttributes = getMessageHeaderProperties(headerBody); - itemValues = new Object[]{msg.getMessageId(), headerAttributes, headerBody.getBodySize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()}; - } - else if(serverMsg instanceof MessageTransferMessage) - { - // We have a 0-10 message - MessageTransferMessage msg = (MessageTransferMessage) serverMsg; - - // Create header attributes list - headerAttributes = getMessageTransferMessageHeaderProps(msg); - itemValues = new Object[]{msg.getMessageNumber(), headerAttributes, msg.getSize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()}; - } - else - { - //unknown message - headerAttributes = new String[]{"N/A"}; - itemValues = new Object[]{serverMsg.getMessageNumber(), headerAttributes, serverMsg.getSize(), queueEntry.isRedelivered(), position, queueEntry.getDeliveryCount()}; - } - - CompositeData messageData = new CompositeDataSupport(_messageDataType, - VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.toArray(new String[VIEW_MSGS_COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues); - _messageList.put(messageData); - } - } - catch (AMQException e) - { - JMException jme = new JMException("Error creating message contents: " + e); - jme.initCause(e); - throw jme; - } - - return _messageList; - } - - private String[] getMessageHeaderProperties(ContentHeaderBody headerBody) - { - List<String> list = new ArrayList<String>(); - BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.getProperties(); - list.add("reply-to = " + headerProperties.getReplyToAsString()); - list.add("propertyFlags = " + headerProperties.getPropertyFlags()); - list.add("ApplicationID = " + headerProperties.getAppIdAsString()); - list.add("ClusterID = " + headerProperties.getClusterIdAsString()); - list.add("UserId = " + headerProperties.getUserIdAsString()); - list.add("JMSMessageID = " + headerProperties.getMessageIdAsString()); - list.add("JMSCorrelationID = " + headerProperties.getCorrelationIdAsString()); - - int delMode = headerProperties.getDeliveryMode(); - list.add("JMSDeliveryMode = " + - ((delMode == BasicContentHeaderProperties.PERSISTENT) ? "Persistent" : "Non_Persistent")); - - list.add("JMSPriority = " + headerProperties.getPriority()); - list.add("JMSType = " + headerProperties.getType()); - - final long expirationDate = headerProperties.getExpiration(); - final long timestampDate = headerProperties.getTimestamp(); - - addStringifiedJMSTimestamoAndJMSExpiration(list, expirationDate, - timestampDate); - - return list.toArray(new String[list.size()]); - } - - private String[] getMessageTransferMessageHeaderProps(MessageTransferMessage msg) - { - List<String> list = new ArrayList<String>(); - - AMQMessageHeader header = msg.getMessageHeader(); - MessageProperties msgProps = msg.getHeader().getMessageProperties(); - - String appID = null; - String userID = null; - - if(msgProps != null) - { - appID = msgProps.getAppId() == null ? "null" : new String(msgProps.getAppId()); - userID = msgProps.getUserId() == null ? "null" : new String(msgProps.getUserId()); - } - - list.add("reply-to = " + header.getReplyTo()); - list.add("propertyFlags = "); //TODO - list.add("ApplicationID = " + appID); - list.add("ClusterID = "); //TODO - list.add("UserId = " + userID); - list.add("JMSMessageID = " + header.getMessageId()); - list.add("JMSCorrelationID = " + header.getCorrelationId()); - list.add("JMSDeliveryMode = " + (msg.isPersistent() ? "Persistent" : "Non_Persistent")); - list.add("JMSPriority = " + header.getPriority()); - list.add("JMSType = " + header.getType()); - - final long expirationDate = header.getExpiration(); - final long timestampDate = header.getTimestamp(); - addStringifiedJMSTimestamoAndJMSExpiration(list, expirationDate, timestampDate); - - return list.toArray(new String[list.size()]); - } - - private void addStringifiedJMSTimestamoAndJMSExpiration(final List<String> list, - final long expirationDate, final long timestampDate) - { - final String formattedExpirationDate = (expirationDate != 0) ? FAST_DATE_FORMAT.format(expirationDate) : null; - final String formattedTimestampDate = (timestampDate != 0) ? FAST_DATE_FORMAT.format(timestampDate) : null; - list.add("JMSExpiration = " + formattedExpirationDate); - list.add("JMSTimestamp = " + formattedTimestampDate); - } - - /** - * @see ManagedQueue#moveMessages - * @param fromMessageId - * @param toMessageId - * @param toQueueName - * @throws JMException - */ - public void moveMessages(long fromMessageId, long toMessageId, String toQueueName) throws JMException - { - if ((fromMessageId > toMessageId) || (fromMessageId < 1)) - { - throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); - } - - _queue.moveMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName); - } - - /** - * @see ManagedQueue#deleteMessages - * @param fromMessageId - * @param toMessageId - * @throws JMException - */ - public void deleteMessages(long fromMessageId, long toMessageId) throws JMException - { - if ((fromMessageId > toMessageId) || (fromMessageId < 1)) - { - throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); - } - - _queue.removeMessagesFromQueue(fromMessageId, toMessageId); - } - - /** - * @see ManagedQueue#copyMessages - * @param fromMessageId - * @param toMessageId - * @param toQueueName - * @throws JMException - */ - public void copyMessages(long fromMessageId, long toMessageId, String toQueueName) throws JMException - { - if ((fromMessageId > toMessageId) || (fromMessageId < 1)) - { - throw new OperationsException("\"From MessageId\" should be greater than 0 and less than \"To MessageId\""); - } - - _queue.copyMessagesToAnotherQueue(fromMessageId, toMessageId, toQueueName); - } - - /** - * returns Notifications sent by this MBean. - */ - @Override - public MBeanNotificationInfo[] getNotificationInfo() - { - String[] notificationTypes = new String[] { MonitorNotification.THRESHOLD_VALUE_EXCEEDED }; - String name = MonitorNotification.class.getName(); - String description = "Either Message count or Queue depth or Message size has reached threshold high value"; - MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description); - - return new MBeanNotificationInfo[] { info1 }; - } - -} // End of AMQQueueMBean class diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java index 2493974d45..27a9e13617 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java @@ -20,12 +20,10 @@ */ package org.apache.qpid.server.queue; -import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.DefaultExchangeRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.ArrayList; import java.util.Collection; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; @@ -33,11 +31,11 @@ import java.util.concurrent.ConcurrentMap; public class DefaultQueueRegistry implements QueueRegistry { - private static final Logger LOGGER = Logger.getLogger(DefaultExchangeRegistry.class); - private ConcurrentMap<AMQShortString, AMQQueue> _queueMap = new ConcurrentHashMap<AMQShortString, AMQQueue>(); private final VirtualHost _virtualHost; + private final Collection<RegistryChangeListener> _listeners = + new ArrayList<RegistryChangeListener>(); public DefaultQueueRegistry(VirtualHost virtualHost) { @@ -52,11 +50,28 @@ public class DefaultQueueRegistry implements QueueRegistry public void registerQueue(AMQQueue queue) { _queueMap.put(queue.getNameShortString(), queue); + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.queueRegistered(queue); + } + } } public void unregisterQueue(AMQShortString name) { - _queueMap.remove(name); + AMQQueue q = _queueMap.remove(name); + if(q != null) + { + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.queueUnregistered(q); + } + } + } } public AMQQueue getQueue(AMQShortString name) @@ -79,19 +94,30 @@ public class DefaultQueueRegistry implements QueueRegistry return getQueue(new AMQShortString(queue)); } + public void addRegistryChangeListener(RegistryChangeListener listener) + { + synchronized(_listeners) + { + _listeners.add(listener); + } + } + @Override public void stopAllAndUnregisterMBeans() { for (final AMQQueue queue : getQueues()) { queue.stop(); - try - { - queue.getManagedObject().unregister(); - } - catch (AMQException e) + + //TODO: this is a bit of a hack, what if the listeners aren't aware + //that we are just unregistering the MBean because of HA, and aren't + //actually removing the queue as such. + synchronized (_listeners) { - LOGGER.warn("Failed to unregister mbean", e); + for(RegistryChangeListener listener : _listeners) + { + listener.queueUnregistered(queue); + } } } _queueMap.clear(); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java index c1ebbe412f..3efef9ab98 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java @@ -20,6 +20,7 @@ */
package org.apache.qpid.server.queue;
+import org.apache.log4j.Logger;
import org.apache.qpid.server.message.ServerMessage;
public enum NotificationCheck
@@ -27,13 +28,16 @@ public enum NotificationCheck MESSAGE_COUNT_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) {
int msgCount;
final long maximumMessageCount = queue.getMaximumMessageCount();
if (maximumMessageCount!= 0 && (msgCount = queue.getMessageCount()) >= maximumMessageCount)
{
- listener.notifyClients(this, queue, msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.");
+ String notificationMsg = msgCount + ": Maximum count on queue threshold ("+ maximumMessageCount +") breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
return false;
@@ -41,7 +45,7 @@ public enum NotificationCheck },
MESSAGE_SIZE_ALERT(true)
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) {
final long maximumMessageSize = queue.getMaximumMessageSize();
if(maximumMessageSize != 0)
@@ -50,10 +54,12 @@ public enum NotificationCheck long messageSize;
messageSize = (msg == null) ? 0 : msg.getSize();
-
if (messageSize >= maximumMessageSize)
{
- listener.notifyClients(this, queue, messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]");
+ String notificationMsg = messageSize + "b : Maximum message size threshold ("+ maximumMessageSize +") breached. [Message ID=" + msg.getMessageNumber() + "]";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
}
@@ -63,7 +69,7 @@ public enum NotificationCheck },
QUEUE_DEPTH_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) {
// Check for threshold queue depth in bytes
final long maximumQueueDepth = queue.getMaximumQueueDepth();
@@ -74,7 +80,10 @@ public enum NotificationCheck if (queueDepth >= maximumQueueDepth)
{
- listener.notifyClients(this, queue, (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.");
+ String notificationMsg = (queueDepth>>10) + "Kb : Maximum queue depth threshold ("+(maximumQueueDepth>>10)+"Kb) breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
}
@@ -84,7 +93,7 @@ public enum NotificationCheck },
MESSAGE_AGE_ALERT
{
- boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener)
+ public boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener) {
final long maxMessageAge = queue.getMaximumMessageAge();
@@ -97,7 +106,10 @@ public enum NotificationCheck if(firstArrivalTime < thresholdTime)
{
long oldestAge = currentTime - firstArrivalTime;
- listener.notifyClients(this, queue, (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.");
+ String notificationMsg = (oldestAge/1000) + "s : Maximum age on queue threshold ("+(maxMessageAge /1000)+"s) breached.";
+
+ logNotification(this, queue, notificationMsg);
+ listener.notifyClients(this, queue, notificationMsg);
return true;
}
@@ -109,6 +121,8 @@ public enum NotificationCheck }
;
+ private static final Logger LOGGER = Logger.getLogger(NotificationCheck.class);
+
private final boolean _messageSpecific;
NotificationCheck()
@@ -126,6 +140,11 @@ public enum NotificationCheck return _messageSpecific;
}
- abstract boolean notifyIfNecessary(ServerMessage msg, AMQQueue queue, QueueNotificationListener listener);
+ public abstract boolean notifyIfNecessary(ServerMessage<?> msg, AMQQueue queue, AMQQueue.NotificationListener listener); + //A bit of a hack, only for use until we do the logging listener
+ private static void logNotification(NotificationCheck notification, AMQQueue queue, String notificationMsg)
+ {
+ LOGGER.info(notification.name() + " On Queue " + queue.getNameShortString() + " - " + notificationMsg);
+ }
}
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index 209553e8fa..25e771a9cf 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java @@ -233,7 +233,7 @@ public abstract class QueueEntryImpl implements QueueEntry if(state instanceof SubscriptionAcquiredState) { - getQueue().decrementUnackedMsgCount(); + getQueue().decrementUnackedMsgCount(this); Subscription subscription = ((SubscriptionAcquiredState)state).getSubscription(); if (subscription != null) { @@ -369,7 +369,7 @@ public abstract class QueueEntryImpl implements QueueEntry Subscription s = null; if (state instanceof SubscriptionAcquiredState) { - getQueue().decrementUnackedMsgCount(); + getQueue().decrementUnackedMsgCount(this); s = ((SubscriptionAcquiredState) state).getSubscription(); s.onDequeue(this); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java index 72a54c9889..e8c34128e9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java @@ -42,7 +42,15 @@ public interface QueueRegistry AMQQueue getQueue(String queue); + void addRegistryChangeListener(RegistryChangeListener listener); + void stopAllAndUnregisterMBeans(); AMQQueue getQueue(UUID queueId); + + interface RegistryChangeListener + { + void queueRegistered(AMQQueue queue); + void queueUnregistered(AMQQueue queue); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index d7eb304c92..3d54bba48f 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -19,8 +19,10 @@ package org.apache.qpid.server.queue; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -32,8 +34,6 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; -import javax.management.JMException; - import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.AMQSecurityException; @@ -52,7 +52,6 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.QueueActor; import org.apache.qpid.server.logging.messages.QueueMessages; import org.apache.qpid.server.logging.subjects.QueueLogSubject; -import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.registry.ApplicationRegistry; @@ -70,6 +69,7 @@ import org.apache.qpid.server.virtualhost.VirtualHost; public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, MessageGroupManager.SubscriptionResetHelper { private static final Logger _logger = Logger.getLogger(SimpleAMQQueue.class); + private static final String QPID_GROUP_HEADER_KEY = "qpid.group_header_key"; private static final String QPID_SHARED_MSG_GROUP = "qpid.shared_msg_group"; private static final String QPID_DEFAULT_MESSAGE_GROUP = "qpid.default-message-group"; @@ -77,11 +77,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes // TODO - should make this configurable at the vhost / broker level private static final int DEFAULT_MAX_GROUPS = 255; - private final VirtualHost _virtualHost; private final AMQShortString _name; - private final String _resourceName; /** null means shared */ private final AMQShortString _owner; @@ -118,6 +116,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private final AtomicLong _dequeueCount = new AtomicLong(); private final AtomicLong _dequeueSize = new AtomicLong(); + private final AtomicLong _enqueueCount = new AtomicLong(); private final AtomicLong _enqueueSize = new AtomicLong(); private final AtomicLong _persistentMessageEnqueueSize = new AtomicLong(); private final AtomicLong _persistentMessageDequeueSize = new AtomicLong(); @@ -130,6 +129,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private final AtomicLong _byteTxnDequeues = new AtomicLong(0); private final AtomicLong _unackedMsgCount = new AtomicLong(0); private final AtomicLong _unackedMsgCountHigh = new AtomicLong(0); + private final AtomicLong _unackedMsgBytes = new AtomicLong(); private final AtomicInteger _bindingCountHigh = new AtomicInteger(); @@ -173,7 +173,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private LogSubject _logSubject; private LogActor _logActor; - private AMQQueueMBean _managedObject; private static final String SUB_FLUSH_RUNNER = "SUB_FLUSH_RUNNER"; private boolean _nolocal; @@ -191,6 +190,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private int _maximumDeliveryCount = ApplicationRegistry.getInstance().getConfiguration().getMaxDeliveryCount(); private final MessageGroupManager _messageGroupManager; + private final Collection<SubscriptionRegistrationListener> _subscriptionListeners = + new ArrayList<SubscriptionRegistrationListener>(); + + private AMQQueue.NotificationListener _notificationListener; + private final long[] _lastNotificationTimes = new long[NotificationCheck.values().length]; + protected SimpleAMQQueue(UUID id, AMQShortString name, boolean durable, AMQShortString owner, boolean autoDelete, boolean exclusive, VirtualHost virtualHost, Map<String,Object> arguments) { this(id, name, durable, owner, autoDelete, exclusive,virtualHost, new SimpleQueueEntryList.Factory(), arguments); @@ -227,14 +232,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } _name = name; - _resourceName = String.valueOf(name); _durable = durable; _owner = owner; _autoDelete = autoDelete; _exclusive = exclusive; _virtualHost = virtualHost; _entries = entryListFactory.createQueueEntryList(this); - _arguments = arguments; + _arguments = arguments == null ? new HashMap<String, Object>() : new HashMap<String, Object>(arguments); _id = id; @@ -255,16 +259,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes getConfigStore().addConfiguredObject(this); - try - { - _managedObject = new AMQQueueMBean(this); - _managedObject.register(); - } - catch (JMException e) - { - _logger.error("AMQQueue MBean creation has failed ", e); - } - if(arguments != null && arguments.containsKey(QPID_GROUP_HEADER_KEY)) { if(arguments.containsKey(QPID_SHARED_MSG_GROUP) && String.valueOf(arguments.get(QPID_SHARED_MSG_GROUP)).equals("1")) @@ -339,15 +333,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { return _exclusive; } - - public void setExclusive(boolean exclusive) throws AMQException + + public void setExclusive(boolean exclusive) { _exclusive = exclusive; - - if(isDurable()) - { - getVirtualHost().getMessageStore().updateQueue(this); - } } public Exchange getAlternateExchange() @@ -368,22 +357,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes _alternateExchange = exchange; } - public void setAlternateExchange(String exchangeName) - { - if(exchangeName == null || exchangeName.equals("")) - { - _alternateExchange = null; - return; - } - - Exchange exchange = getVirtualHost().getExchangeRegistry().getExchange(new AMQShortString(exchangeName)); - if (exchange == null) - { - throw new RuntimeException("Exchange '" + exchangeName + "' is not registered with the VirtualHost."); - } - setAlternateExchange(exchange); - } - + /** + * Arguments used to create this queue. The caller is assured + * that null will never be returned. + */ public Map<String, Object> getArguments() { return _arguments; @@ -430,8 +407,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { throw new AMQSecurityException("Permission denied"); } - - + + if (hasExclusiveSubscriber()) { throw new ExistingExclusiveSubscription(); @@ -463,15 +440,24 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { subscription.setNoLocal(_nolocal); } + + synchronized (_subscriptionListeners) + { + for(SubscriptionRegistrationListener listener : _subscriptionListeners) + { + listener.subscriptionRegistered(this, subscription); + } + } + _subscriptionList.add(subscription); - + //Increment consumerCountHigh if necessary. (un)registerSubscription are both //synchronized methods so we don't need additional synchronization here if(_counsumerCountHigh.get() < getConsumerCount()) { _counsumerCountHigh.incrementAndGet(); } - + if (isDeleted()) { subscription.queueDeleted(this); @@ -507,6 +493,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes resetSubPointersForGroups(subscription, true); } + synchronized (_subscriptionListeners) + { + for(SubscriptionRegistrationListener listener : _subscriptionListeners) + { + listener.subscriptionUnregistered(this, subscription); + } + } + // auto-delete queues must be deleted if there are no remaining subscribers if (_autoDelete && getDeleteOnNoConsumers() && !subscription.isTransient() && getConsumerCount() == 0 ) @@ -526,6 +520,34 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } + public Collection<Subscription> getConsumers() + { + List<Subscription> consumers = new ArrayList<Subscription>(); + SubscriptionList.SubscriptionNodeIterator iter = _subscriptionList.iterator(); + while(iter.advance()) + { + consumers.add(iter.getNode().getSubscription()); + } + return consumers; + + } + + public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener) + { + synchronized (_subscriptionListeners) + { + _subscriptionListeners.add(listener); + } + } + + public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener) + { + synchronized (_subscriptionListeners) + { + _subscriptionListeners.remove(listener); + } + } + public void resetSubPointersForGroups(Subscription subscription, boolean clearAssignments) { QueueEntry entry = _messageGroupManager.findEarliestAssignedAvailableEntry(subscription); @@ -576,10 +598,10 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes break; } } - + reconfigure(); } - + private void reconfigure() { //Reconfigure the queue for to reflect this new binding. @@ -604,7 +626,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes public void removeBinding(final Binding binding) { _bindings.remove(binding); - + reconfigure(); } @@ -718,10 +740,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } } - if(_managedObject != null) - { - _managedObject.checkForNotification(entry.getMessage()); - } + checkForNotification(entry.getMessage()); if(action != null) { @@ -738,8 +757,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { try { - if (!sub.isSuspended() - && subscriptionReadyAndHasInterest(sub, entry) + if (!sub.isSuspended() + && subscriptionReadyAndHasInterest(sub, entry) && mightAssign(sub, entry) && !sub.wouldSuspend(entry)) { @@ -788,6 +807,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { long size = message.getSize(); getAtomicQueueSize().addAndGet(size); + _enqueueCount.incrementAndGet(); _enqueueSize.addAndGet(size); if(message.isPersistent() && isDurable()) { @@ -796,19 +816,29 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } } + public long getTotalDequeueCount() + { + return _dequeueCount.get(); + } + + public long getTotalEnqueueCount() + { + return _enqueueCount.get(); + } + private void incrementQueueCount() { getAtomicQueueCount().incrementAndGet(); } - + private void incrementTxnEnqueueStats(final ServerMessage message) { _msgTxnEnqueues.incrementAndGet(); _byteTxnEnqueues.addAndGet(message.getSize()); } - + private void incrementTxnDequeueStats(QueueEntry entry) - { + { _msgTxnDequeues.incrementAndGet(); _byteTxnDequeues.addAndGet(entry.getSize()); } @@ -819,7 +849,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes setLastSeenEntry(sub, entry); _deliveredMessages.incrementAndGet(); - incrementUnackedMsgCount(); + incrementUnackedMsgCount(entry); sub.send(entry, batch); } @@ -887,7 +917,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { _deliveredMessages.decrementAndGet(); } - + if(sub != null && sub.isSessionTransactional()) { incrementTxnDequeueStats(entry); @@ -940,11 +970,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } } + + public int getConsumerCount() { return _subscriptionList.size(); } - + public int getConsumerCountHigh() { return _counsumerCountHigh.get(); @@ -1148,7 +1180,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } - public void visit(final Visitor visitor) + public void visit(final QueueEntryVisitor visitor) { QueueEntryIterator queueListIterator = _entries.iterator(); @@ -1195,192 +1227,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } - public void moveMessagesToAnotherQueue(final long fromMessageId, - final long toMessageId, - String destinationQueueName) throws IllegalArgumentException - { - - final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName); - - List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() - { - - public boolean accept(QueueEntry entry) - { - final long messageId = entry.getMessage().getMessageNumber(); - return (messageId >= fromMessageId) - && (messageId <= toMessageId) - && entry.acquire(); - } - - public boolean filterComplete() - { - return false; - } - }); - - - final ServerTransaction txn = new LocalTransaction(getVirtualHost().getMessageStore()); - boolean shouldRollback = true; - try - { - // Move the messages in on the message store. - for (final QueueEntry entry : entries) - { - final ServerMessage message = entry.getMessage(); - txn.enqueue(toQueue, message, - new ServerTransaction.Action() - { - - public void postCommit() - { - try - { - toQueue.enqueue(message); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - } - - public void onRollback() - { - entry.release(); - } - }); - txn.dequeue(this, message, - new ServerTransaction.Action() - { - - public void postCommit() - { - entry.discard(); - } - - public void onRollback() - { - - } - }); - } - txn.commit(); - shouldRollback = false; - } - finally - { - if (shouldRollback) - { - txn.rollback(); - } - } - - } - - public void copyMessagesToAnotherQueue(final long fromMessageId, - final long toMessageId, - String destinationQueueName) throws IllegalArgumentException - { - final AMQQueue toQueue = getValidatedDestinationQueue(destinationQueueName); - - List<QueueEntry> entries = getMessagesOnTheQueue(new QueueEntryFilter() - { - - public boolean accept(QueueEntry entry) - { - final long messageId = entry.getMessage().getMessageNumber(); - return ((messageId >= fromMessageId) - && (messageId <= toMessageId)); - } - - public boolean filterComplete() - { - return false; - } - }); - - final ServerTransaction txn = new LocalTransaction(_virtualHost.getMessageStore()); - boolean shouldRollback = true; - try - { - // Copy the messages in on the message store. - for (QueueEntry entry : entries) - { - final ServerMessage message = entry.getMessage(); - - txn.enqueue(toQueue, message, new ServerTransaction.Action() - { - public void postCommit() - { - try - { - toQueue.enqueue(message); - } - catch (AMQException e) - { - throw new RuntimeException(e); - } - } - - public void onRollback() - { - } - }); - - } - - txn.commit(); - shouldRollback = false; - } - finally - { - if (shouldRollback) - { - txn.rollback(); - } - } - - } - - private AMQQueue getValidatedDestinationQueue(String queueName) - { - final AMQQueue toQueue = getVirtualHost().getQueueRegistry().getQueue(new AMQShortString(queueName)); - if (toQueue == null) - { - throw new IllegalArgumentException("Queue '" + queueName + "' is not registered with the virtualhost."); - } - else if (toQueue == this) - { - throw new IllegalArgumentException("The destination queue can't be the same as the source queue"); - } - return toQueue; - } - - public void removeMessagesFromQueue(long fromMessageId, long toMessageId) - { - - QueueEntryIterator queueListIterator = _entries.iterator(); - - while (queueListIterator.advance()) - { - QueueEntry node = queueListIterator.getNode(); - - final ServerMessage message = node.getMessage(); - if(message != null) - { - final long messageId = message.getMessageNumber(); - - if ((messageId >= fromMessageId) - && (messageId <= toMessageId) - && node.acquire()) - { - dequeueEntry(node); - } - } - } - - } - public void purge(final long request) throws AMQException { clear(request); @@ -1393,6 +1239,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes // ------ Management functions + // TODO - now only used by the tests public void deleteMessageFromTop() { QueueEntryIterator queueListIterator = _entries.iterator(); @@ -1411,7 +1258,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } public long clearQueue() throws AMQException - { + { return clear(0l); } @@ -1422,7 +1269,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { throw new AMQSecurityException("Permission denied: queue " + getName()); } - + QueueEntryIterator queueListIterator = _entries.iterator(); long count = 0; @@ -1489,7 +1336,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { throw new AMQSecurityException("Permission denied: " + getName()); } - + if (!_deleted.getAndSet(true)) { @@ -1617,12 +1464,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes txn.commit(); - - if(_managedObject!=null) - { - _managedObject.unregister(); - } - for (Task task : _deleteTaskList) { task.doTask(this); @@ -2101,16 +1942,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } else { - if (_managedObject != null) + // There is a chance that the node could be deleted by + // the time the check actually occurs. So verify we + // can actually get the message to perform the check. + ServerMessage msg = node.getMessage(); + if (msg != null) { - // There is a chance that the node could be deleted by - // the time the check actually occurs. So verify we - // can actually get the message to perform the check. - ServerMessage msg = node.getMessage(); - if (msg != null) - { - _managedObject.checkForNotification(msg); - } + checkForNotification(msg); } } } @@ -2235,11 +2073,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes return _notificationChecks; } - public ManagedObject getManagedObject() - { - return _managedObject; - } - private final class QueueEntryListener implements QueueEntry.StateChangeListener { @@ -2330,12 +2163,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes return _queueConfiguration; } - public String getResourceName() - { - return _resourceName; - } - - public ConfigStore getConfigStore() { return getVirtualHost().getConfigStore(); @@ -2355,22 +2182,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { return _dequeueSize.get(); } - + public long getByteTxnEnqueues() { return _byteTxnEnqueues.get(); } - + public long getByteTxnDequeues() { return _byteTxnDequeues.get(); } - + public long getMsgTxnEnqueues() { return _msgTxnEnqueues.get(); } - + public long getMsgTxnDequeues() { return _msgTxnDequeues.get(); @@ -2407,21 +2234,28 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { return _unackedMsgCountHigh.get(); } - + public long getUnackedMessageCount() { return _unackedMsgCount.get(); } - - public void decrementUnackedMsgCount() + + public long getUnackedMessageBytes() + { + return _unackedMsgBytes.get(); + } + + public void decrementUnackedMsgCount(QueueEntry queueEntry) { _unackedMsgCount.decrementAndGet(); + _unackedMsgBytes.addAndGet(-queueEntry.getSize()); } - - private void incrementUnackedMsgCount() + + private void incrementUnackedMsgCount(QueueEntry entry) { long unackedMsgCount = _unackedMsgCount.incrementAndGet(); - + _unackedMsgBytes.addAndGet(entry.getSize()); + long unackedMsgCountHigh; while(unackedMsgCount > (unackedMsgCountHigh = _unackedMsgCountHigh.get())) { @@ -2447,4 +2281,54 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes _maximumDeliveryCount = maximumDeliveryCount; } + /** + * Checks if there is any notification to send to the listeners + */ + private void checkForNotification(ServerMessage<?> msg) throws AMQException + { + final Set<NotificationCheck> notificationChecks = getNotificationChecks(); + final AMQQueue.NotificationListener listener = _notificationListener; + + if(listener != null && !notificationChecks.isEmpty()) + { + final long currentTime = System.currentTimeMillis(); + final long thresholdTime = currentTime - getMinimumAlertRepeatGap(); + + for (NotificationCheck check : notificationChecks) + { + if (check.isMessageSpecific() || (_lastNotificationTimes[check.ordinal()] < thresholdTime)) + { + if (check.notifyIfNecessary(msg, this, listener)) + { + _lastNotificationTimes[check.ordinal()] = currentTime; + } + } + } + } + } + + public void setNotificationListener(AMQQueue.NotificationListener listener) + { + _notificationListener = listener; + } + + @Override + public void setDescription(String description) + { + if (description == null) + { + _arguments.remove(AMQQueueFactory.X_QPID_DESCRIPTION); + } + else + { + _arguments.put(AMQQueueFactory.X_QPID_DESCRIPTION, description); + } + } + + @Override + public String getDescription() + { + return (String) _arguments.get(AMQQueueFactory.X_QPID_DESCRIPTION); + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index 80a91be262..10c69b7f97 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java @@ -22,9 +22,9 @@ package org.apache.qpid.server.registry; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; +import org.apache.qpid.server.logging.*; import org.osgi.framework.BundleContext; -import org.apache.qpid.AMQException; import org.apache.qpid.common.Closeable; import org.apache.qpid.common.QpidProperties; import org.apache.qpid.qmf.QMFService; @@ -35,18 +35,13 @@ import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.configuration.SystemConfig; import org.apache.qpid.server.configuration.SystemConfigImpl; import org.apache.qpid.server.configuration.VirtualHostConfiguration; -import org.apache.qpid.server.logging.CompositeStartupMessageLogger; -import org.apache.qpid.server.logging.Log4jMessageLogger; -import org.apache.qpid.server.logging.LogActor; -import org.apache.qpid.server.logging.RootMessageLogger; -import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.AbstractActor; import org.apache.qpid.server.logging.actors.BrokerActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.logging.messages.VirtualHostMessages; -import org.apache.qpid.server.management.ManagedObjectRegistry; -import org.apache.qpid.server.management.NoopManagedObjectRegistry; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.adapter.BrokerAdapter; import org.apache.qpid.server.plugins.PluginManager; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; @@ -72,6 +67,7 @@ import java.util.concurrent.atomic.AtomicReference; */ public abstract class ApplicationRegistry implements IApplicationRegistry { + private static final Logger _logger = Logger.getLogger(ApplicationRegistry.class); private static AtomicReference<IApplicationRegistry> _instance = new AtomicReference<IApplicationRegistry>(null); @@ -81,11 +77,9 @@ public abstract class ApplicationRegistry implements IApplicationRegistry private final Map<InetSocketAddress, QpidAcceptor> _acceptors = Collections.synchronizedMap(new HashMap<InetSocketAddress, QpidAcceptor>()); - private ManagedObjectRegistry _managedObjectRegistry; - private IAuthenticationManagerRegistry _authenticationManagerRegistry; - private VirtualHostRegistry _virtualHostRegistry; + private final VirtualHostRegistry _virtualHostRegistry = new VirtualHostRegistry(this); private SecurityManager _securityManager; @@ -101,30 +95,32 @@ public abstract class ApplicationRegistry implements IApplicationRegistry private QMFService _qmfService; - private BrokerConfig _broker; + private BrokerConfig _brokerConfig; + + private Broker _broker; private ConfigStore _configStore; - + private Timer _reportingTimer; - private boolean _statisticsEnabled = false; private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; private BundleContext _bundleContext; + private final List<PortBindingListener> _portBindingListeners = new ArrayList<PortBindingListener>(); - protected Map<InetSocketAddress, QpidAcceptor> getAcceptors() - { - return _acceptors; - } + private int _httpManagementPort = -1; - protected void setManagedObjectRegistry(ManagedObjectRegistry managedObjectRegistry) - { - _managedObjectRegistry = managedObjectRegistry; - } + private LogRecorder _logRecorder; + + private List<IAuthenticationManagerRegistry.RegistryChangeListener> _authManagerChangeListeners = + new ArrayList<IAuthenticationManagerRegistry.RegistryChangeListener>(); - protected void setVirtualHostRegistry(VirtualHostRegistry virtualHostRegistry) + public Map<InetSocketAddress, QpidAcceptor> getAcceptors() { - _virtualHostRegistry = virtualHostRegistry; + synchronized (_acceptors) + { + return new HashMap<InetSocketAddress, QpidAcceptor>(_acceptors); + } } protected void setSecurityManager(SecurityManager securityManager) @@ -191,11 +187,11 @@ public abstract class ApplicationRegistry implements IApplicationRegistry store.setRoot(new SystemConfigImpl(store)); instance.setConfigStore(store); - BrokerConfig broker = new BrokerConfigAdapter(instance); + final BrokerConfig brokerConfig = new BrokerConfigAdapter(instance); - SystemConfig system = store.getRoot(); - system.addBroker(broker); - instance.setBroker(broker); + final SystemConfig system = store.getRoot(); + system.addBroker(brokerConfig); + instance.setBrokerConfig(brokerConfig); try { @@ -208,7 +204,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry //remove the Broker instance, then re-throw try { - system.removeBroker(broker); + system.removeBroker(brokerConfig); } catch(Throwable t) { @@ -283,18 +279,28 @@ public abstract class ApplicationRegistry implements IApplicationRegistry public void initialise() throws Exception { + _logRecorder = new LogRecorder(); //Create the RootLogger to be used during broker operation _rootMessageLogger = new Log4jMessageLogger(_configuration); //Create the composite (log4j+SystemOut MessageLogger to be used during startup RootMessageLogger[] messageLoggers = {new SystemOutMessageLogger(), _rootMessageLogger}; _startupMessageLogger = new CompositeStartupMessageLogger(messageLoggers); - - CurrentActor.set(new BrokerActor(_startupMessageLogger)); + + BrokerActor actor = new BrokerActor(_startupMessageLogger); + CurrentActor.setDefault(actor); + CurrentActor.set(actor); try { - initialiseManagedObjectRegistry(); + initialiseStatistics(); + + if(_configuration.getHTTPManagementEnabled()) + { + _httpManagementPort = _configuration.getHTTPManagementPort(); + } + + _broker = new BrokerAdapter(this); configure(); @@ -302,13 +308,23 @@ public abstract class ApplicationRegistry implements IApplicationRegistry logStartupMessages(CurrentActor.get()); - _virtualHostRegistry = new VirtualHostRegistry(this); - _securityManager = new SecurityManager(_configuration, _pluginManager); _authenticationManagerRegistry = createAuthenticationManagerRegistry(_configuration, _pluginManager); - _managedObjectRegistry.start(); + if(!_authManagerChangeListeners.isEmpty()) + { + for(IAuthenticationManagerRegistry.RegistryChangeListener listener : _authManagerChangeListeners) + { + + _authenticationManagerRegistry.addRegistryChangeListener(listener); + for(AuthenticationManager authMgr : _authenticationManagerRegistry.getAvailableAuthenticationManagers().values()) + { + listener.authenticationManagerRegistered(authMgr); + } + } + _authManagerChangeListeners.clear(); + } } finally { @@ -319,7 +335,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry try { initialiseVirtualHosts(); - initialiseStatistics(); initialiseStatisticsReporting(); } finally @@ -344,23 +359,18 @@ public abstract class ApplicationRegistry implements IApplicationRegistry getVirtualHostRegistry().setDefaultVirtualHostName(_configuration.getDefaultVirtualHost()); } - protected void initialiseManagedObjectRegistry() throws AMQException - { - _managedObjectRegistry = new NoopManagedObjectRegistry(); - } - public void initialiseStatisticsReporting() { long report = _configuration.getStatisticsReportingPeriod() * 1000; // convert to ms final boolean broker = _configuration.isStatisticsGenerationBrokerEnabled(); final boolean virtualhost = _configuration.isStatisticsGenerationVirtualhostsEnabled(); final boolean reset = _configuration.isStatisticsReportResetEnabled(); - + /* add a timer task to report statistics if generation is enabled for broker or virtualhosts */ if (report > 0L && (broker || virtualhost)) { _reportingTimer = new Timer("Statistics-Reporting", true); - + _reportingTimer.scheduleAtFixedRate(new StatisticsReportingTask(broker, virtualhost, reset), @@ -495,9 +505,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry close(_pluginManager); - close(_managedObjectRegistry); - - BrokerConfig broker = getBroker(); + BrokerConfig broker = getBrokerConfig(); if(broker != null) { broker.getSystem().removeBroker(broker); @@ -513,12 +521,14 @@ public abstract class ApplicationRegistry implements IApplicationRegistry private void unbind() { + List<QpidAcceptor> removedAcceptors = new ArrayList<QpidAcceptor>(); synchronized (_acceptors) { for (InetSocketAddress bindAddress : _acceptors.keySet()) { QpidAcceptor acceptor = _acceptors.get(bindAddress); + removedAcceptors.add(acceptor); try { acceptor.getNetworkTransport().close(); @@ -531,6 +541,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry CurrentActor.get().message(BrokerMessages.SHUTTING_DOWN(acceptor.toString(), bindAddress.getPort())); } } + synchronized (_portBindingListeners) + { + for(QpidAcceptor acceptor : removedAcceptors) + { + for(PortBindingListener listener : _portBindingListeners) + { + listener.unbound(acceptor); + } + } + } } public ServerConfiguration getConfiguration() @@ -544,6 +564,13 @@ public abstract class ApplicationRegistry implements IApplicationRegistry { _acceptors.put(bindAddress, acceptor); } + synchronized (_portBindingListeners) + { + for(PortBindingListener listener : _portBindingListeners) + { + listener.bound(acceptor, bindAddress); + } + } } public VirtualHostRegistry getVirtualHostRegistry() @@ -556,15 +583,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry return _securityManager; } - public ManagedObjectRegistry getManagedObjectRegistry() + @Override + public AuthenticationManager getAuthenticationManager(SocketAddress address) { - return _managedObjectRegistry; + return _authenticationManagerRegistry.getAuthenticationManager(address); } @Override - public AuthenticationManager getAuthenticationManager(SocketAddress address) + public IAuthenticationManagerRegistry getAuthenticationManagerRegistry() { - return _authenticationManagerRegistry.getAuthenticationManager(address); + return _authenticationManagerRegistry; } public PluginManager getPluginManager() @@ -581,7 +609,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry { return _rootMessageLogger; } - + public RootMessageLogger getCompositeStartupMessageLogger() { return _startupMessageLogger; @@ -597,69 +625,63 @@ public abstract class ApplicationRegistry implements IApplicationRegistry return _qmfService; } - public BrokerConfig getBroker() + public BrokerConfig getBrokerConfig() { - return _broker; + return _brokerConfig; } - public void setBroker(final BrokerConfig broker) + public void setBrokerConfig(final BrokerConfig broker) { - _broker = broker; + _brokerConfig = broker; } public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception { VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig); _virtualHostRegistry.registerVirtualHost(virtualHost); - getBroker().addVirtualHost(virtualHost); + getBrokerConfig().addVirtualHost(virtualHost); return virtualHost; } - + public void registerMessageDelivered(long messageSize) { - if (isStatisticsEnabled()) - { - _messagesDelivered.registerEvent(1L); - _dataDelivered.registerEvent(messageSize); - } + _messagesDelivered.registerEvent(1L); + _dataDelivered.registerEvent(messageSize); } - + public void registerMessageReceived(long messageSize, long timestamp) { - if (isStatisticsEnabled()) - { - _messagesReceived.registerEvent(1L, timestamp); - _dataReceived.registerEvent(messageSize, timestamp); - } + _messagesReceived.registerEvent(1L, timestamp); + _dataReceived.registerEvent(messageSize, timestamp); } - + public StatisticsCounter getMessageReceiptStatistics() { return _messagesReceived; } - + public StatisticsCounter getDataReceiptStatistics() { return _dataReceived; } - + public StatisticsCounter getMessageDeliveryStatistics() { return _messagesDelivered; } - + public StatisticsCounter getDataDeliveryStatistics() { return _dataDelivered; } - + public void resetStatistics() { _messagesDelivered.reset(); _dataDelivered.reset(); _messagesReceived.reset(); _dataReceived.reset(); - + for (VirtualHost vhost : _virtualHostRegistry.getVirtualHosts()) { vhost.resetStatistics(); @@ -668,25 +690,12 @@ public abstract class ApplicationRegistry implements IApplicationRegistry public void initialiseStatistics() { - setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS && - getConfiguration().isStatisticsGenerationBrokerEnabled()); - _messagesDelivered = new StatisticsCounter("messages-delivered"); _dataDelivered = new StatisticsCounter("bytes-delivered"); _messagesReceived = new StatisticsCounter("messages-received"); _dataReceived = new StatisticsCounter("bytes-received"); } - public boolean isStatisticsEnabled() - { - return _statisticsEnabled; - } - - public void setStatisticsEnabled(boolean enabled) - { - _statisticsEnabled = enabled; - } - private void logStartupMessages(LogActor logActor) { logActor.message(BrokerMessages.STARTUP(QpidProperties.getReleaseVersion(), QpidProperties.getBuildVersion())); @@ -700,4 +709,48 @@ public abstract class ApplicationRegistry implements IApplicationRegistry logActor.message(BrokerMessages.MAX_MEMORY(Runtime.getRuntime().maxMemory())); } + public Broker getBroker() + { + return _broker; + } + + @Override + public void addPortBindingListener(PortBindingListener listener) + { + synchronized (_portBindingListeners) + { + _portBindingListeners.add(listener); + } + } + + + @Override + public boolean useHTTPManagement() + { + return _httpManagementPort != -1; + } + + @Override + public int getHTTPManagementPort() + { + return _httpManagementPort; + } + + public LogRecorder getLogRecorder() + { + return _logRecorder; + } + + @Override + public void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener) + { + if(_authenticationManagerRegistry == null) + { + _authManagerChangeListeners.add(registryChangeListener); + } + else + { + _authenticationManagerRegistry.addRegistryChangeListener(registryChangeListener); + } + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java index b28e3d6c89..774d0338ef 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java @@ -25,8 +25,6 @@ import org.osgi.framework.BundleContext; import org.apache.qpid.AMQException; import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.management.JMXManagedObjectRegistry; -import org.apache.qpid.server.management.NoopManagedObjectRegistry; import java.io.File; @@ -41,18 +39,4 @@ public class ConfigurationFileApplicationRegistry extends ApplicationRegistry { super(new ServerConfiguration(configurationURL), bundleContext); } - - @Override - protected void initialiseManagedObjectRegistry() throws AMQException - { - if (getConfiguration().getManagementEnabled()) - { - setManagedObjectRegistry(new JMXManagedObjectRegistry()); - } - else - { - setManagedObjectRegistry(new NoopManagedObjectRegistry()); - } - } - } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java index 35e7fe3f61..2baf7ed5ee 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java @@ -27,10 +27,11 @@ import org.apache.qpid.server.configuration.ConfigurationManager; import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.configuration.VirtualHostConfiguration; import org.apache.qpid.server.logging.RootMessageLogger; -import org.apache.qpid.server.management.ManagedObjectRegistry; +import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.plugins.PluginManager; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; import org.apache.qpid.server.stats.StatisticsGatherer; import org.apache.qpid.server.transport.QpidAcceptor; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -38,6 +39,7 @@ import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.util.Map; import java.util.UUID; public interface IApplicationRegistry extends StatisticsGatherer @@ -61,8 +63,6 @@ public interface IApplicationRegistry extends StatisticsGatherer */ ServerConfiguration getConfiguration(); - ManagedObjectRegistry getManagedObjectRegistry(); - /** * Get the AuthenticationManager for the given socket address * @@ -74,6 +74,8 @@ public interface IApplicationRegistry extends StatisticsGatherer */ AuthenticationManager getAuthenticationManager(SocketAddress address); + IAuthenticationManagerRegistry getAuthenticationManagerRegistry(); + VirtualHostRegistry getVirtualHostRegistry(); SecurityManager getSecurityManager(); @@ -95,15 +97,35 @@ public interface IApplicationRegistry extends StatisticsGatherer QMFService getQMFService(); - void setBroker(BrokerConfig broker); + void setBrokerConfig(BrokerConfig broker); + + BrokerConfig getBrokerConfig(); - BrokerConfig getBroker(); + Broker getBroker(); VirtualHost createVirtualHost(VirtualHostConfiguration vhostConfig) throws Exception; ConfigStore getConfigStore(); void setConfigStore(ConfigStore store); - + void initialiseStatisticsReporting(); + + Map<InetSocketAddress, QpidAcceptor> getAcceptors(); + + void addPortBindingListener(PortBindingListener listener); + + boolean useHTTPManagement(); + + int getHTTPManagementPort(); + + void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener); + + public interface PortBindingListener + { + public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress); + public void unbound(QpidAcceptor acceptor); + + } + } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java index 7088fae50c..cac60a5283 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java @@ -198,7 +198,7 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr try { _userUpdate.lock(); - _userMap.clear(); + final Map<String, U> newUserMap = new HashMap<String, U>(); BufferedReader reader = null; try @@ -216,7 +216,7 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr U user = createUserFromFileData(result); getLogger().info("Created user:" + user); - _userMap.put(user.getName(), user); + newUserMap.put(user.getName(), user); } } finally @@ -226,6 +226,9 @@ public abstract class AbstractPasswordFilePrincipalDatabase<U extends PasswordPr reader.close(); } } + + _userMap.clear(); + _userMap.putAll(newUserMap); } finally { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java deleted file mode 100644 index 1314a5d6a6..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.security.auth.management; - -import org.apache.log4j.Logger; - -import org.apache.qpid.management.common.mbeans.UserManagement; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import javax.management.openmbean.TabularType; -import javax.security.auth.login.AccountNotFoundException; -import java.io.IOException; -import java.security.Principal; -import java.util.List; - -/** MBean class for AMQUserManagementMBean. It implements all the management features exposed for managing users. */ -@MBeanDescription("User Management Interface") -public class AMQUserManagementMBean extends AMQManagedObject implements UserManagement -{ - private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class); - - private PrincipalDatabase _principalDatabase; - - // Setup for the TabularType - private static final TabularType _userlistDataType; // Datatype for representing User Lists - private static final CompositeType _userDataType; // Composite type for representing User - - static - { - OpenType[] userItemTypes = new OpenType[4]; // User item types. - userItemTypes[0] = SimpleType.STRING; // For Username - userItemTypes[1] = SimpleType.BOOLEAN; // For Rights - Read - No longer in use - userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write - No longer in use - userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin - No longer is use - - try - { - _userDataType = - new CompositeType("User", "User Data", COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), - COMPOSITE_ITEM_DESCRIPTIONS.toArray(new String[COMPOSITE_ITEM_DESCRIPTIONS.size()]), userItemTypes); - - _userlistDataType = new TabularType("Users", "List of users", _userDataType, TABULAR_UNIQUE_INDEX.toArray(new String[TABULAR_UNIQUE_INDEX.size()])); - } - catch (OpenDataException e) - { - _logger.error("Tabular data setup for viewing users incorrect.", e); - throw new ExceptionInInitializerError("Tabular data setup for viewing users incorrect"); - } - } - - public AMQUserManagementMBean() throws JMException - { - super(UserManagement.class, UserManagement.TYPE); - } - - public String getObjectInstanceName() - { - return UserManagement.TYPE; - } - - public boolean setPassword(String username, String password) - { - try - { - //delegate password changes to the Principal Database - return _principalDatabase.updatePassword(new UsernamePrincipal(username), password.toCharArray()); - } - catch (AccountNotFoundException e) - { - _logger.warn("Attempt to set password of non-existent user'" + username + "'"); - return false; - } - } - - public boolean createUser(String username, String password) - { - if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password.toCharArray())) - { - return true; - } - - return false; - } - - public boolean deleteUser(String username) - { - try - { - _principalDatabase.deletePrincipal(new UsernamePrincipal(username)); - } - catch (AccountNotFoundException e) - { - _logger.warn("Attempt to delete user (" + username + ") that doesn't exist"); - return false; - } - - return true; - } - - public boolean reloadData() - { - try - { - _principalDatabase.reload(); - } - catch (IOException e) - { - _logger.warn("Reload failed due to:", e); - return false; - } - // Reload successful - return true; - } - - - @MBeanOperation(name = "viewUsers", description = "All users that are currently available to the system.") - public TabularData viewUsers() - { - List<Principal> users = _principalDatabase.getUsers(); - - TabularDataSupport userList = new TabularDataSupport(_userlistDataType); - - try - { - // Create the tabular list of message header contents - for (Principal user : users) - { - // Create header attributes list - // Read,Write,Admin items are depcreated and we return always false. - Object[] itemData = {user.getName(), false, false, false}; - CompositeData messageData = new CompositeDataSupport(_userDataType, COMPOSITE_ITEM_NAMES.toArray(new String[COMPOSITE_ITEM_NAMES.size()]), itemData); - userList.put(messageData); - } - } - catch (OpenDataException e) - { - _logger.warn("Unable to create user list due to :", e); - return null; - } - - return userList; - } - - /*** Broker Methods **/ - - /** - * setPrincipalDatabase - * - * @param database set The Database to use for user lookup - */ - public void setPrincipalDatabase(PrincipalDatabase database) - { - _principalDatabase = database; - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java index 0eb3963865..5676c43754 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java @@ -47,7 +47,7 @@ public class AnonymousAuthenticationManager implements AuthenticationManager private static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal("ANONYMOUS"); - private static final Subject ANONYMOUS_SUBJECT = new Subject(); + public static final Subject ANONYMOUS_SUBJECT = new Subject(); static { ANONYMOUS_SUBJECT.getPrincipals().add(ANONYMOUS_PRINCIPAL); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java index 3a1ca4f19d..89a4d8ae66 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java @@ -21,9 +21,12 @@ package org.apache.qpid.server.security.auth.manager; import java.net.InetSocketAddress; import java.net.SocketAddress; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import org.apache.commons.configuration.ConfigurationException; @@ -49,6 +52,8 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication private final Map<String,AuthenticationManager> _classToAuthManagerMap = new HashMap<String,AuthenticationManager>(); private final AuthenticationManager _defaultAuthenticationManager; private final Map<Integer,AuthenticationManager> _portToAuthenticationManagerMap; + private final List<RegistryChangeListener> _listeners = + Collections.synchronizedList(new ArrayList<RegistryChangeListener>()); public AuthenticationManagerRegistry(ServerConfiguration serverConfiguration, PluginManager _pluginManager) throws ConfigurationException @@ -114,9 +119,8 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication final SecurityConfiguration securityConfiguration) throws ConfigurationException { - for (final Iterator<AuthenticationManagerPluginFactory<? extends Plugin>> iterator = factories.iterator(); iterator.hasNext();) + for(AuthenticationManagerPluginFactory<? extends Plugin> factory : factories) { - final AuthenticationManagerPluginFactory<? extends Plugin> factory = (AuthenticationManagerPluginFactory<? extends Plugin>) iterator.next(); final AuthenticationManager tmp = factory.newInstance(securityConfiguration); if (tmp != null) { @@ -127,6 +131,11 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication + " Remove configuration for one of the authentication managers."); } _classToAuthManagerMap.put(tmp.getClass().getSimpleName(),tmp); + + for(RegistryChangeListener listener : _listeners) + { + listener.authenticationManagerRegistered(tmp); + } } } } @@ -179,5 +188,16 @@ public class AuthenticationManagerRegistry implements Closeable, IAuthentication return portToAuthenticationManagerMap; } + @Override + public Map<String, AuthenticationManager> getAvailableAuthenticationManagers() + { + return Collections.unmodifiableMap(new HashMap<String, AuthenticationManager>(_classToAuthManagerMap)); + } + + @Override + public void addRegistryChangeListener(RegistryChangeListener listener) + { + _listeners.add(listener); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java index bfb49b8ed6..485ca2e1e9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java @@ -21,7 +21,9 @@ package org.apache.qpid.server.security.auth.manager; import java.net.SocketAddress; +import java.util.Map; import org.apache.qpid.common.Closeable; +import org.apache.qpid.server.virtualhost.VirtualHost; /** * Registry for {@link AuthenticationManager} instances. @@ -43,4 +45,15 @@ public interface IAuthenticationManagerRegistry extends Closeable * @return authentication manager. */ public AuthenticationManager getAuthenticationManager(SocketAddress address); + + Map<String, AuthenticationManager> getAvailableAuthenticationManagers(); + + public static interface RegistryChangeListener + { + void authenticationManagerRegistered(AuthenticationManager authenticationManager); + void authenticationManagerUnregistered(AuthenticationManager authenticationManager); + } + + public void addRegistryChangeListener(RegistryChangeListener listener); + }
\ No newline at end of file diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java index 24b365d34c..e6498919a1 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java @@ -32,7 +32,6 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; import org.apache.qpid.server.security.auth.database.PrincipalDatabase; -import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean; import org.apache.qpid.server.security.auth.sasl.AuthenticationProviderInitialiser; import org.apache.qpid.server.security.auth.sasl.JCAProvider; import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; @@ -98,8 +97,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan private PrincipalDatabase _principalDatabase = null; - private AMQUserManagementMBean _mbean = null; - public static final AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<PrincipalDatabaseAuthenticationManager>() { public PrincipalDatabaseAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException @@ -211,8 +208,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan { _logger.warn("No additional SASL providers registered."); } - - registerManagement(); } private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database) @@ -332,8 +327,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan { _mechanisms = null; Security.removeProvider(PROVIDER_NAME); - - unregisterManagement(); } private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException @@ -407,6 +400,11 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan } } + public PrincipalDatabase getPrincipalDatabase() + { + return _principalDatabase; + } + private String generateSetterName(String argName) throws ConfigurationException { if ((argName == null) || (argName.length() == 0)) @@ -427,41 +425,4 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan { _principalDatabase = principalDatabase; } - - protected void registerManagement() - { - try - { - _logger.info("Registering UserManagementMBean"); - - _mbean = new AMQUserManagementMBean(); - _mbean.setPrincipalDatabase(_principalDatabase); - _mbean.register(); - } - catch (Exception e) - { - _logger.warn("User management disabled as unable to create MBean:", e); - _mbean = null; - } - } - - protected void unregisterManagement() - { - try - { - if (_mbean != null) - { - _logger.info("Unregistering UserManagementMBean"); - _mbean.unregister(); - } - } - catch (Exception e) - { - _logger.warn("Failed to unregister User management MBean:", e); - } - finally - { - _mbean = null; - } - } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java index e27fd99f90..2e21cfbb07 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java @@ -20,6 +20,9 @@ */ package org.apache.qpid.server.security.auth.rmi; +import java.net.SocketAddress; + +import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; @@ -37,11 +40,13 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator static final String INVALID_CREDENTIALS = "Invalid user details supplied"; static final String CREDENTIALS_REQUIRED = "User details are required. " + "Please ensure you are using an up to date management console to connect."; - + private AuthenticationManager _authenticationManager = null; + private SocketAddress _socketAddress; - public RMIPasswordAuthenticator() + public RMIPasswordAuthenticator(SocketAddress socketAddress) { + _socketAddress = socketAddress; } public void setAuthenticationManager(final AuthenticationManager authenticationManager) @@ -79,11 +84,25 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator { throw new SecurityException(SHOULD_BE_NON_NULL); } - + // Verify that an AuthenticationManager has been set. if (_authenticationManager == null) { - throw new SecurityException(UNABLE_TO_LOOKUP); + try + { + if(ApplicationRegistry.getInstance().getAuthenticationManager(_socketAddress) != null) + { + _authenticationManager = ApplicationRegistry.getInstance().getAuthenticationManager(_socketAddress); + } + else + { + throw new SecurityException(UNABLE_TO_LOOKUP); + } + } + catch(IllegalStateException e) + { + throw new SecurityException(UNABLE_TO_LOOKUP); + } } final AuthenticationResult result = _authenticationManager.authenticate(username, password); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java index 2bd17cfa2f..f382f90010 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java @@ -33,8 +33,7 @@ public class StatisticsCounter private static final Logger _log = LoggerFactory.getLogger(StatisticsCounter.class); public static final long DEFAULT_SAMPLE_PERIOD = Long.getLong("qpid.statistics.samplePeriod", 2000L); // 2s - public static final boolean DISABLE_STATISTICS = Boolean.getBoolean("qpid.statistics.disable"); - + private static final String COUNTER = "counter"; private static final AtomicLong _counterIds = new AtomicLong(0L); @@ -78,11 +77,6 @@ public class StatisticsCounter public void registerEvent(long value, long timestamp) { - if (DISABLE_STATISTICS) - { - return; - } - long thisSample = (timestamp / _period); synchronized (this) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java index 36fec4025a..37d87bb628 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java @@ -103,16 +103,4 @@ public interface StatisticsGatherer * Reset the counters for this, and any child {@link StatisticsGatherer}s. */ void resetStatistics(); - - /** - * Check if this object has statistics generation enabled. - * - * @return true if statistics generation is enabled - */ - boolean isStatisticsEnabled(); - - /** - * Enable or disable statistics generation for this object. - */ - void setStatisticsEnabled(boolean enabled); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java index 1307b1dbd4..f1053f60ad 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java @@ -32,7 +32,7 @@ public interface ConfigurationRecoveryHandler public static interface QueueRecoveryHandler { - void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments); + void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId); ExchangeRecoveryHandler completeQueueRecovery(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java index 1a67fdf540..7356e1ae83 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java @@ -40,12 +40,7 @@ import org.apache.qpid.server.util.MapJsonSerializer; public class ConfiguredObjectHelper { - /** - * Name of queue attribute to store queue creation arguments. - * <p> - * This attribute is not defined yet on Queue configured object interface. - */ - private static final String QUEUE_ARGUMENTS = "ARGUMENTS"; + private MapJsonSerializer _serializer = new MapJsonSerializer(); @@ -57,14 +52,15 @@ public class ConfiguredObjectHelper String queueName = (String) attributeMap.get(Queue.NAME); String owner = (String) attributeMap.get(Queue.OWNER); boolean exclusive = (Boolean) attributeMap.get(Queue.EXCLUSIVE); + UUID alternateExchangeId = attributeMap.get(Queue.ALTERNATE_EXCHANGE) == null ? null : UUID.fromString((String)attributeMap.get(Queue.ALTERNATE_EXCHANGE)); @SuppressWarnings("unchecked") - Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(QUEUE_ARGUMENTS); + Map<String, Object> queueArgumentsMap = (Map<String, Object>) attributeMap.get(Queue.ARGUMENTS); FieldTable arguments = null; if (queueArgumentsMap != null) { arguments = FieldTable.convertToFieldTable(queueArgumentsMap); } - qrh.queue(configuredObject.getId(), queueName, owner, exclusive, arguments); + qrh.queue(configuredObject.getId(), queueName, owner, exclusive, arguments, alternateExchangeId); } } @@ -73,6 +69,24 @@ public class ConfiguredObjectHelper Map<String, Object> attributesMap = _serializer.deserialize(queueRecord.getAttributes()); attributesMap.put(Queue.NAME, queue.getName()); attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive()); + if (queue.getAlternateExchange() != null) + { + attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId()); + } + else + { + attributesMap.remove(Queue.ALTERNATE_EXCHANGE); + } + if (attributesMap.containsKey(Queue.ARGUMENTS)) + { + // We wouldn't need this if createQueueConfiguredObject took only AMQQueue + Map<String, Object> currentArgs = (Map<String, Object>) attributesMap.get(Queue.ARGUMENTS); + currentArgs.putAll(queue.getArguments()); + } + else + { + attributesMap.put(Queue.ARGUMENTS, queue.getArguments()); + } String newJson = _serializer.serialize(attributesMap); ConfiguredObjectRecord newQueueRecord = new ConfiguredObjectRecord(queue.getId(), queueRecord.getType(), newJson); return newQueueRecord; @@ -84,9 +98,15 @@ public class ConfiguredObjectHelper attributesMap.put(Queue.NAME, queue.getName()); attributesMap.put(Queue.OWNER, AMQShortString.toString(queue.getOwner())); attributesMap.put(Queue.EXCLUSIVE, queue.isExclusive()); + if (queue.getAlternateExchange() != null) + { + attributesMap.put(Queue.ALTERNATE_EXCHANGE, queue.getAlternateExchange().getId()); + } + // TODO KW i think the arguments could come from the queue itself removing the need for the parameter arguments. + // It would also do away with the need for the if/then/else within updateQueueConfiguredObject if (arguments != null) { - attributesMap.put(QUEUE_ARGUMENTS, FieldTable.convertToMap(arguments)); + attributesMap.put(Queue.ARGUMENTS, FieldTable.convertToMap(arguments)); } String json = _serializer.serialize(attributesMap); ConfiguredObjectRecord configuredObject = new ConfiguredObjectRecord(queue.getId(), Queue.class.getName(), json); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java index 7b98b30860..262d7d0213 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java @@ -134,4 +134,10 @@ public class MemoryMessageStore extends NullMessageStore { _eventManager.addEventListener(eventListener, events); } + + @Override + public String getStoreType() + { + return "Memory"; + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java index cf08ee00ff..0acaf164d9 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java @@ -67,4 +67,6 @@ public interface MessageStore extends DurableConfigurationStore void addEventListener(EventListener eventListener, Event... events); String getStoreLocation(); + + String getStoreType(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java index 34c7d2d933..be08e309e6 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java @@ -28,7 +28,7 @@ import org.apache.qpid.server.federation.Bridge; import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.queue.AMQQueue; -public class NullMessageStore implements MessageStore +public abstract class NullMessageStore implements MessageStore { @Override public void configureConfigStore(String name, diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java index c065eb263b..ab374b4917 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java @@ -232,6 +232,8 @@ public class DerbyMessageStore implements MessageStore private static final String DERBY_SINGLE_DB_SHUTDOWN_CODE = "08006"; + private static final String DERBY_STORE_TYPE = "DERBY"; + private final StateManager _stateManager; private final EventManager _eventManager = new EventManager(); @@ -2651,4 +2653,11 @@ public class DerbyMessageStore implements MessageStore { return _persistentSizeHighThreshold; } + + @Override + public String getStoreType() + { + return DERBY_STORE_TYPE; + } + }
\ No newline at end of file diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java index 6b2dff7165..efedad1181 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java @@ -20,10 +20,10 @@ */ package org.apache.qpid.server.subscription; +import org.apache.qpid.server.queue.QueueEntryVisitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; import java.util.Iterator; @@ -102,7 +102,7 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana return visitor.getEntry(); } - private class EntryFinder implements AMQQueue.Visitor + private class EntryFinder implements QueueEntryVisitor { private QueueEntry _entry; private Subscription _sub; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java index 62e94f6f2e..f38e23b342 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java @@ -20,12 +20,12 @@ */ package org.apache.qpid.server.subscription; +import org.apache.qpid.server.queue.QueueEntryVisitor; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; import java.util.HashMap; @@ -176,7 +176,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager return visitor.getEntry(); } - private class EntryFinder implements AMQQueue.Visitor + private class EntryFinder implements QueueEntryVisitor { private QueueEntry _entry; private Subscription _sub; diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java index cf2754862d..8f3822be6c 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java @@ -45,7 +45,7 @@ class ExplicitAcceptDispositionChangeListener implements ServerSession.MessageDi final Subscription_0_10 subscription = getSubscription(); if(subscription != null && _entry.isAcquiredBy(_sub)) { - subscription.getSession().acknowledge(subscription, _entry); + subscription.getSessionModel().acknowledge(subscription, _entry); } else { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java index 1e37675c98..826082cc65 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java @@ -72,6 +72,10 @@ class ImplicitAcceptDispositionChangeListener implements ServerSession.MessageDi public boolean acquire() { boolean acquired = _entry.acquire(getSubscription()); + if(acquired) + { + getSubscription().recordUnacknowledged(_entry); + } return acquired; } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java index 66825caa24..8911754a66 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java @@ -23,6 +23,7 @@ package org.apache.qpid.server.subscription; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; @@ -32,6 +33,14 @@ public interface Subscription boolean isTransient(); + long getBytesOut(); + + long getMessagesOut(); + + long getUnacknowledgedBytes(); + + long getUnacknowledgedMessages(); + public static enum State { ACTIVE, @@ -45,6 +54,7 @@ public interface Subscription } AMQQueue getQueue(); + AMQSessionModel getSessionModel(); QueueEntry.SubscriptionAcquiredState getOwningState(); QueueEntry.SubscriptionAssignedState getAssignedState(); @@ -108,4 +118,6 @@ public interface Subscription boolean isSessionTransactional(); void queueEmpty() throws AMQException; + + String getConsumerName(); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java index 1f25c215cc..baf5d09c95 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java @@ -44,6 +44,7 @@ import org.apache.qpid.server.logging.subjects.SubscriptionLogSubject; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.output.ProtocolOutputConverter; import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.QueueEntry; @@ -92,8 +93,13 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private LogActor _logActor; private UUID _id; private final AtomicLong _deliveredCount = new AtomicLong(0); - private long _createTime = System.currentTimeMillis(); + private final AtomicLong _deliveredBytes = new AtomicLong(0); + + private final AtomicLong _unacknowledgedCount = new AtomicLong(0); + private final AtomicLong _unacknowledgedBytes = new AtomicLong(0); + private long _createTime = System.currentTimeMillis(); + static final class BrowserSubscription extends SubscriptionImpl { @@ -276,22 +282,13 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage public void send(QueueEntry entry, boolean batch) throws AMQException { - // if we do not need to wait for client acknowledgements - // we can decrement the reference count immediately. - - // By doing this _before_ the send we ensure that it - // doesn't get sent if it can't be dequeued, preventing - // duplicate delivery on recovery. - - // The send may of course still fail, in which case, as - // the message is unacked, it will be lost. - + synchronized (getChannel()) { getChannel().getProtocolSession().setDeferFlush(batch); long deliveryTag = getChannel().getNextDeliveryTag(); - + addUnacknowledgedMessage(entry); recordMessageDelivery(entry, deliveryTag); sendToClient(entry, deliveryTag); @@ -371,6 +368,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage } + public AMQSessionModel getSessionModel() + { + return _channel; + } + public ConfigStore getConfigStore() { return getQueue().getConfigStore(); @@ -599,6 +601,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return _consumerTag; } + public String getConsumerName() + { + return _consumerTag == null ? null : _consumerTag.asString(); + } + public long getSubscriptionID() { return _subscriptionID; @@ -687,6 +694,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage { _deliveryMethod.deliverToClient(this,entry,deliveryTag); _deliveredCount.incrementAndGet(); + _deliveredBytes.addAndGet(entry.getSize()); } @@ -832,4 +840,44 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage _channel.getProtocolSession().flushBatched(); } + + public long getBytesOut() + { + return _deliveredBytes.longValue(); + } + + public long getMessagesOut() + { + return _deliveredCount.longValue(); + } + + + protected void addUnacknowledgedMessage(QueueEntry entry) + { + final long size = entry.getSize(); + _unacknowledgedBytes.addAndGet(size); + _unacknowledgedCount.incrementAndGet(); + entry.addStateChangeListener(new QueueEntry.StateChangeListener() + { + public void stateChanged(QueueEntry entry, QueueEntry.State oldState, QueueEntry.State newState) + { + if(oldState.equals(QueueEntry.State.ACQUIRED) && !newState.equals(QueueEntry.State.ACQUIRED)) + { + _unacknowledgedBytes.addAndGet(-size); + _unacknowledgedCount.decrementAndGet(); + entry.removeStateChangeListener(this); + } + } + }); + } + + public long getUnacknowledgedBytes() + { + return _unacknowledgedBytes.longValue(); + } + + public long getUnacknowledgedMessages() + { + return _unacknowledgedCount.longValue(); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java index 76d975a789..db378f2bf3 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java @@ -130,6 +130,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private String _trace; private final long _createTime = System.currentTimeMillis(); private final AtomicLong _deliveredCount = new AtomicLong(0); + private final AtomicLong _deliveredBytes = new AtomicLong(0); + private final AtomicLong _unacknowledgedCount = new AtomicLong(0); + private final AtomicLong _unacknowledgedBytes = new AtomicLong(0); + private final Map<String, Object> _arguments; private int _deferredMessageCredit; private long _deferredSizeCredit; @@ -185,7 +189,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } _queue = queue; - Map<String, Object> arguments = queue.getArguments() == null ? Collections.EMPTY_MAP : queue.getArguments(); + Map<String, Object> arguments = queue.getArguments(); _traceExclude = (String) arguments.get("qpid.trace.exclude"); _trace = (String) arguments.get("qpid.trace.id"); _id = getConfigStore().createId(); @@ -199,9 +203,13 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr CurrentActor.get().message(this, SubscriptionMessages.CREATE(filterLogString, queue.isDurable() && exclusive, filterLogString.length() > 0)); } - } + public String getConsumerName() + { + return _destination; + } + public boolean isSuspended() { return !isActive() || _deleted.get() || _session.isClosing(); // TODO check for Session suspension @@ -620,10 +628,15 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr _session.sendMessage(xfr, _postIdSettingAction); entry.incrementDeliveryCount(); _deliveredCount.incrementAndGet(); + _deliveredBytes.addAndGet(entry.getSize()); if(_acceptMode == MessageAcceptMode.NONE && _acquireMode == MessageAcquireMode.PRE_ACQUIRED) { forceDequeue(entry, false); } + else if(_acquireMode == MessageAcquireMode.PRE_ACQUIRED) + { + recordUnacknowledged(entry); + } } else { @@ -632,6 +645,12 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr } } + void recordUnacknowledged(QueueEntry entry) + { + _unacknowledgedCount.incrementAndGet(); + _unacknowledgedBytes.addAndGet(entry.getSize()); + } + private void deferredAddCredit(final int deferredMessageCredit, final long deferredSizeCredit) { _deferredMessageCredit += deferredMessageCredit; @@ -653,7 +672,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private void forceDequeue(final QueueEntry entry, final boolean restoreCredit) { - AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); + AutoCommitTransaction dequeueTxn = new AutoCommitTransaction(getQueue().getVirtualHost().getMessageStore()); dequeueTxn.dequeue(entry.getQueue(), entry.getMessage(), new ServerTransaction.Action() { @@ -690,7 +709,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr entry.setRedelivered(); } - if (getSession().isClosing() || !setRedelivered) + if (getSessionModel().isClosing() || !setRedelivered) { entry.decrementDeliveryCount(); } @@ -918,6 +937,8 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr // TODO Fix Store Context / cleanup if(entry.isAcquiredBy(this)) { + _unacknowledgedBytes.addAndGet(-entry.getSize()); + _unacknowledgedCount.decrementAndGet(); entry.discard(); } } @@ -944,7 +965,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return false; } - ServerSession getSession() + public ServerSession getSessionModel() { return _session; } @@ -952,7 +973,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr public SessionConfig getSessionConfig() { - return getSession(); + return getSessionModel(); } public boolean isBrowsing() @@ -1073,4 +1094,24 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr { _session.getConnection().flush(); } + + public long getBytesOut() + { + return _deliveredBytes.longValue(); + } + + public long getMessagesOut() + { + return _deliveredCount.longValue(); + } + + public long getUnacknowledgedBytes() + { + return _unacknowledgedBytes.longValue(); + } + + public long getUnacknowledgedMessages() + { + return _unacknowledgedCount.longValue(); + } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java index 637ea7dffc..7c4188bfcd 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java @@ -20,25 +20,62 @@ */ package org.apache.qpid.server.transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; import org.apache.qpid.transport.network.NetworkTransport; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + public class QpidAcceptor { - private NetworkTransport _transport; - private String _protocol; - public QpidAcceptor(NetworkTransport transport, String protocol) + public enum Transport { - _transport = transport; - _protocol = protocol; + TCP("TCP"), + SSL("TCP/SSL"); + + private final String _asString; + + Transport(String asString) + { + _asString = asString; + } + + public String toString() + { + return _asString; + } + } + + private NetworkTransport _networkTransport; + private Transport _transport; + private Set<AmqpProtocolVersion> _supported; + + + public QpidAcceptor(NetworkTransport transport, Transport protocol, Set<AmqpProtocolVersion> supported) + { + _networkTransport = transport; + _transport = protocol; + _supported = Collections.unmodifiableSet(new HashSet<AmqpProtocolVersion>(supported)); } public NetworkTransport getNetworkTransport() { + return _networkTransport; + } + + public Transport getTransport() + { return _transport; } + public Set<AmqpProtocolVersion> getSupported() + { + return _supported; + } + public String toString() { - return _protocol; + return _transport.toString(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java index c9482b9712..2d0e61ec2e 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java @@ -37,8 +37,6 @@ import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.messages.ConnectionMessages; -import org.apache.qpid.server.management.Managable; -import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.security.AuthorizationHolder; @@ -56,7 +54,7 @@ import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTIO import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT; import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT; -public class ServerConnection extends Connection implements Managable, AMQConnectionModel, LogSubject, AuthorizationHolder +public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder { private ConnectionConfig _config; private Runnable _onOpenTask; @@ -65,11 +63,9 @@ public class ServerConnection extends Connection implements Managable, AMQConnec private Subject _authorizedSubject = null; private Principal _authorizedPrincipal = null; - private boolean _statisticsEnabled = false; private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; private final long _connectionId; private final Object _reference = new Object(); - private ServerConnectionMBean _mBean; private VirtualHost _virtualHost; private AtomicLong _lastIoTime = new AtomicLong(); private boolean _blocking; @@ -118,7 +114,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec { _virtualHost.getConnectionRegistry().deregisterConnection(this); } - unregisterConnectionMbean(); } if (state == State.CLOSED) @@ -156,8 +151,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec _virtualHost = virtualHost; initialiseStatistics(); - - registerConnectionMbean(); } public void setConnectionConfig(final ConnectionConfig config) @@ -273,7 +266,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec public void close(AMQConstant cause, String message) throws AMQException { closeSubscriptions(); - unregisterConnectionMbean(); ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL; try { @@ -338,21 +330,15 @@ public class ServerConnection extends Connection implements Managable, AMQConnec public void registerMessageDelivered(long messageSize) { - if (isStatisticsEnabled()) - { - _messagesDelivered.registerEvent(1L); - _dataDelivered.registerEvent(messageSize); - } + _messagesDelivered.registerEvent(1L); + _dataDelivered.registerEvent(messageSize); _virtualHost.registerMessageDelivered(messageSize); } public void registerMessageReceived(long messageSize, long timestamp) { - if (isStatisticsEnabled()) - { - _messagesReceived.registerEvent(1L, timestamp); - _dataReceived.registerEvent(messageSize, timestamp); - } + _messagesReceived.registerEvent(1L, timestamp); + _dataReceived.registerEvent(messageSize, timestamp); _virtualHost.registerMessageReceived(messageSize, timestamp); } @@ -386,25 +372,12 @@ public class ServerConnection extends Connection implements Managable, AMQConnec public void initialiseStatistics() { - setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS && - _virtualHost.getApplicationRegistry().getConfiguration().isStatisticsGenerationConnectionsEnabled()); - _messagesDelivered = new StatisticsCounter("messages-delivered-" + getConnectionId()); _dataDelivered = new StatisticsCounter("data-delivered-" + getConnectionId()); _messagesReceived = new StatisticsCounter("messages-received-" + getConnectionId()); _dataReceived = new StatisticsCounter("data-received-" + getConnectionId()); } - public boolean isStatisticsEnabled() - { - return _statisticsEnabled; - } - - public void setStatisticsEnabled(boolean enabled) - { - _statisticsEnabled = enabled; - } - /** * @return authorizedSubject */ @@ -448,6 +421,11 @@ public class ServerConnection extends Connection implements Managable, AMQConnec return !super.hasSessionWithName(name); } + public String getRemoteAddressString() + { + return getConfig().getAddress(); + } + public String getUserName() { return _authorizedPrincipal.getName(); @@ -476,12 +454,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec } } - - public ManagedObject getManagedObject() - { - return _mBean; - } - @Override public void send(ProtocolEvent event) { @@ -489,54 +461,29 @@ public class ServerConnection extends Connection implements Managable, AMQConnec super.send(event); } - public AtomicLong getLastIoTime() + public long getLastIoTime() { - return _lastIoTime; + return _lastIoTime.longValue(); } - void checkForNotification() - { - int channelsCount = getSessionModels().size(); - if (_mBean != null && channelsCount >= getConnectionDelegate().getChannelMax()) - { - _mBean.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value"); - } - } - - private void registerConnectionMbean() + public String getClientId() { - try - { - _mBean = new ServerConnectionMBean(this); - _mBean.register(); - } - catch (JMException jme) - { - log.error("Unable to register mBean for ServerConnection", jme); - } + return getConnectionDelegate().getClientId(); } - private void unregisterConnectionMbean() + public String getClientVersion() { - if (_mBean != null) - { - if (log.isDebugEnabled()) - { - log.debug("Unregistering mBean for ServerConnection" + _mBean); - } - _mBean.unregister(); - _mBean = null; - } + return getConnectionDelegate().getClientVersion(); } - public String getClientId() + public String getPrincipalAsString() { - return getConnectionDelegate().getClientId(); + return getAuthorizedPrincipal().getName(); } - public String getClientVersion() + public long getSessionCountLimit() { - return getConnectionDelegate().getClientVersion(); + return getChannelMax(); } public Principal getPeerPrincipal() diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java index ad59c56878..c13f63b44d 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java @@ -61,7 +61,7 @@ public class ServerConnectionDelegate extends ServerDelegate public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN, AuthenticationManager authManager) { - this(createConnectionProperties(appRegistry.getBroker()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN, authManager); + this(createConnectionProperties(appRegistry.getBrokerConfig()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN, authManager); } private ServerConnectionDelegate(Map<String, Object> properties, @@ -226,7 +226,7 @@ public class ServerConnectionDelegate extends ServerDelegate } @Override - protected int getChannelMax() + public int getChannelMax() { return _maxNoOfChannels; } @@ -266,9 +266,6 @@ public class ServerConnectionDelegate extends ServerDelegate if(isSessionNameUnique(atc.getName(), conn)) { super.sessionAttach(conn, atc); - final ServerConnection serverConnection = (ServerConnection) conn; - - serverConnection.checkForNotification(); } else { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java deleted file mode 100644 index bb545164fb..0000000000 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.qpid.server.transport; - -import org.apache.qpid.management.common.mbeans.annotations.MBeanConstructor; -import org.apache.qpid.management.common.mbeans.annotations.MBeanDescription; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.ManagementActor; -import org.apache.qpid.server.management.AbstractAMQManagedConnectionObject; -import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.protocol.AMQSessionModel; - -import javax.management.JMException; -import javax.management.NotCompliantMBeanException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import java.io.IOException; -import java.util.Date; -import java.util.List; - -/** - * This MBean class implements the management interface. In order to make more attributes, operations and notifications - * available over JMX simply augment the ManagedConnection interface and add the appropriate implementation here. - */ -@MBeanDescription("Management Bean for an AMQ Broker 0-10 Connection") -public class ServerConnectionMBean extends AbstractAMQManagedConnectionObject -{ - private final ServerConnection _serverConnection; - - @MBeanConstructor("Creates an MBean exposing an AMQ Broker 0-10 Connection") - protected ServerConnectionMBean(final ServerConnection serverConnection) throws NotCompliantMBeanException - { - super(serverConnection.getConfig().getAddress()); - _serverConnection = serverConnection; - } - - @Override - public ManagedObject getParentObject() - { - return _serverConnection.getVirtualHost().getManagedObject(); - } - - @Override - public String getClientId() - { - return _serverConnection.getClientId(); - } - - @Override - public String getAuthorizedId() - { - return _serverConnection.getAuthorizedPrincipal().getName(); - } - - @Override - public String getVersion() - { - return String.valueOf(_serverConnection.getClientVersion()); - } - - @Override - public String getRemoteAddress() - { - return _serverConnection.getConfig().getAddress(); - } - - @Override - public Date getLastIoTime() - { - return new Date(_serverConnection.getLastIoTime().longValue()); - } - - @Override - public Long getMaximumNumberOfChannels() - { - return (long) _serverConnection.getConnectionDelegate().getChannelMax(); - } - - @Override - public TabularData channels() throws IOException, JMException - { - final TabularDataSupport channelsList = new TabularDataSupport(_channelsType); - final List<AMQSessionModel> list = _serverConnection.getSessionModels(); - - for (final AMQSessionModel channel : list) - { - final ServerSession session = (ServerSession)channel; - Object[] itemValues = - { - session.getChannel(), - session.isTransactional(), - null, - session.getUnacknowledgedMessageCount(), - session.getBlocking() - }; - - final CompositeData channelData = new CompositeDataSupport(_channelType, - COMPOSITE_ITEM_NAMES_DESC.toArray(new String[COMPOSITE_ITEM_NAMES_DESC.size()]), itemValues); - channelsList.put(channelData); - } - return channelsList; - } - - @Override - public void commitTransactions(int channelId) throws JMException - { - final ServerSession session = (ServerSession)_serverConnection.getSession(channelId); - if (session == null) - { - throw new JMException("The channel (channel Id = " + channelId + ") does not exist"); - } - else if (session.isTransactional()) - { - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - session.commit(); - } - finally - { - CurrentActor.remove(); - } - } - } - - @Override - public void rollbackTransactions(int channelId) throws JMException - { - final ServerSession session = (ServerSession)_serverConnection.getSession(channelId); - if (session == null) - { - throw new JMException("The channel (channel Id = " + channelId + ") does not exist"); - } - else if (session.isTransactional()) - { - CurrentActor.set(new ManagementActor(getLogActor().getRootMessageLogger())); - try - { - session.rollback(); - } - finally - { - CurrentActor.remove(); - } - } - } - - @Override - public void closeConnection() throws Exception - { - _serverConnection.mgmtClose(); - } - - @Override - public void resetStatistics() throws Exception - { - _serverConnection.resetStatistics(); - } - - @Override - public double getPeakMessageDeliveryRate() - { - return _serverConnection.getMessageDeliveryStatistics().getPeak(); - } - - @Override - public double getPeakDataDeliveryRate() - { - return _serverConnection.getDataDeliveryStatistics().getPeak(); - } - - @Override - public double getMessageDeliveryRate() - { - return _serverConnection.getMessageDeliveryStatistics().getRate(); - } - - @Override - public double getDataDeliveryRate() - { - return _serverConnection.getDataDeliveryStatistics().getRate(); - } - - @Override - public long getTotalMessagesDelivered() - { - return _serverConnection.getMessageDeliveryStatistics().getTotal(); - } - - @Override - public long getTotalDataDelivered() - { - return _serverConnection.getDataDeliveryStatistics().getTotal(); - } - - @Override - public double getPeakMessageReceiptRate() - { - return _serverConnection.getMessageReceiptStatistics().getPeak(); - } - - @Override - public double getPeakDataReceiptRate() - { - return _serverConnection.getDataReceiptStatistics().getPeak(); - } - - @Override - public double getMessageReceiptRate() - { - return _serverConnection.getMessageReceiptStatistics().getRate(); - } - - @Override - public double getDataReceiptRate() - { - return _serverConnection.getDataReceiptStatistics().getRate(); - } - - @Override - public long getTotalMessagesReceived() - { - return _serverConnection.getMessageReceiptStatistics().getTotal(); - } - - @Override - public long getTotalDataReceived() - { - return _serverConnection.getDataReceiptStatistics().getTotal(); - } - - @Override - public boolean isStatisticsEnabled() - { - return _serverConnection.isStatisticsEnabled(); - } - - @Override - public void setStatisticsEnabled(boolean enabled) - { - _serverConnection.setStatisticsEnabled(enabled); - } -} diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java index 0cb60fafd3..9914485638 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java @@ -630,11 +630,21 @@ public class ServerSession extends Session return _txnRejects.get(); } + public int getChannelId() + { + return getChannel(); + } + public Long getTxnCount() { return _txnCount.get(); } + public Long getTxnStart() + { + return _txnStarts.get(); + } + public Principal getAuthorizedPrincipal() { return getConnection().getAuthorizedPrincipal(); @@ -1059,5 +1069,4 @@ public class ServerSession extends Session { return getId().compareTo(session.getId()); } - } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java index 85ea97c107..3dbc835c45 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java @@ -1226,11 +1226,7 @@ public class ServerSessionDelegate extends SessionDelegate try { queue = createQueue(queueName, method, virtualHost, (ServerSession)session); - if(method.getExclusive()) - { - queue.setExclusive(true); - } - else if(method.getAutoDelete()) + if(!method.getExclusive() && method.getAutoDelete()) { queue.setDeleteOnNoConsumers(true); } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index c59016173a..dcc5acb820 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java @@ -32,7 +32,6 @@ import org.apache.qpid.server.connection.IConnectionRegistry; import org.apache.qpid.server.exchange.ExchangeFactory; import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.federation.BrokerLink; -import org.apache.qpid.server.management.ManagedObject; import org.apache.qpid.server.protocol.v1_0.LinkRegistry; import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; @@ -62,8 +61,6 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo void close(); - ManagedObject getManagedObject(); - UUID getBrokerId(); void scheduleHouseKeepingTask(long period, HouseKeepingTask task); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java index e956806823..acd6101ff8 100755 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -100,7 +100,7 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa return this; } - public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments) + public void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId) { try { @@ -111,6 +111,17 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa q = AMQQueueFactory.createAMQQueueImpl(id, queueName, true, owner, false, exclusive, _virtualHost, FieldTable.convertToMap(arguments)); _virtualHost.getQueueRegistry().registerQueue(q); + + if (alternateExchangeId != null) + { + Exchange altExchange = _virtualHost.getExchangeRegistry().getExchange(alternateExchangeId); + if (altExchange == null) + { + _logger.error("Unknown exchange id " + alternateExchangeId + ", cannot set alternate exchange on queue with id " + id); + return; + } + q.setAlternateExchange(altExchange); + } } CurrentActor.get().message(_logSubject, TransactionLogMessages.RECOVERY_START(queueName, true)); diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java index 5a56fe1765..8945431e99 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java @@ -20,12 +20,20 @@ */ package org.apache.qpid.server.virtualhost; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.AMQBrokerManagerMBean; import org.apache.qpid.server.binding.BindingFactory; import org.apache.qpid.server.configuration.BrokerConfig; import org.apache.qpid.server.configuration.ConfigStore; @@ -45,11 +53,9 @@ import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.VirtualHostMessages; import org.apache.qpid.server.logging.subjects.MessageStoreLogSubject; -import org.apache.qpid.server.management.AMQManagedObject; -import org.apache.qpid.server.management.ManagedObject; -import org.apache.qpid.server.protocol.v1_0.LinkRegistry; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; +import org.apache.qpid.server.protocol.v1_0.LinkRegistry; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.DefaultQueueRegistry; @@ -66,20 +72,6 @@ import org.apache.qpid.server.txn.DtxRegistry; import org.apache.qpid.server.virtualhost.plugins.VirtualHostPlugin; import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory; -import javax.management.JMException; -import javax.management.NotCompliantMBeanException; -import javax.management.ObjectName; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; - - public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.RegistryChangeListener, EventListener { private static final Logger _logger = Logger.getLogger(VirtualHostImpl.class); @@ -104,10 +96,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr private final VirtualHostConfiguration _vhostConfig; - private final VirtualHostMBean _virtualHostMBean; - - private final AMQBrokerManagerMBean _brokerMBean; - private final QueueRegistry _queueRegistry; private final ExchangeRegistry _exchangeRegistry; @@ -124,8 +112,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr private volatile State _state = State.INITIALISING; - private boolean _statisticsEnabled = false; - private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; private final Map<String, LinkRegistry> _linkRegistry = new HashMap<String, LinkRegistry>(); @@ -144,7 +130,7 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr } _appRegistry = appRegistry; - _brokerConfig = _appRegistry.getBroker(); + _brokerConfig = _appRegistry.getBrokerConfig(); _vhostConfig = hostConfig; _name = _vhostConfig.getName(); _dtxRegistry = new DtxRegistry(); @@ -153,7 +139,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr CurrentActor.get().message(VirtualHostMessages.CREATED(_name)); - _virtualHostMBean = new VirtualHostMBean(); _securityManager = new SecurityManager(_appRegistry.getSecurityManager()); _securityManager.configureHostPlugins(_vhostConfig); @@ -171,8 +156,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr _bindingFactory = new BindingFactory(this); - _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean); - _messageStore = initialiseMessageStore(hostConfig.getMessageStoreClass()); configureMessageStore(hostConfig); @@ -541,16 +524,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr CurrentActor.get().message(VirtualHostMessages.CLOSED()); } - public ManagedObject getBrokerMBean() - { - return _brokerMBean; - } - - public ManagedObject getManagedObject() - { - return _virtualHostMBean; - } - public UUID getBrokerId() { return _appRegistry.getBrokerId(); @@ -568,21 +541,15 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr public void registerMessageDelivered(long messageSize) { - if (isStatisticsEnabled()) - { - _messagesDelivered.registerEvent(1L); - _dataDelivered.registerEvent(messageSize); - } + _messagesDelivered.registerEvent(1L); + _dataDelivered.registerEvent(messageSize); _appRegistry.registerMessageDelivered(messageSize); } public void registerMessageReceived(long messageSize, long timestamp) { - if (isStatisticsEnabled()) - { - _messagesReceived.registerEvent(1L, timestamp); - _dataReceived.registerEvent(messageSize, timestamp); - } + _messagesReceived.registerEvent(1L, timestamp); + _dataReceived.registerEvent(messageSize, timestamp); _appRegistry.registerMessageReceived(messageSize, timestamp); } @@ -621,25 +588,12 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr public void initialiseStatistics() { - setStatisticsEnabled(!StatisticsCounter.DISABLE_STATISTICS && - _appRegistry.getConfiguration().isStatisticsGenerationVirtualhostsEnabled()); - _messagesDelivered = new StatisticsCounter("messages-delivered-" + getName()); _dataDelivered = new StatisticsCounter("bytes-delivered-" + getName()); _messagesReceived = new StatisticsCounter("messages-received-" + getName()); _dataReceived = new StatisticsCounter("bytes-received-" + getName()); } - public boolean isStatisticsEnabled() - { - return _statisticsEnabled; - } - - public void setStatisticsEnabled(boolean enabled) - { - _statisticsEnabled = enabled; - } - public BrokerLink createBrokerConnection(UUID id, long createTime, Map<String,String> arguments) { BrokerLink blink = new BrokerLink(this, id, createTime, arguments); @@ -772,36 +726,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr } } - - /** - * Virtual host JMX MBean class. - * - * This has some of the methods implemented from management interface for exchanges. Any - * Implementation of an Exchange MBean should extend this class. - */ - public class VirtualHostMBean extends AMQManagedObject implements ManagedVirtualHost - { - public VirtualHostMBean() throws NotCompliantMBeanException - { - super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE); - } - - public String getObjectInstanceName() - { - return ObjectName.quote(_name); - } - - public String getName() - { - return _name; - } - - public VirtualHostImpl getVirtualHost() - { - return VirtualHostImpl.this; - } - } - private final class BeforeActivationListener implements EventListener { @Override @@ -825,17 +749,19 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr public void event(Event event) { State finalState = State.ERRORED; + try { initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod()); - try - { - _brokerMBean.register(); - } - catch (JMException e) - { - throw new RuntimeException("Failed to register virtual host mbean for virtual host " + getName(), e); - } +//TODO: implement state changing for the VirtualHost MBean instead of registering and unregistering +// try +// { +// _brokerMBean.register(); +// } +// catch (JMException e) +// { +// throw new RuntimeException("Failed to register virtual host mbean for virtual host " + getName(), e); +// } finalState = State.ACTIVE; } finally @@ -861,7 +787,8 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr */ _connectionRegistry.close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT); - _brokerMBean.unregister(); +//TODO: implement state changing for the VirtualHost MBean instead of registering and unregistering +// _brokerMBean.unregister(); removeHouseKeepingTasks(); _queueRegistry.stopAllAndUnregisterMBeans(); @@ -884,7 +811,6 @@ public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.Registr @Override public void event(Event event) { - _brokerMBean.unregister(); shutdownHouseKeeping(); } } diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java index ef621a166a..1be472844a 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java @@ -22,10 +22,12 @@ package org.apache.qpid.server.virtualhost; import org.apache.qpid.common.Closeable;
import org.apache.qpid.server.configuration.ConfigStore;
+import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.registry.ApplicationRegistry;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -37,6 +39,8 @@ public class VirtualHostRegistry implements Closeable private String _defaultVirtualHostName;
private ApplicationRegistry _applicationRegistry;
+ private final Collection<RegistryChangeListener> _listeners = + Collections.synchronizedCollection(new ArrayList<RegistryChangeListener>()); public VirtualHostRegistry(ApplicationRegistry applicationRegistry)
{
@@ -50,11 +54,25 @@ public class VirtualHostRegistry implements Closeable throw new Exception("Virtual Host with name " + host.getName() + " already registered.");
}
_registry.put(host.getName(),host);
+ synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.virtualHostRegistered(host); + } + } }
public synchronized void unregisterVirtualHost(VirtualHost host)
{
_registry.remove(host.getName());
+ synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.virtualHostUnregistered(host); + } + } }
public VirtualHost getVirtualHost(String name)
@@ -106,4 +124,17 @@ public class VirtualHostRegistry implements Closeable }
}
+ + public static interface RegistryChangeListener + { + void virtualHostRegistered(VirtualHost virtualHost); + void virtualHostUnregistered(VirtualHost virtualHost); + + } + + public void addRegistryChangeListener(RegistryChangeListener listener) + { + _listeners.add(listener); + } + }
|
