diff options
author | Kim van der Riet <kpvdr@apache.org> | 2012-08-03 12:13:32 +0000 |
---|---|---|
committer | Kim van der Riet <kpvdr@apache.org> | 2012-08-03 12:13:32 +0000 |
commit | d43d1912b376322e27fdcda551a73f9ff5487972 (patch) | |
tree | ce493e10baa95f44be8beb5778ce51783463196d /java/broker/src | |
parent | 04877fec0c6346edec67072d7f2d247740cf2af5 (diff) | |
download | qpid-python-d43d1912b376322e27fdcda551a73f9ff5487972.tar.gz |
QPID-3858: Updated branch - merged from trunk r.1368650
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1368910 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/broker/src')
267 files changed, 15524 insertions, 10804 deletions
diff --git a/java/broker/src/main/java/broker.bnd b/java/broker/src/main/java/broker.bnd index fa433848a6..4e799a1609 100755 --- a/java/broker/src/main/java/broker.bnd +++ b/java/broker/src/main/java/broker.bnd @@ -17,7 +17,7 @@ # under the License. # -ver: 0.17.0 +ver: 0.19.0 Bundle-SymbolicName: qpid-broker Bundle-Version: ${ver} diff --git a/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java b/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java deleted file mode 100644 index dca62f34b4..0000000000 --- a/java/broker/src/main/java/org/apache/log4j/xml/QpidLog4JConfigurator.java +++ /dev/null @@ -1,320 +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.log4j.xml; - -import org.apache.log4j.Level; -import org.apache.log4j.Logger; -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; -import java.io.File; -import java.io.IOException; -import java.util.Map; -import java.util.concurrent.locks.ReentrantLock; - -/** - * Substitute for the Log4J XMLWatchdog (as used by DOMConfigurator.configureAndWatch) - * - * Extends the default behaviour with a strict parser check on the XML file before allowing the reconfiguration to proceed, - * ensuring that any parser error or warning prevents initiation of a configuration update by Log4J, which aborts mid-update - * upon fatal errors from the parser and proceeds in the event of 'regular' parser errors and warnings, in all cases allowing - * startup to proceed with whatever half-baked configuration then exists. - */ -public class QpidLog4JConfigurator -{ - //lock to protect access to the configuration file - //shared with LoggingManagementMBean - public static final ReentrantLock LOCK = new ReentrantLock(); - private static Logger _logger; - private static DOMConfigurator domConfig = new DOMConfigurator(); - - private QpidLog4JConfigurator() - { - //no instances - } - - public static void configure(String filename) throws IOException, ParserConfigurationException, - SAXException, IllegalLoggerLevelException - { - try - { - LOCK.lock(); - - parseXMLConfigFile(filename); - checkLoggerLevels(filename); - - DOMConfigurator.configure(filename); - - if(_logger == null) - { - _logger = Logger.getLogger(QpidLog4JConfigurator.class); - } - } - finally - { - LOCK.unlock(); - } - } - - public static void configureAndWatch(String filename, long delay) throws IOException, ParserConfigurationException, - SAXException, IllegalLoggerLevelException - { - parseXMLConfigFile(filename); - checkLoggerLevels(filename); - - QpidLog4JXMLWatchdog watchdog = new QpidLog4JXMLWatchdog(filename); - watchdog.setDelay(delay); - watchdog.start(); - } - - private static void parseXMLConfigFile(String fileName) throws IOException, SAXException, - ParserConfigurationException - { - try - { - LOCK.lock(); - - //check file was specified, exists, and is readable - if(fileName == null) - { - throw new IOException("Provided log4j XML configuration filename was null"); - } - - File configFile = new File(fileName); - - if (!configFile.exists()) - { - throw new IOException("The log4j XML configuration file does not exist: " + fileName); - } - else if (!configFile.canRead()) - { - throw new IOException("The log4j XML configuration file is not readable: " + fileName); - } - - //parse it - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - DocumentBuilder docBuilder; - - ErrorHandler errHandler = new QpidLog4JSaxErrorHandler(); - - docFactory.setValidating(true); - docBuilder = docFactory.newDocumentBuilder(); - docBuilder.setErrorHandler(errHandler); - docBuilder.setEntityResolver(new Log4jEntityResolver()); - docBuilder.parse(fileName); - } - finally - { - LOCK.unlock(); - } - } - - public static class QpidLog4JSaxErrorHandler implements ErrorHandler - { - public void error(SAXParseException e) throws SAXException - { - if(_logger != null) - { - _logger.warn(constructMessage("Error parsing XML file", e)); - } - else - { - System.err.println(constructMessage("Error parsing XML file", e)); - } - } - - public void fatalError(SAXParseException e) throws SAXException - { - throw new SAXException(constructMessage("Fatal error parsing XML file", e)); - } - - public void warning(SAXParseException e) throws SAXException - { - if(_logger != null) - { - _logger.warn(constructMessage("Warning parsing XML file", e)); - } - else - { - System.err.println(constructMessage("Warning parsing XML file", e)); - } - } - - private static String constructMessage(final String msg, final SAXParseException ex) - { - return msg + ": Line " + ex.getLineNumber()+" column " +ex.getColumnNumber() + ": " + ex.getMessage(); - } - } - - private static class QpidLog4JXMLWatchdog extends XMLWatchdog - { - public QpidLog4JXMLWatchdog(String filename) - { - super(filename); - } - - public void doOnChange() - { - try - { - LOCK.lock(); - - try - { - parseXMLConfigFile(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("Parsing the log4j XML configuration file generated errors/warnings. " + - "The new configuration was not applied. Correct the issues to prompt " + - "another update attempt: " + e.getMessage()); - } - 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(); - - //a configuration has now been applied, enable logging for future attempts - if(_logger == null) - { - _logger = Logger.getLogger(QpidLog4JConfigurator.class); - } - - _logger.info("Applied log4j configuration from: " + filename); - } - finally - { - LOCK.unlock(); - } - - } - } - - 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)) - { - //the string "null" signals to inherit from a parent logger - return; - } - - Level level = Level.toLevel(levelString); - - //above Level.toLevel call returns a DEBUG Level if the request fails. Check the result. - if (level.equals(Level.DEBUG) && !(levelString.equalsIgnoreCase("debug"))) - { - //received DEBUG but we did not ask for it, the Level request failed. - throw new IllegalLoggerLevelException("Level '" + levelString + "' specified for Logger '" + loggerName + "' is invalid"); - } - } - - public static class IllegalLoggerLevelException extends Exception - { - private static final long serialVersionUID = 1L; - - public IllegalLoggerLevelException(String msg) - { - super(msg); - } - } -} - diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java index 034a4ae53c..27ab580642 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/ManagementExchange.java @@ -70,6 +70,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener private final Set<Binding> _bindingSet = new CopyOnWriteArraySet<Binding>(); private UUID _id; + private UUID _qmfId; private static final String AGENT_BANK = "0"; private int _bindingCountHigh; @@ -84,7 +85,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener private class ManagementQueue implements BaseQueue { - private final UUID QUEUE_ID = UUIDGenerator.generateUUID(); + private final UUID QUEUE_ID = UUIDGenerator.generateRandomUUID(); private final String NAME_AS_STRING = "##__mgmt_pseudo_queue__##" + QUEUE_ID.toString(); private final AMQShortString NAME_AS_SHORT_STRING = new AMQShortString(NAME_AS_STRING); @@ -196,6 +197,7 @@ public class ManagementExchange implements Exchange, QMFService.Listener _virtualHost = host; _id = id; _virtualHost.scheduleHouseKeepingTask(_virtualHost.getBroker().getManagementPublishInterval(), new UpdateTask(_virtualHost)); + _qmfId = getConfigStore().createId(); getConfigStore().addConfiguredObject(this); getQMFService().addListener(this); } @@ -205,6 +207,12 @@ public class ManagementExchange implements Exchange, QMFService.Listener return _id; } + @Override + public UUID getQMFId() + { + return _qmfId; + } + public ExchangeConfigType getConfigType() { return ExchangeConfigType.getInstance(); @@ -540,6 +548,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener return getMsgReceives(); } + public long getMsgDrops() + { + return 0l; + } + public long getByteReceives() { return _bytesReceived.get(); @@ -550,6 +563,11 @@ public class ManagementExchange implements Exchange, QMFService.Listener return getByteReceives(); } + public long getByteDrops() + { + return 0l; + } + public long getCreateTime() { return _createTime; diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java index 787cede2b7..1b173c7e11 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFMessage.java +++ b/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/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java index 631bd3c7cc..c3604dca44 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFObject.java @@ -28,7 +28,7 @@ public abstract class QMFObject<C extends QMFClass, D extends QMFObject.Delegate public interface Delegate { - UUID getId(); + UUID getQMFId(); long getCreateTime(); } @@ -49,7 +49,7 @@ public abstract class QMFObject<C extends QMFClass, D extends QMFObject.Delegate public final UUID getId() { - return _delegate.getId(); + return _delegate.getQMFId(); } public final long getCreateTime() diff --git a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java index 900b722886..d713976919 100644 --- a/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java +++ b/java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java @@ -436,7 +436,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable QMFObject qmfObject = classObjects.remove(object); if(qmfObject != null) { - _managedObjectsById.get(qmfClass).remove(object.getId()); + _managedObjectsById.get(qmfClass).remove(object.getQMFId()); objectRemoved(qmfObject); } } @@ -468,7 +468,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable } } - classObjectsById.put(object.getId(),qmfObject); + classObjectsById.put(object.getQMFId(),qmfObject); if(classObjects.putIfAbsent(object, qmfObject) == null) { @@ -570,7 +570,7 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable public UUID getSystemId() { - return _obj.getId(); + return _obj.getQMFId(); } public String getOsName() @@ -598,9 +598,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getOSArchitecture(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -964,9 +964,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1004,9 +1004,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getFederationTag(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1135,9 +1135,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getByteRoutes(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1470,9 +1470,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getArguments(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1526,9 +1526,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getMatches(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1647,9 +1647,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return factory.createResponseCommand(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1741,6 +1741,12 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return 0l; } + public Long getUnackedMessages() + { + // TODO + return 0l; + } + public Long getTxnStarts() { return _obj.getTxnStarts(); @@ -1799,9 +1805,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return factory.createResponseCommand(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1870,9 +1876,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getDelivered(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -1955,14 +1961,20 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getAckBatching(); } + /* support TBD */ + public String getName() + { + return null; + } + public BrokerSchema.BridgeClass.CloseMethodResponseCommand close(final BrokerSchema.BridgeClass.CloseMethodResponseCommandFactory factory) { return null; } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() @@ -2020,6 +2032,18 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return _obj.getLastError(); } + /* support TBD */ + public String getName() + { + return null; + } + + /* support TBD */ + public BrokerSchema.ConnectionObject getConnectionRef() + { + return (BrokerSchema.ConnectionObject) null; + } + public BrokerSchema.LinkClass.CloseMethodResponseCommand close(final BrokerSchema.LinkClass.CloseMethodResponseCommandFactory factory) { _obj.close(); @@ -2042,9 +2066,9 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable return factory.createResponseCommand(); } - public UUID getId() + public UUID getQMFId() { - return _obj.getId(); + return _obj.getQMFId(); } public long getCreateTime() diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java deleted file mode 100644 index 0f32b98aa8..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java index 8198cec821..e197dddfde 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java +++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java @@ -23,7 +23,9 @@ package org.apache.qpid.server; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -32,9 +34,9 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; import java.util.UUID; -import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.locks.Lock; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; @@ -89,7 +91,6 @@ import org.apache.qpid.server.subscription.ClientDeliveryMethod; import org.apache.qpid.server.subscription.RecordDeliveryMethod; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.subscription.SubscriptionImpl; import org.apache.qpid.server.txn.AsyncAutoCommitTransaction; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.ServerTransaction; @@ -137,11 +138,9 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm private final LinkedList<AsyncCommand> _unfinishedCommandsQueue = new LinkedList<AsyncCommand>(); - private static final int UNFINISHED_COMMAND_QUEUE_THRESHOLD = 500; - 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); @@ -157,7 +156,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm private final AMQProtocolSession _session; private AtomicBoolean _closing = new AtomicBoolean(false); - private final Set<AMQQueue> _blockingQueues = new ConcurrentSkipListSet<AMQQueue>(); + private final Set<Object> _blockingEntities = Collections.synchronizedSet(new HashSet<Object>()); private final AtomicBoolean _blocking = new AtomicBoolean(false); @@ -170,11 +169,13 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm private List<QueueEntry> _resendList = new ArrayList<QueueEntry>(); private static final AMQShortString IMMEDIATE_DELIVERY_REPLY_TEXT = new AMQShortString("Immediate delivery is not possible."); - private final UUID _id; + private final UUID _qmfId; private long _createTime = System.currentTimeMillis(); private final ClientDeliveryMethod _clientDeliveryMethod; + private final TransactionTimeoutHelper _transactionTimeoutHelper; + public AMQChannel(AMQProtocolSession session, int channelId, MessageStore messageStore) throws AMQException { @@ -183,7 +184,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm _actor = new AMQPChannelActor(this, session.getLogActor().getRootMessageLogger()); _logSubject = new ChannelLogSubject(this); - _id = getConfigStore().createId(); + _qmfId = getConfigStore().createId(); _actor.message(ChannelMessages.CREATE()); getConfigStore().addConfiguredObject(this); @@ -194,6 +195,8 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm _transaction = new AsyncAutoCommitTransaction(_messageStore, this); _clientDeliveryMethod = session.createDeliveryMethod(_channelId); + + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject); } public ConfigStore getConfigStore() @@ -264,6 +267,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm return _txnCount.get(); } + public Long getTxnStart() + { + return _txnStarts.get(); + } + public int getChannelId() { return _channelId; @@ -441,7 +449,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 * @@ -948,9 +956,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm public void commit() throws AMQException { - commit(null); + commit(null, false); } - public void commit(Runnable immediateAction) throws AMQException + + + public void commit(final Runnable immediateAction, boolean async) throws AMQException { if (!isTransactional()) @@ -958,11 +968,29 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm throw new AMQException("Fatal error: commit called on non-transactional channel"); } - _transaction.commit(immediateAction); + if(async && _transaction instanceof LocalTransaction) + { + + ((LocalTransaction)_transaction).commitAsync(new Runnable() + { + @Override + public void run() + { + immediateAction.run(); + _txnCommits.incrementAndGet(); + _txnStarts.incrementAndGet(); + decrementOutstandingTxnsIfNecessary(); + } + }); + } + else + { + _transaction.commit(immediateAction); - _txnCommits.incrementAndGet(); - _txnStarts.incrementAndGet(); - decrementOutstandingTxnsIfNecessary(); + _txnCommits.incrementAndGet(); + _txnStarts.incrementAndGet(); + decrementOutstandingTxnsIfNecessary(); + } } public void rollback() throws AMQException @@ -1357,9 +1385,34 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm return _actor; } - public void block(AMQQueue queue) + public synchronized void block() { - if(_blockingQueues.add(queue)) + if(_blockingEntities.add(this)) + { + if(_blocking.compareAndSet(false,true)) + { + _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED("** All Queues **")); + flow(false); + } + } + } + + public synchronized void unblock() + { + if(_blockingEntities.remove(this)) + { + if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false)) + { + _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); + + flow(true); + } + } + } + + public synchronized void block(AMQQueue queue) + { + if(_blockingEntities.add(queue)) { if(_blocking.compareAndSet(false,true)) @@ -1370,11 +1423,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm } } - public void unblock(AMQQueue queue) + public synchronized void unblock(AMQQueue queue) { - if(_blockingQueues.remove(queue)) + if(_blockingEntities.remove(queue)) { - if(_blocking.compareAndSet(true,false) && !isClosing()) + if(_blockingEntities.isEmpty() && _blocking.compareAndSet(true,false) && !isClosing()) { _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); @@ -1393,6 +1446,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(); @@ -1400,6 +1458,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm _session.writeFrame(responseBody.generateFrame(_channelId)); } + @Override public boolean getBlocking() { return _blocking.get(); @@ -1456,9 +1515,10 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm return false; } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public String getSessionName() @@ -1484,30 +1544,42 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm long openTime = currentTime - _transaction.getTransactionStartTime(); long idleTime = currentTime - _txnUpdateTime.get(); - // Log a warning on idle or open transactions - if (idleWarn > 0L && idleTime > idleWarn) - { - CurrentActor.get().message(_logSubject, ChannelMessages.IDLE_TXN(idleTime)); - _logger.warn("IDLE TRANSACTION ALERT " + _logSubject.toString() + " " + idleTime + " ms"); - } - else if (openWarn > 0L && openTime > openWarn) + _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, ChannelMessages.IDLE_TXN(idleTime), + TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT); + if (_transactionTimeoutHelper.isTimedOut(idleTime, idleClose)) { - CurrentActor.get().message(_logSubject, ChannelMessages.OPEN_TXN(openTime)); - _logger.warn("OPEN TRANSACTION ALERT " + _logSubject.toString() + " " + openTime + " ms"); + closeConnection("Idle transaction timed out"); + return; } - // Close connection for idle or open transactions that have timed out - if (idleClose > 0L && idleTime > idleClose) + _transactionTimeoutHelper.logIfNecessary(openTime, openWarn, ChannelMessages.OPEN_TXN(openTime), + TransactionTimeoutHelper.OPEN_TRANSACTION_ALERT); + if (_transactionTimeoutHelper.isTimedOut(openTime, openClose)) { - getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Idle transaction timed out"); - } - else if (openClose > 0L && openTime > openClose) - { - getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Open transaction timed out"); + closeConnection("Open transaction timed out"); + return; } } } + /** + * Typically called from the HouseKeepingThread instead of the main receiver thread, + * therefore uses a lock to close the connection in a thread-safe manner. + */ + private void closeConnection(String reason) throws AMQException + { + Lock receivedLock = _session.getReceivedLock(); + receivedLock.lock(); + try + { + _session.close(AMQConstant.RESOURCE_ERROR, reason); + } + finally + { + receivedLock.unlock(); + } + } + public void deadLetter(long deliveryTag) throws AMQException { final UnacknowledgedMessageMap unackedMap = getUnacknowledgedMessageMap(); @@ -1563,23 +1635,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm _unfinishedCommandsQueue.add(new AsyncCommand(future, action)); } - public void completeAsyncCommands() - { - AsyncCommand cmd; - while((cmd = _unfinishedCommandsQueue.peek()) != null && cmd.isReadyForCompletion()) - { - cmd.complete(); - _unfinishedCommandsQueue.poll(); - } - while(_unfinishedCommandsQueue.size() > UNFINISHED_COMMAND_QUEUE_THRESHOLD) - { - cmd = _unfinishedCommandsQueue.poll(); - cmd.awaitReadyForCompletion(); - cmd.complete(); - } - } - - public void sync() { AsyncCommand cmd; @@ -1588,6 +1643,10 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm cmd.awaitReadyForCompletion(); cmd.complete(); } + if(_transaction instanceof LocalTransaction) + { + ((LocalTransaction)_transaction).sync(); + } } private static class AsyncCommand @@ -1624,6 +1683,12 @@ public class AMQChannel implements SessionConfig, AMQSessionModel, AsyncAutoComm public int compareTo(AMQSessionModel session) { - return getId().compareTo(session.getId()); + return getQMFId().compareTo(session.getQMFId()); + } + + @Override + public int getConsumerCount() + { + return _tag2SubscriptionMap.size(); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/Broker.java index 5004d320c2..d58a0d5bb4 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/Broker.java +++ b/java/broker/src/main/java/org/apache/qpid/server/Broker.java @@ -20,19 +20,22 @@ */ package org.apache.qpid.server; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +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.log4j.LoggingFacade; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.protocol.AmqpProtocolVersion; import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; @@ -46,30 +49,10 @@ import org.apache.qpid.transport.network.Transport; import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; -import javax.net.ssl.SSLContext; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.util.EnumSet; -import java.util.Formatter; -import java.util.HashSet; -import java.util.List; -import java.util.Properties; -import java.util.Set; -import java.util.logging.ConsoleHandler; -import java.util.logging.FileHandler; -import java.util.logging.Handler; -import java.util.logging.Level; -import java.util.logging.LogRecord; - public class Broker { private static final Logger LOGGER = Logger.getLogger(Broker.class); - private static final int IPV4_ADDRESS_LENGTH = 4; - private static final char IPV4_LITERAL_SEPARATOR = '.'; private volatile Thread _shutdownHookThread; protected static class InitException extends RuntimeException @@ -128,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); @@ -145,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()) { @@ -165,36 +148,71 @@ public class Broker parsePortList(sslPorts, serverConfig.getSSLPorts()); } + //1-0 excludes and includes Set<Integer> exclude_1_0 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v1_0)); if(exclude_1_0.isEmpty()) { parsePortList(exclude_1_0, serverConfig.getPortExclude10()); } + Set<Integer> include_1_0 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v1_0)); + if(include_1_0.isEmpty()) + { + parsePortList(include_1_0, serverConfig.getPortInclude10()); + } + + //0-10 excludes and includes Set<Integer> exclude_0_10 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_10)); if(exclude_0_10.isEmpty()) { parsePortList(exclude_0_10, serverConfig.getPortExclude010()); } + Set<Integer> include_0_10 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_10)); + if(include_0_10.isEmpty()) + { + parsePortList(include_0_10, serverConfig.getPortInclude010()); + } + + //0-9-1 excludes and includes Set<Integer> exclude_0_9_1 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_9_1)); if(exclude_0_9_1.isEmpty()) { parsePortList(exclude_0_9_1, serverConfig.getPortExclude091()); } + Set<Integer> include_0_9_1 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_9_1)); + if(include_0_9_1.isEmpty()) + { + parsePortList(include_0_9_1, serverConfig.getPortInclude091()); + } + + //0-9 excludes and includes Set<Integer> exclude_0_9 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_9)); if(exclude_0_9.isEmpty()) { parsePortList(exclude_0_9, serverConfig.getPortExclude09()); } + Set<Integer> include_0_9 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_9)); + if(include_0_9.isEmpty()) + { + parsePortList(include_0_9, serverConfig.getPortInclude09()); + } + + //0-8 excludes and includes Set<Integer> exclude_0_8 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_8)); if(exclude_0_8.isEmpty()) { parsePortList(exclude_0_8, serverConfig.getPortExclude08()); } + Set<Integer> include_0_8 = new HashSet<Integer>(options.getIncludedPorts(ProtocolInclusion.v0_8)); + if(include_0_8.isEmpty()) + { + parsePortList(include_0_8, serverConfig.getPortInclude08()); + } + String bindAddr = options.getBind(); if (bindAddr == null) { @@ -220,8 +238,8 @@ public class Broker final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, port); final Set<AmqpProtocolVersion> supported = - getSupportedVersions(port, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9, - exclude_0_8, serverConfig); + getSupportedVersions(port, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8, + include_1_0, include_0_10, include_0_9_1, include_0_9, include_0_8,serverConfig); final NetworkTransportConfiguration settings = new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP); @@ -233,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)); } } @@ -242,16 +260,31 @@ public class Broker { final String keystorePath = serverConfig.getConnectorKeyStorePath(); final String keystorePassword = serverConfig.getConnectorKeyStorePassword(); + final String keystoreType = serverConfig.getConnectorKeyStoreType(); final String keyManagerFactoryAlgorithm = serverConfig.getConnectorKeyManagerFactoryAlgorithm(); - final SSLContext sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keyManagerFactoryAlgorithm); + final SSLContext sslContext; + if(serverConfig.getConnectorTrustStorePath()!=null) + { + sslContext = SSLContextFactory.buildClientContext(serverConfig.getConnectorTrustStorePath(), + serverConfig.getConnectorTrustStorePassword(), + serverConfig.getConnectorTrustStoreType(), + serverConfig.getConnectorTrustManagerFactoryAlgorithm(), + keystorePath, + keystorePassword, keystoreType, keyManagerFactoryAlgorithm, + serverConfig.getCertAlias()); + } + else + { + sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, keystoreType, keyManagerFactoryAlgorithm); + } for(int sslPort : sslPorts) { final InetSocketAddress inetSocketAddress = new InetSocketAddress(bindAddress, sslPort); final Set<AmqpProtocolVersion> supported = - getSupportedVersions(sslPort, exclude_1_0, exclude_0_10, exclude_0_9_1, - exclude_0_9, exclude_0_8, serverConfig); + getSupportedVersions(sslPort, exclude_1_0, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8, + include_1_0, include_0_10, include_0_9_1, include_0_9, include_0_8, serverConfig); final NetworkTransportConfiguration settings = new ServerNetworkTransportConfiguration(serverConfig, inetSocketAddress, Transport.TCP); @@ -262,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)); } } @@ -282,27 +315,36 @@ public class Broker final Set<Integer> exclude_0_9_1, final Set<Integer> exclude_0_9, final Set<Integer> exclude_0_8, + final Set<Integer> include_1_0, + final Set<Integer> include_0_10, + final Set<Integer> include_0_9_1, + final Set<Integer> include_0_9, + final Set<Integer> include_0_8, final ServerConfiguration serverConfig) { final EnumSet<AmqpProtocolVersion> supported = EnumSet.allOf(AmqpProtocolVersion.class); - if(exclude_1_0.contains(port) || !serverConfig.isAmqp10enabled()) + if((exclude_1_0.contains(port) || !serverConfig.isAmqp10enabled()) && !include_1_0.contains(port)) { supported.remove(AmqpProtocolVersion.v1_0_0); } - if(exclude_0_10.contains(port) || !serverConfig.isAmqp010enabled()) + + if((exclude_0_10.contains(port) || !serverConfig.isAmqp010enabled()) && !include_0_10.contains(port)) { supported.remove(AmqpProtocolVersion.v0_10); } - if(exclude_0_9_1.contains(port) || !serverConfig.isAmqp091enabled()) + + if((exclude_0_9_1.contains(port) || !serverConfig.isAmqp091enabled()) && !include_0_9_1.contains(port)) { supported.remove(AmqpProtocolVersion.v0_9_1); } - if(exclude_0_9.contains(port) || !serverConfig.isAmqp09enabled()) + + if((exclude_0_9.contains(port) || !serverConfig.isAmqp09enabled()) && !include_0_9.contains(port)) { supported.remove(AmqpProtocolVersion.v0_9); } - if(exclude_0_8.contains(port) || !serverConfig.isAmqp08enabled()) + + if((exclude_0_8.contains(port) || !serverConfig.isAmqp08enabled()) && !include_0_8.contains(port)) { supported.remove(AmqpProtocolVersion.v0_8); } @@ -388,7 +430,7 @@ public class Broker } } - private void configureLogging(File logConfigFile, long logWatchTime) throws InitException, IOException + private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException { if (logConfigFile.exists() && logConfigFile.canRead()) { @@ -401,7 +443,7 @@ public class Broker // log4j expects the watch interval in milliseconds try { - QpidLog4JConfigurator.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000); + LoggingFacade.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000); } catch (Exception e) { @@ -412,7 +454,7 @@ public class Broker { try { - QpidLog4JConfigurator.configure(logConfigFile.getPath()); + LoggingFacade.configure(logConfigFile.getPath()); } catch (Exception e) { @@ -446,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/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java index d871c724fd..434d40d557 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java +++ b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java @@ -33,10 +33,12 @@ 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>(); private final Map<ProtocolExclusion,Set<Integer>> _exclusionMap = new HashMap<ProtocolExclusion, Set<Integer>>(); + private final Map<ProtocolInclusion,Set<Integer>> _inclusionMap = new HashMap<ProtocolInclusion, Set<Integer>>(); private String _configFile; private String _logConfigFile; @@ -46,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) { @@ -108,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) @@ -161,4 +165,36 @@ public class BrokerOptions { _bundleContext = bundleContext; } + + public Set<Integer> getIncludedPorts(final ProtocolInclusion includeProtocol) + { + final Set<Integer> includedPorts = _inclusionMap.get(includeProtocol); + return includedPorts == null ? Collections.<Integer>emptySet() : includedPorts; + } + + public void addIncludedPort(final ProtocolInclusion includeProtocol, final int port) + { + if (!_inclusionMap.containsKey(includeProtocol)) + { + _inclusionMap.put(includeProtocol, new HashSet<Integer>()); + } + + 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/java/broker/src/main/java/org/apache/qpid/server/Main.java b/java/broker/src/main/java/org/apache/qpid/server/Main.java index 70fa414e3c..9fe7a6619f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/Main.java +++ b/java/broker/src/main/java/org/apache/qpid/server/Main.java @@ -85,6 +85,32 @@ public class Main .withDescription("when listening on the specified port do not accept AMQP0-8 connections. The specified port must be one specified on the command line") .withLongOpt("exclude-0-8").create(); + private static final Option OPTION_INCLUDE_1_0 = + OptionBuilder.withArgName("port").hasArg() + .withDescription("accept AMQP1-0 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") + .withLongOpt("include-1-0").create(); + +private static final Option OPTION_INCLUDE_0_10 = + OptionBuilder.withArgName("port").hasArg() + .withDescription("accept AMQP0-10 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") + .withLongOpt("include-0-10").create(); + +private static final Option OPTION_INCLUDE_0_9_1 = + OptionBuilder.withArgName("port").hasArg() + .withDescription("accept AMQP0-9-1 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") + .withLongOpt("include-0-9-1").create(); + +private static final Option OPTION_INCLUDE_0_9 = + OptionBuilder.withArgName("port").hasArg() + .withDescription("accept AMQP0-9 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") + .withLongOpt("include-0-9").create(); + +private static final Option OPTION_INCLUDE_0_8 = + OptionBuilder.withArgName("port").hasArg() + .withDescription("accept AMQP0-8 connections on this port, overriding configuration to the contrary. The specified port must be one specified on the command line") + .withLongOpt("include-0-8").create(); + + private static final Option OPTION_JMX_PORT_REGISTRY_SERVER = OptionBuilder.withArgName("port").hasArg() .withDescription("listen on the specified management (registry server) port. Overrides any value in the config file") @@ -127,6 +153,11 @@ public class Main OPTIONS.addOption(OPTION_EXCLUDE_0_9_1); OPTIONS.addOption(OPTION_EXCLUDE_0_9); OPTIONS.addOption(OPTION_EXCLUDE_0_8); + OPTIONS.addOption(OPTION_INCLUDE_1_0); + OPTIONS.addOption(OPTION_INCLUDE_0_10); + OPTIONS.addOption(OPTION_INCLUDE_0_9_1); + OPTIONS.addOption(OPTION_INCLUDE_0_9); + OPTIONS.addOption(OPTION_INCLUDE_0_8); OPTIONS.addOption(OPTION_BIND); OPTIONS.addOption(OPTION_JMX_PORT_REGISTRY_SERVER); @@ -256,6 +287,10 @@ public class Main { parsePortArray(options, _commandLine.getOptionValues(pe.getExcludeName()), pe); } + for(ProtocolInclusion pe : ProtocolInclusion.values()) + { + parseProtocolInclusions(options, _commandLine.getOptionValues(pe.getIncludeName()), pe); + } } String[] sslPortStr = _commandLine.getOptionValues(OPTION_SSLPORT.getOpt()); @@ -266,6 +301,10 @@ public class Main { parsePortArray(options, _commandLine.getOptionValues(pe.getExcludeName()), pe); } + for(ProtocolInclusion pe : ProtocolInclusion.values()) + { + parseProtocolInclusions(options, _commandLine.getOptionValues(pe.getIncludeName()), pe); + } } setExceptionHandler(); @@ -399,4 +438,23 @@ public class Main } } } + + private static void parseProtocolInclusions(final BrokerOptions options, final Object[] ports, + final ProtocolInclusion includedProtocol) throws InitException + { + if(ports != null) + { + for(int i = 0; i < ports.length; i++) + { + try + { + options.addIncludedPort(includedProtocol, Integer.parseInt(String.valueOf(ports[i]))); + } + catch (NumberFormatException e) + { + throw new InitException("Invalid port for inclusion: " + ports[i], e); + } + } + } + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java b/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java new file mode 100644 index 0000000000..85fbe2e02e --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/ProtocolInclusion.java @@ -0,0 +1,74 @@ +/* + * + * 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 java.util.HashMap; +import java.util.Map; + +public enum ProtocolInclusion +{ + v0_8("include-0-8","--include-0-8"), + v0_9("include-0-9", "--include-0-9"), + v0_9_1("include-0-9-1", "--include-0-9-1"), + v0_10("include-0-10", "--include-0-10"), + v1_0("include-1-0", "--include-1-0"); + + private static final Map<String, ProtocolInclusion> MAP = new HashMap<String,ProtocolInclusion>(); + + static + { + for(ProtocolInclusion pe : ProtocolInclusion.values()) + { + MAP.put(pe.getArg(), pe); + } + } + + private String _arg; + private String _includeName; + + private ProtocolInclusion(final String includeName, final String arg) + { + _includeName = includeName; + _arg = arg; + } + + public String getArg() + { + return _arg; + } + + public String getIncludeName() + { + return _includeName; + } + + public static ProtocolInclusion lookup(final String arg) + { + ProtocolInclusion ex = MAP.get(arg); + + if(ex == null) + { + throw new IllegalArgumentException(arg + " is not a valid protocol inclusion"); + } + + return ex; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java b/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java new file mode 100644 index 0000000000..0c474cca13 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/TransactionTimeoutHelper.java @@ -0,0 +1,63 @@ +/* + * 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.log4j.Logger; +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogMessage; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.messages.ChannelMessages; + +public class TransactionTimeoutHelper +{ + private static final Logger LOGGER = Logger.getLogger(TransactionTimeoutHelper.class); + + public static final String IDLE_TRANSACTION_ALERT = "IDLE TRANSACTION ALERT"; + public static final String OPEN_TRANSACTION_ALERT = "OPEN TRANSACTION ALERT"; + + private final LogSubject _logSubject; + + public TransactionTimeoutHelper(final LogSubject logSubject) + { + _logSubject = logSubject; + } + + public void logIfNecessary(final long timeSoFar, final long warnTimeout, + final LogMessage message, final String alternateLogPrefix) + { + if (isTimedOut(timeSoFar, warnTimeout)) + { + LogActor logActor = CurrentActor.get(); + if(logActor.getRootMessageLogger().isMessageEnabled(logActor, _logSubject, message.getLogHierarchy())) + { + logActor.message(_logSubject, message); + } + else + { + LOGGER.warn(alternateLogPrefix + " " + _logSubject.toLogString() + " " + timeSoFar + " ms"); + } + } + } + + public boolean isTimedOut(long timeSoFar, long timeout) + { + return timeout > 0L && timeSoFar > timeout; + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java index 2efd4cee26..9b3be624e0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/Binding.java @@ -35,11 +35,13 @@ public class Binding private final Exchange _exchange; private final Map<String, Object> _arguments; private final UUID _id; + private final UUID _qmfId; private final AtomicLong _matches = new AtomicLong(); - public Binding(UUID id, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments) + public Binding(UUID id, UUID qmfId, final String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments) { _id = id; + _qmfId = qmfId; _bindingKey = bindingKey; _queue = queue; _exchange = exchange; @@ -51,6 +53,11 @@ public class Binding return _id; } + public UUID getQMFId() + { + return _qmfId; + } + public String getBindingKey() { return _bindingKey; diff --git a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java index abf252c733..b805056311 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/binding/BindingFactory.java @@ -60,7 +60,7 @@ public class BindingFactory private BindingImpl(UUID id, String bindingKey, final AMQQueue queue, final Exchange exchange, final Map<String, Object> arguments) { - super(id, bindingKey, queue, exchange, arguments); + super(id, queue.getVirtualHost().getConfigStore().createId(), bindingKey, queue, exchange, arguments); _logSubject = new BindingLogSubject(bindingKey,exchange,queue); } @@ -166,7 +166,7 @@ public class BindingFactory if (id == null) { - id = UUIDGenerator.generateUUID(); + id = UUIDGenerator.generateBindingUUID(exchange.getName(), queue.getName(), bindingKey, _virtualHost.getName()); } BindingImpl b = new BindingImpl(id, bindingKey, queue, exchange, arguments); BindingImpl existingMapping = _bindings.putIfAbsent(b, b); diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java index aff07250f3..c519a0c0fa 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfigStore.java @@ -101,7 +101,7 @@ public class ConfigStore } - typeMap.put(object.getId(), object); + typeMap.put(object.getQMFId(), object); sendEvent(Event.CREATED, object); } @@ -111,7 +111,7 @@ public class ConfigStore ConcurrentHashMap typeMap = _typeMap.get(object.getConfigType()); if(typeMap != null) { - typeMap.remove(object.getId()); + typeMap.remove(object.getQMFId()); sendEvent(Event.DELETED, object); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java index 78666a3f93..ff4e38d9f7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ConfiguredObject.java @@ -25,7 +25,7 @@ import java.util.UUID; public interface ConfiguredObject<T extends ConfigObjectType<T,C>, C extends ConfiguredObject<T, C>> { - public UUID getId(); + public UUID getQMFId(); public T getConfigType(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java index 41c51d9684..6633d93adf 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ExchangeConfig.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java index ea4f723dda..847cae87f5 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/LinkConfigType.java @@ -76,7 +76,7 @@ public final class LinkConfigType extends ConfigObjectType<LinkConfigType, LinkC } }; - public static final LinkReadOnlyProperty<Integer> PORT_PROPERTY = new LinkReadOnlyProperty<Integer>("host") + public static final LinkReadOnlyProperty<Integer> PORT_PROPERTY = new LinkReadOnlyProperty<Integer>("port") { public Integer getValue(LinkConfig object) { @@ -134,4 +134,4 @@ public final class LinkConfigType extends ConfigObjectType<LinkConfigType, LinkC -}
\ No newline at end of file +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java index 40bafb4275..8f03383777 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/QueueConfiguration.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java index 46027d02c6..f9e2d93cff 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java @@ -20,6 +20,16 @@ package org.apache.qpid.server.configuration; +import java.io.File; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Map.Entry; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.TrustManagerFactory; import org.apache.commons.configuration.CompositeConfiguration; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; @@ -28,7 +38,6 @@ import org.apache.commons.configuration.HierarchicalConfiguration; import org.apache.commons.configuration.SystemConfiguration; import org.apache.commons.configuration.XMLConfiguration; import org.apache.log4j.Logger; - import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; import org.apache.qpid.server.exchange.DefaultExchangeFactory; import org.apache.qpid.server.protocol.AmqpProtocolVersion; @@ -40,17 +49,6 @@ import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; -import java.io.File; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Map.Entry; - -import javax.net.ssl.KeyManagerFactory; - public class ServerConfiguration extends ConfigurationPlugin { protected static final Logger _logger = Logger.getLogger(ServerConfiguration.class); @@ -66,6 +64,9 @@ 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 int DEFAULT_HTTPS_MANAGEMENT_PORT = 8443; + public static final long DEFAULT_MINIMUM_ALERT_REPEAT_GAP = 30000l; public static final String QPID_HOME = "QPID_HOME"; public static final String QPID_WORK = "QPID_WORK"; @@ -77,6 +78,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>(); @@ -86,6 +89,9 @@ public class ServerConfiguration extends ConfigurationPlugin public static final String MGMT_CUSTOM_REGISTRY_SOCKET = "management.custom-registry-socket"; public static final String MGMT_JMXPORT_REGISTRYSERVER = "management.jmxport.registryServer"; public static final String MGMT_JMXPORT_CONNECTORSERVER = "management.jmxport.connectorServer"; + public static final String SECURITY_DEFAULT_AUTH_MANAGER = "security.default-auth-manager"; + public static final String SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER = "security.port-mappings.port-mapping.auth-manager"; + public static final String SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT = "security.port-mappings.port-mapping.port"; public static final String STATUS_UPDATES = "status-updates"; public static final String ADVANCED_LOCALE = "advanced.locale"; public static final String CONNECTOR_AMQP10ENABLED = "connector.amqp10enabled"; @@ -94,6 +100,11 @@ public class ServerConfiguration extends ConfigurationPlugin public static final String CONNECTOR_AMQP09ENABLED = "connector.amqp09enabled"; public static final String CONNECTOR_AMQP08ENABLED = "connector.amqp08enabled"; public static final String CONNECTOR_AMQP_SUPPORTED_REPLY = "connector.amqpDefaultSupportedProtocolReply"; + public static final String CONNECTOR_INCLUDE_10 = "connector.include10"; + public static final String CONNECTOR_INCLUDE_010 = "connector.include010"; + public static final String CONNECTOR_INCLUDE_091 = "connector.include091"; + public static final String CONNECTOR_INCLUDE_09 = "connector.include09"; + public static final String CONNECTOR_INCLUDE_08 = "connector.include08"; { envVarMap.put("QPID_PORT", "connector.port"); @@ -104,6 +115,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"); @@ -177,7 +190,7 @@ public class ServerConfiguration extends ConfigurationPlugin * This has been made a two step process to allow the Plugin Manager and * Configuration Manager to be initialised in the Application Registry. * <p> - * If using this ServerConfiguration via an ApplicationRegistry there is no + * If using this ServerConfiguration via an ApplicationRegistry there is no * need to explicitly call {@link #initialise()} as this is done via the * {@link ApplicationRegistry#initialise()} method. * @@ -199,12 +212,12 @@ public class ServerConfiguration extends ConfigurationPlugin * Called by {@link ApplicationRegistry#initialise()}. * <p> * NOTE: A DEFAULT ApplicationRegistry must exist when using this method - * or a new ApplicationRegistry will be created. + * or a new ApplicationRegistry will be created. * * @throws ConfigurationException */ public void initialise() throws ConfigurationException - { + { setConfiguration("", getConfig()); setupVirtualHosts(getConfig()); } @@ -219,10 +232,10 @@ public class ServerConfiguration extends ConfigurationPlugin { // Support for security.jmx.access was removed when JMX access rights were incorporated into the main ACL. // This ensure that users remove the element from their configuration file. - + if (getListValue("security.jmx.access").size() > 0) { - String message = "Validation error : security/jmx/access is no longer a supported element within the configuration xml." + String message = "Validation error : security/jmx/access is no longer a supported element within the configuration xml." + (_configFile == null ? "" : " Configuration file : " + _configFile); throw new ConfigurationException(message); } @@ -236,7 +249,7 @@ public class ServerConfiguration extends ConfigurationPlugin if (getListValue("security.principal-databases.principal-database(0).class").size() > 0) { - String message = "Validation error : security/principal-databases is no longer supported within the configuration xml." + String message = "Validation error : security/principal-databases is no longer supported within the configuration xml." + (_configFile == null ? "" : " Configuration file : " + _configFile); throw new ConfigurationException(message); } @@ -249,6 +262,13 @@ public class ServerConfiguration extends ConfigurationPlugin throw new ConfigurationException(message); } + String[] ports = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT); + String[] authManagers = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER); + if (ports.length != authManagers.length) + { + throw new ConfigurationException("Validation error: Each port-mapping must have exactly one port and exactly one auth-manager."); + } + // QPID-3517: Inconsistency in capitalisation in the SSL configuration keys used within the connector and management configuration // sections. For the moment, continue to understand both but generate a deprecated warning if the less preferred keystore is used. for (String key : new String[] {"management.ssl.keystorePath", @@ -280,7 +300,7 @@ public class ServerConfiguration extends ConfigurationPlugin @SuppressWarnings("unchecked") protected void setupVirtualHosts(Configuration conf) throws ConfigurationException { - List<String> vhostFiles = conf.getList("virtualhosts"); + List<String> vhostFiles = (List) conf.getList("virtualhosts"); Configuration vhostConfig = conf.subset("virtualhosts"); // Only one configuration mechanism allowed @@ -470,7 +490,7 @@ public class ServerConfiguration extends ConfigurationPlugin Configuration newConfig = parseConfig(_configFile); setConfiguration("", newConfig); ApplicationRegistry.getInstance().getSecurityManager().configureHostPlugins(this); - + // Reload virtualhosts from correct location Configuration newVhosts; if (_vhostsFile == null) @@ -495,15 +515,29 @@ public class ServerConfiguration extends ConfigurationPlugin _logger.warn(SECURITY_CONFIG_RELOADED); } } - + 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) @@ -541,16 +575,36 @@ 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", DEFAULT_HTTP_MANAGEMENT_PORT); + } + + public boolean getHTTPSManagementEnabled() + { + return getBooleanValue("management.https.enabled", false); + } + + public int getHTTPSManagementPort() + { + return getIntValue("management.https.port", DEFAULT_HTTPS_MANAGEMENT_PORT); + } + public String[] getVirtualHosts() { return _virtualHosts.keySet().toArray(new String[_virtualHosts.size()]); } - + public String getPluginDirectory() { return getStringValue("plugin-directory"); } - + public String getCacheDirectory() { return getStringValue("cache-directory"); @@ -581,6 +635,26 @@ public class ServerConfiguration extends ConfigurationPlugin return getBooleanValue("security.msg-auth"); } + public String getDefaultAuthenticationManager() + { + return getStringValue(SECURITY_DEFAULT_AUTH_MANAGER); + } + + public Map<Integer, String> getPortAuthenticationMappings() + { + String[] ports = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_PORT); + String[] authManagers = getConfig().getStringArray(SECURITY_PORT_MAPPINGS_PORT_MAPPING_AUTH_MANAGER); + + Map<Integer,String> portMappings = new HashMap<Integer, String>(); + for(int i = 0; i < ports.length; i++) + { + portMappings.put(Integer.valueOf(ports[i]), authManagers[i]); + } + + return portMappings; + } + + public String getManagementKeyStorePath() { final String fallback = getStringValue("management.ssl.keystorePath"); @@ -589,7 +663,7 @@ public class ServerConfiguration extends ConfigurationPlugin public boolean getManagementSSLEnabled() { - return getBooleanValue("management.ssl.enabled", true); + return getBooleanValue("management.ssl.enabled", false); } public String getManagementKeyStorePassword() @@ -603,16 +677,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); @@ -645,7 +714,7 @@ public class ServerConfiguration extends ConfigurationPlugin public long getMinimumAlertRepeatGap() { - return getLongValue("minimumAlertRepeatGap"); + return getLongValue("minimumAlertRepeatGap", DEFAULT_MINIMUM_ALERT_REPEAT_GAP); } public long getCapacity() @@ -693,6 +762,31 @@ public class ServerConfiguration extends ConfigurationPlugin return getListValue("connector.non08port"); } + public List getPortInclude08() + { + return getListValue(CONNECTOR_INCLUDE_08); + } + + public List getPortInclude09() + { + return getListValue(CONNECTOR_INCLUDE_09); + } + + public List getPortInclude091() + { + return getListValue(CONNECTOR_INCLUDE_091); + } + + public List getPortInclude010() + { + return getListValue(CONNECTOR_INCLUDE_010); + } + + public List getPortInclude10() + { + return getListValue(CONNECTOR_INCLUDE_10); + } + public String getBind() { return getStringValue("connector.bind", WILDCARD_ADDRESS); @@ -740,6 +834,11 @@ public class ServerConfiguration extends ConfigurationPlugin return getStringValue("connector.ssl.keyStorePassword", fallback); } + public String getConnectorKeyStoreType() + { + return getStringValue("connector.ssl.keyStoreType", "JKS"); + } + public String getConnectorKeyManagerFactoryAlgorithm() { final String systemFallback = KeyManagerFactory.getDefaultAlgorithm(); @@ -748,6 +847,41 @@ public class ServerConfiguration extends ConfigurationPlugin return getStringValue("connector.ssl.keyManagerFactoryAlgorithm", fallback); } + public String getConnectorTrustStorePath() + { + return getStringValue("connector.ssl.trustStorePath", null); + } + + public String getConnectorTrustStorePassword() + { + return getStringValue("connector.ssl.trustStorePassword", null); + } + + public String getConnectorTrustStoreType() + { + return getStringValue("connector.ssl.trustStoreType", "JKS"); + } + + public String getConnectorTrustManagerFactoryAlgorithm() + { + return getStringValue("connector.ssl.trustManagerFactoryAlgorithm", TrustManagerFactory.getDefaultAlgorithm()); + } + + public String getCertAlias() + { + return getStringValue("connector.ssl.certAlias", null); + } + + public boolean needClientAuth() + { + return getConfig().getBoolean("connector.ssl.needClientAuth", false); + } + + public boolean wantClientAuth() + { + return getConfig().getBoolean("connector.ssl.wantClientAuth", false); + } + public String getDefaultVirtualHost() { return getStringValue("virtualhosts.default"); @@ -756,7 +890,7 @@ public class ServerConfiguration extends ConfigurationPlugin public void setDefaultVirtualHost(String vhost) { getConfig().setProperty("virtualhosts.default", vhost); - } + } public void setHousekeepingCheckPeriod(long value) { @@ -883,4 +1017,15 @@ 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/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java index f6fe47b996..51dcc38c47 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java @@ -28,7 +28,7 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf private final String _transport; private InetSocketAddress _address; - public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig, + public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig, final InetSocketAddress address, final String transport) { @@ -76,4 +76,15 @@ public class ServerNetworkTransportConfiguration implements NetworkTransportConf { return _address; } + + public boolean needClientAuth() + { + return _serverConfig.needClientAuth(); + } + + @Override + public boolean wantClientAuth() + { + return _serverConfig.wantClientAuth(); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java index 98109ce1e8..80c2e8b2f1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigImpl.java @@ -33,7 +33,7 @@ public class SystemConfigImpl implements SystemConfig private static final String OS_ARCH = System.getProperty("os.arch"); private static final String OS_VERSION = System.getProperty("os.version"); - private final UUID _id; + private final UUID _qmfId; private String _name; private final String _host; @@ -48,9 +48,9 @@ public class SystemConfigImpl implements SystemConfig this(store.createId(), store); } - public SystemConfigImpl(UUID id, ConfigStore store) + public SystemConfigImpl(UUID qmfId, ConfigStore store) { - _id = id; + _qmfId = qmfId; _store = store; String host; try @@ -95,9 +95,10 @@ public class SystemConfigImpl implements SystemConfig return OS_ARCH; } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public SystemConfigType getConfigType() @@ -119,12 +120,12 @@ public class SystemConfigImpl implements SystemConfig { broker.setSystem(this); _store.addConfiguredObject(broker); - _brokers.put(broker.getId(), broker); + _brokers.put(broker.getQMFId(), broker); } public void removeBroker(final BrokerConfig broker) { - _brokers.remove(broker.getId()); + _brokers.remove(broker.getQMFId()); _store.removeConfiguredObject(broker); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java index d7c36da4e0..4a383cce7a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/SystemConfigType.java @@ -65,7 +65,7 @@ public final class SystemConfigType extends ConfigObjectType<SystemConfigType, S { public UUID getValue(SystemConfig object) { - return object.getId(); + return object.getQMFId(); } }; diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java index 10e40151b0..aaa1766489 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/TopicConfig.java @@ -61,7 +61,6 @@ public class TopicConfig extends ConfigurationPlugin throw new ConfigurationException("Topic section must have a 'name' or 'subscriptionName' element."); } - System.err.println("********* Created TC:"+this); } @@ -75,5 +74,5 @@ public class TopicConfig extends ConfigurationPlugin } return response; - } + } }
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java index 5f472b6ddd..e557085631 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java +++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java @@ -32,7 +32,6 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.MemoryMessageStore; -import org.apache.qpid.server.store.MemoryMessageStoreFactory; import java.util.ArrayList; import java.util.Arrays; @@ -103,14 +102,14 @@ public class VirtualHostConfiguration extends ConfigurationPlugin return getConfig().subset("store"); } - public String getMessageStoreFactoryClass() + public String getMessageStoreClass() { - return getStringValue("store.factoryclass", MemoryMessageStoreFactory.class.getName()); + return getStringValue("store.class", MemoryMessageStore.class.getName()); } - public void setMessageStoreFactoryClass(String storeFactoryClass) + public void setMessageStoreClass(String storeFactoryClass) { - getConfig().setProperty("store.factoryclass", storeFactoryClass); + getConfig().setProperty("store.class", storeFactoryClass); } public List getExchanges() @@ -271,7 +270,7 @@ public class VirtualHostConfiguration extends ConfigurationPlugin public Long getMinimumAlertRepeatGap() { - return getLongValue("queues.minimumAlertRepeatGap"); + return getLongValue("queues.minimumAlertRepeatGap", ApplicationRegistry.getInstance().getConfiguration().getMinimumAlertRepeatGap()); } public long getCapacity() diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/management/ConfigurationManagementMBean.java deleted file mode 100644 index f0ca5dc139..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java index 4a58314f51..451754e6d8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java @@ -22,13 +22,12 @@ package org.apache.qpid.server.connection; import org.apache.log4j.Logger; -import org.apache.qpid.AMQException; import org.apache.qpid.common.Closeable; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.protocol.AMQConnectionModel; -import org.apache.qpid.transport.TransportException; import java.util.ArrayList; +import java.util.Collection; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -37,6 +36,8 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable private List<AMQConnectionModel> _registry = new CopyOnWriteArrayList<AMQConnectionModel>(); private Logger _logger = Logger.getLogger(ConnectionRegistry.class); + private final Collection<RegistryChangeListener> _listeners = + new ArrayList<RegistryChangeListener>(); public void initialise() { @@ -62,34 +63,77 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable } } - public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message) + private void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message) { try { connection.close(cause, message); } - catch (TransportException e) + catch (Exception e) { - _logger.warn("Error closing connection:" + e.getMessage()); - } - catch (AMQException e) - { - _logger.warn("Error closing connection:" + e.getMessage()); + _logger.warn("Exception closing connection", e); } } public void registerConnection(AMQConnectionModel connnection) { - _registry.add(connnection); + synchronized (this) + { + _registry.add(connnection); + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.connectionRegistered(connnection); + } + } + } + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.connectionRegistered(connnection); + } + } } public void deregisterConnection(AMQConnectionModel connnection) { - _registry.remove(connnection); + synchronized (this) + { + _registry.remove(connnection); + + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.connectionUnregistered(connnection); + } + } + } + + synchronized (_listeners) + { + for(RegistryChangeListener listener : _listeners) + { + listener.connectionUnregistered(connnection); + } + } + } + + public void addRegistryChangeListener(RegistryChangeListener listener) + { + synchronized (_listeners) + { + _listeners.add(listener); + } } public List<AMQConnectionModel> getConnections() { - return new ArrayList<AMQConnectionModel>(_registry); + synchronized (this) + { + return new ArrayList<AMQConnectionModel>(_registry); + } } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java index 954c448b72..82adcf4dde 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java @@ -37,11 +37,18 @@ public interface IConnectionRegistry public void close(String replyText) throws AMQException; - public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message); - public List<AMQConnectionModel> getConnections(); public void registerConnection(AMQConnectionModel connnection); public void deregisterConnection(AMQConnectionModel connnection); + + void addRegistryChangeListener(RegistryChangeListener listener); + + interface RegistryChangeListener + { + void connectionRegistered(AMQConnectionModel connection); + void connectionUnregistered(AMQConnectionModel connection); + + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index 9493f400f2..512a8c6996 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/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,12 +78,16 @@ 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>(); //TODO : persist creation time private long _createTime = System.currentTimeMillis(); + private UUID _qmfId; + public AbstractExchange(final ExchangeType<? extends Exchange> type) { _type = type; @@ -107,13 +103,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 { @@ -124,28 +113,14 @@ public abstract class AbstractExchange implements Exchange, Managable _ticket = ticket; _id = id; - + _qmfId = getConfigStore().createId(); 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 +146,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 +167,6 @@ public abstract class AbstractExchange implements Exchange, Managable return getClass().getSimpleName() + "[" + getNameShortString() +"]"; } - public ManagedObject getManagedObject() - { - return _exchangeMbean; - } - public VirtualHost getVirtualHost() { return _virtualHost; @@ -332,6 +298,12 @@ public abstract class AbstractExchange implements Exchange, Managable return _id; } + @Override + public UUID getQMFId() + { + return _qmfId; + } + public ExchangeConfigType getConfigType() { return ExchangeConfigType.getInstance(); @@ -359,6 +331,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 +351,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 +366,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/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java deleted file mode 100644 index 034331abd9..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java index bf4184bf0b..07813b073b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeRegistry.java +++ b/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 + for(RegistryChangeListener listener : _listeners) { - abstractExchange.getManagedObject().unregister(); - } - catch (AMQException e) - { - LOGGER.warn("Failed to unregister mbean", e); + listener.exchangeUnregistered(exchange); } } } @@ -196,4 +225,21 @@ public class DefaultExchangeRegistry implements ExchangeRegistry } } + public boolean isReservedExchangeName(String name) + { + if (name == null || "".equals(name) || ExchangeDefaults.DEFAULT_EXCHANGE_NAME.asString().equals(name) + || name.startsWith("amq.") || name.startsWith("qpid.")) + { + return true; + } + Collection<ExchangeType<? extends Exchange>> registeredTypes = _host.getExchangeFactory().getRegisteredTypes(); + for (ExchangeType<? extends Exchange> type : registeredTypes) + { + if (type.getDefaultExchangeName().toString().equals(name)) + { + return true; + } + } + return false; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index af9322764a..92326412c1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DirectExchangeMBean.java deleted file mode 100644 index 0bfaf7035d..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java index 289cb1a923..762686e68d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java @@ -147,4 +147,6 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig { public void onClose(Exchange exchange) throws AMQSecurityException, AMQInternalException; } + + UUID getId(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java index 795ae2e140..4dcedb4797 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java +++ b/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,21 @@ public interface ExchangeRegistry void clearAndUnregisterMbeans(); Exchange getExchange(UUID exchangeId); + + Collection<Exchange> getExchanges(); + + void addRegistryChangeListener(RegistryChangeListener listener); + + /** + * Validates the name of user custom exchange. + * <p> + * Return true if the exchange name is reserved and false otherwise. + */ + boolean isReservedExchangeName(String name); + + interface RegistryChangeListener + { + void exchangeRegistered(Exchange exchange); + void exchangeUnregistered(Exchange exchange); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java index 5ebcfd095f..5f4998f77f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeMBean.java deleted file mode 100644 index 61e23c896c..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index 16ba3c0431..6bad59c2ae 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeMBean.java deleted file mode 100644 index 395c6c8a91..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index 7ea7a41826..0ce16bd3f7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -291,7 +291,7 @@ public class TopicExchange extends AbstractExchange public boolean isBound(AMQShortString routingKey, FieldTable arguments, AMQQueue queue) { - Binding binding = new Binding(null, routingKey.toString(), queue, this, FieldTable.convertToMap(arguments)); + Binding binding = new Binding(null, null, routingKey.toString(), queue, this, FieldTable.convertToMap(arguments)); if (arguments == null) { @@ -314,7 +314,7 @@ public class TopicExchange extends AbstractExchange public boolean isBound(String bindingKey, Map<String, Object> arguments, AMQQueue queue) { - Binding binding = new Binding(null, bindingKey, queue, this, arguments); + Binding binding = new Binding(null, null, bindingKey, queue, this, arguments); if (arguments == null) { return _bindings.containsKey(binding); @@ -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/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/TopicExchangeMBean.java deleted file mode 100644 index 481a377fc4..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java index dfe4d85320..dad951c3ca 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherDFAState.java @@ -1,3 +1,23 @@ +/* + * + * 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.topic; import org.apache.qpid.framing.AMQShortString; @@ -16,26 +36,6 @@ import java.util.SortedSet; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; -/* -* -* 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. -* -*/ public class TopicMatcherDFAState { private static final AtomicInteger stateId = new AtomicInteger(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java index 71d30adfac..6084b18b31 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicMatcherResult.java @@ -1,5 +1,3 @@ -package org.apache.qpid.server.exchange.topic; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -20,6 +18,8 @@ package org.apache.qpid.server.exchange.topic; * under the License. * */ +package org.apache.qpid.server.exchange.topic; + public interface TopicMatcherResult { } diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java index 1cb4301838..6f47e4e7f2 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicParser.java @@ -1,3 +1,23 @@ +/* + * + * 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.topic; import org.apache.qpid.framing.AMQShortString; @@ -13,26 +33,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.atomic.AtomicReference; -/* -* -* 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. -* -*/ public class TopicParser { private static final byte TOPIC_DELIMITER = (byte)'.'; diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java index b23b3db272..7345d30a0a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWord.java @@ -1,7 +1,3 @@ -package org.apache.qpid.server.exchange.topic; - -import org.apache.qpid.framing.AMQShortString; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -22,6 +18,11 @@ import org.apache.qpid.framing.AMQShortString; * under the License. * */ + +package org.apache.qpid.server.exchange.topic; + +import org.apache.qpid.framing.AMQShortString; + public final class TopicWord { public static final TopicWord ANY_WORD = new TopicWord("*"); diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java index 65a0cd3107..181c26dd66 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java +++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/topic/TopicWordDictionary.java @@ -1,9 +1,3 @@ -package org.apache.qpid.server.exchange.topic; - -import org.apache.qpid.framing.AMQShortString; - -import java.util.concurrent.ConcurrentHashMap; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -24,6 +18,12 @@ import java.util.concurrent.ConcurrentHashMap; * under the License. * */ +package org.apache.qpid.server.exchange.topic; + +import org.apache.qpid.framing.AMQShortString; + +import java.util.concurrent.ConcurrentHashMap; + public class TopicWordDictionary { private final ConcurrentHashMap<AMQShortString,TopicWord> _dictionary = diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java index c7046f8e53..7eb476b15a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java +++ b/java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java @@ -91,7 +91,7 @@ public class Bridge implements BridgeConfig private final String _tag; private final String _excludes; private final BrokerLink _link; - private UUID _id; + private UUID _qmfId; private long _createTime = System.currentTimeMillis(); private Session _session; @@ -124,7 +124,7 @@ public class Bridge implements BridgeConfig _key = key; _tag = tag; _excludes = excludes; - _id = durable ? brokerLink.getConfigStore().createPersistentId() : brokerLink.getConfigStore().createId(); + _qmfId = durable ? brokerLink.getConfigStore().createPersistentId() : brokerLink.getConfigStore().createId(); _transaction = new AutoCommitTransaction(getVirtualHost().getMessageStore()); @@ -198,7 +198,7 @@ public class Bridge implements BridgeConfig { _link = brokerLink; _bridgeNo = bridgeNo; - _id = id; + _qmfId = id; brokerLink.getConfigStore().persistentIdInUse(id); _createTime = createTime; @@ -249,9 +249,10 @@ public class Bridge implements BridgeConfig return Collections.unmodifiableMap(arguments); } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public BridgeConfigType getConfigType() diff --git a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java index 4bcc0d6136..1ef57c53cb 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java +++ b/java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java @@ -89,7 +89,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener private final String _username; private final String _password; private final VirtualHost _virtualHost; - private UUID _id; + private UUID _qmfId; private AtomicBoolean _closing = new AtomicBoolean(); private final long _createTime; private Connection _qpidConnection; @@ -133,7 +133,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener private class ConnectionConfigAdapter implements ConnectionConfig { private long _adapterCreateTime = System.currentTimeMillis(); - private UUID _id = BrokerLink.this.getConfigStore().createId(); + private UUID _qmfId = BrokerLink.this.getConfigStore().createId(); public VirtualHost getVirtualHost() { @@ -185,9 +185,10 @@ public class BrokerLink implements LinkConfig, ConnectionListener return getVirtualHost().getConfigStore(); } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public ConnectionConfigType getConfigType() @@ -230,11 +231,11 @@ public class BrokerLink implements LinkConfig, ConnectionListener } }; - public BrokerLink(final VirtualHost virtualHost, UUID id, long createTime, Map<String, String> arguments) + public BrokerLink(final VirtualHost virtualHost, UUID qmfId, long createTime, Map<String, String> arguments) { _virtualHost = virtualHost; - _id = id; - virtualHost.getConfigStore().persistentIdInUse(id); + _qmfId = qmfId; + virtualHost.getConfigStore().persistentIdInUse(qmfId); _createTime = createTime; _transport = arguments.get(TRANSPORT); @@ -289,7 +290,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener _authMechanism = authMechanism; _username = username; _password = password; - _id = durable ? virtualHost.getConfigStore().createPersistentId() : virtualHost.getConfigStore().createId(); + _qmfId = durable ? virtualHost.getConfigStore().createPersistentId() : virtualHost.getConfigStore().createId(); if(durable) { @@ -457,9 +458,10 @@ public class BrokerLink implements LinkConfig, ConnectionListener return _remoteVhost; } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public LinkConfigType getConfigType() @@ -672,7 +674,7 @@ public class BrokerLink implements LinkConfig, ConnectionListener public String toString() { return "BrokerLink{" + - " _id=" + _id + + " _id=" + _qmfId + ", _transport='" + _transport + '\'' + ", _host='" + _host + '\'' + ", _port=" + _port + diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java index 5a5ef5e6c5..be3a13d2d3 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/flow/BytesOnlyCreditManager.java @@ -1,8 +1,3 @@ -package org.apache.qpid.server.flow; - - -import java.util.concurrent.atomic.AtomicLong; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -23,6 +18,11 @@ import java.util.concurrent.atomic.AtomicLong; * under the License. * */ +package org.apache.qpid.server.flow; + + +import java.util.concurrent.atomic.AtomicLong; + public class BytesOnlyCreditManager extends AbstractFlowCreditManager { private final AtomicLong _bytesCredit; diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java index 8a80262983..280f2851a4 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager.java @@ -1,6 +1,3 @@ -package org.apache.qpid.server.flow; - - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -21,6 +18,10 @@ package org.apache.qpid.server.flow; * under the License. * */ +package org.apache.qpid.server.flow; + + + public interface FlowCreditManager { long getMessageCredit(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java index 48c336c0b1..fea6eaf744 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/flow/FlowCreditManager_0_10.java @@ -1,5 +1,3 @@ -package org.apache.qpid.server.flow; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -20,6 +18,8 @@ package org.apache.qpid.server.flow; * under the License. * */ +package org.apache.qpid.server.flow; + public interface FlowCreditManager_0_10 extends FlowCreditManager { public void addCredit(long count, long bytes); diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java index 6fcc687440..89fc60666b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/flow/LimitlessCreditManager.java @@ -1,6 +1,3 @@ -package org.apache.qpid.server.flow; - - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -21,6 +18,9 @@ package org.apache.qpid.server.flow; * under the License. * */ +package org.apache.qpid.server.flow; + + public class LimitlessCreditManager extends AbstractFlowCreditManager implements FlowCreditManager { public long getMessageCredit() diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java index 0e6ce70a60..31c1fda968 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageAndBytesCreditManager.java @@ -1,6 +1,3 @@ -package org.apache.qpid.server.flow; - - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -21,6 +18,9 @@ package org.apache.qpid.server.flow; * under the License. * */ +package org.apache.qpid.server.flow; + + public class MessageAndBytesCreditManager extends AbstractFlowCreditManager implements FlowCreditManager { private long _messageCredit; diff --git a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java index 9b7c40e923..1817e8ad31 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/flow/MessageOnlyCreditManager.java @@ -1,8 +1,3 @@ -package org.apache.qpid.server.flow; - - -import java.util.concurrent.atomic.AtomicLong; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -23,6 +18,10 @@ import java.util.concurrent.atomic.AtomicLong; * under the License. * */ +package org.apache.qpid.server.flow; + +import java.util.concurrent.atomic.AtomicLong; + public class MessageOnlyCreditManager extends AbstractFlowCreditManager implements FlowCreditManager { private final AtomicLong _messageCredit; diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java index e1c2782dec..84812485fd 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/AccessRequestHandler.java @@ -1,4 +1,3 @@ -package org.apache.qpid.server.handler;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.handler; * under the License.
*
*/
+package org.apache.qpid.server.handler; import org.apache.qpid.AMQException;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java index 1e0c0273df..43ee8da64f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicRecoverSyncMethodHandler.java @@ -1,4 +1,3 @@ -package org.apache.qpid.server.handler;
/*
*
* Licensed to the Apache Software Foundation (ASF) under one
@@ -19,6 +18,7 @@ package org.apache.qpid.server.handler; * under the License.
*
*/
+package org.apache.qpid.server.handler; import org.apache.log4j.Logger;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java index 2ccf97f17c..b8c8411c5d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.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 @@ -61,7 +61,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener { AMQProtocolSession session = stateManager.getProtocolSession(); - AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager(); + AuthenticationManager authMgr = stateManager.getAuthenticationManager(); SaslServer ss = session.getSaslServer(); if (ss == null) @@ -92,7 +92,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener case SUCCESS: if (_logger.isInfoEnabled()) { - _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject())); + _logger.info("Connected as: " + authResult.getSubject()); } stateManager.changeState(AMQState.CONNECTION_NOT_TUNED); @@ -102,7 +102,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay()); session.writeFrame(tuneBody.generateFrame(0)); session.setAuthorizedSubject(authResult.getSubject()); - disposeSaslServer(session); + disposeSaslServer(session); break; case CONTINUE: stateManager.changeState(AMQState.CONNECTION_NOT_AUTH); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java index 162e4e0215..a522b9f60f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.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 @@ -61,15 +61,15 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener< public void methodReceived(AMQStateManager stateManager, ConnectionStartOkBody body, int channelId) throws AMQException { AMQProtocolSession session = stateManager.getProtocolSession(); - + _logger.info("SASL Mechanism selected: " + body.getMechanism()); _logger.info("Locale selected: " + body.getLocale()); - AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager(); + AuthenticationManager authMgr = stateManager.getAuthenticationManager(); SaslServer ss = null; try - { - ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN()); + { + ss = authMgr.createSaslServer(String.valueOf(body.getMechanism()), session.getLocalFQDN(), session.getPeerPrincipal()); if (ss == null) { @@ -106,7 +106,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener< case SUCCESS: if (_logger.isInfoEnabled()) { - _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject())); + _logger.info("Connected as: " + authResult.getSubject()); } session.setAuthorizedSubject(authResult.getSubject()); diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java index 396829df91..ae725b9ec1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java @@ -225,7 +225,10 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar String owner = body.getExclusive() ? AMQShortString.toString(session.getContextKey()) : null; Map<String, Object> arguments = FieldTable.convertToMap(body.getArguments()); - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), AMQShortString.toString(queueName), body.getDurable(), owner, body.getAutoDelete(), + String queueNameString = AMQShortString.toString(queueName); + + final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueNameString, virtualHost.getName()), + queueNameString, body.getDurable(), owner, body.getAutoDelete(), body.getExclusive(),virtualHost, arguments); if (body.getExclusive() && !body.getDurable()) diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java index a8ae2099cc..66a6ff6527 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/QueueUnbindHandler.java @@ -1,4 +1,3 @@ -package org.apache.qpid.server.handler; /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -19,6 +18,7 @@ package org.apache.qpid.server.handler; * under the License. * */ +package org.apache.qpid.server.handler; import org.apache.log4j.Logger; diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java index 6e8896a023..afa5fdb72a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/handler/TxCommitHandler.java @@ -46,9 +46,9 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody> { } - public void methodReceived(AMQStateManager stateManager, TxCommitBody body, int channelId) throws AMQException + public void methodReceived(AMQStateManager stateManager, TxCommitBody body, final int channelId) throws AMQException { - AMQProtocolSession session = stateManager.getProtocolSession(); + final AMQProtocolSession session = stateManager.getProtocolSession(); try { @@ -62,11 +62,19 @@ public class TxCommitHandler implements StateAwareMethodListener<TxCommitBody> { throw body.getChannelNotFoundException(channelId); } - channel.commit(); + channel.commit(new Runnable() + { + + @Override + public void run() + { + MethodRegistry methodRegistry = session.getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody(); + session.writeFrame(responseBody.generateFrame(channelId)); + } + }, true); + - MethodRegistry methodRegistry = session.getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createTxCommitOkBody(); - session.writeFrame(responseBody.generateFrame(channelId)); } catch (AMQException e) diff --git a/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java b/java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java deleted file mode 100644 index 4d395f625a..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java b/java/broker/src/main/java/org/apache/qpid/server/logging/LogRecorder.java new file mode 100644 index 0000000000..a1065319d3 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java new file mode 100644 index 0000000000..931171b175 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacade.java @@ -0,0 +1,579 @@ +/* + * + * 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.log4j; + +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.apache.log4j.xml.DOMConfigurator; +import org.apache.log4j.xml.Log4jEntityResolver; +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.xml.sax.SAXParseException; + +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.TransformerConfigurationException; +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.FileOutputStream; +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; + +/** + * A facade over log4j that allows both the control of the runtime logging behaviour (that is, the ability to + * turn {@link Logger} on, off and control their {@link Level}, and the manipulation and reload + * of the log4j configuration file. + */ +public class LoggingFacade +{ + private static Logger LOGGER; + private static transient LoggingFacade _instance; + private final String _filename; + private final int _delay; + + public static LoggingFacade configure(String filename) throws LoggingFacadeException + { + _instance = new LoggingFacade(filename); + return _instance; + } + + public static LoggingFacade configureAndWatch(String filename, int delay) throws LoggingFacadeException + { + _instance = new LoggingFacade(filename, delay); + return _instance; + } + + public static LoggingFacade getCurrentInstance() + { + return _instance; + } + + private LoggingFacade(String filename) + { + DOMConfigurator.configure(filename); + + if(LOGGER == null) + { + LOGGER = Logger.getLogger(LoggingFacade.class); + } + _filename = filename; + _delay = 0; + } + + private LoggingFacade(String filename, int delay) + { + DOMConfigurator.configureAndWatch(filename, delay); + + if(LOGGER == null) + { + LOGGER = Logger.getLogger(LoggingFacade.class); + } + + _filename = filename; + _delay = delay; + } + + public int getLog4jLogWatchInterval() + { + return _delay; + } + + public synchronized void reload() throws LoggingFacadeException + { + DOMConfigurator.configure(_filename); + } + + /** 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 synchronized Map<String,String> retrieveConfigFileLoggersLevels() throws LoggingFacadeException + { + try + { + Map<String,String> loggerLevelList = new HashMap<String,String>(); + LOGGER.info("Getting logger levels from log4j configuration file"); + + Document doc = parseConfigFile(_filename); + List<Element> categoryOrLoggerElements = buildListOfCategoryOrLoggerElements(doc); + + for (Element categoryOrLogger : categoryOrLoggerElements) + { + + Element priorityOrLevelElement; + try + { + priorityOrLevelElement = getPriorityOrLevelElement(categoryOrLogger); + } + catch (LoggingFacadeException lfe) + { + //there is no exiting priority or level to view, move onto next category/logger + continue; + } + + String categoryName = categoryOrLogger.getAttribute("name"); + String priorityOrLevelValue = priorityOrLevelElement.getAttribute("value"); + loggerLevelList.put(categoryName, priorityOrLevelValue); + } + + return loggerLevelList; + } + catch (IOException e) + { + throw new LoggingFacadeException(e); + } + } + + /** + * 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 synchronized String retrieveConfigFileRootLoggerLevel() throws LoggingFacadeException + { + try + { + 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); + Element levelElement = getPriorityOrLevelElement(rootElement); + + if(levelElement != null) + { + return levelElement.getAttribute("value"); + } + else + { + return "N/A"; + } + } + catch (IOException e) + { + throw new LoggingFacadeException(e); + } + } + + public synchronized void setConfigFileLoggerLevel(String logger, String level) throws LoggingFacadeException + { + LOGGER.info("Setting level to " + level + " for logger '" + logger + + "' in log4j xml configuration file: " + _filename); + + try + { + Document doc = parseConfigFile(_filename); + + List<Element> logElements = buildListOfCategoryOrLoggerElements(doc); + + //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) + { + throw new LoggingFacadeException("Can't find logger " + logger); + } + + Element levelElement = getPriorityOrLevelElement(logElement); + + //update the element with the new level/priority + levelElement.setAttribute("value", level); + + //output the new file + writeUpdatedConfigFile(_filename, doc); + } + catch (IOException ioe) + { + throw new LoggingFacadeException(ioe); + } + catch (TransformerConfigurationException e) + { + throw new LoggingFacadeException(e); + } + } + + public synchronized void setConfigFileRootLoggerLevel(String level) throws LoggingFacadeException + { + try + { + LOGGER.info("Setting level to " + level + " for the Root logger in " + + "log4j xml configuration file: " + _filename); + + Document doc = parseConfigFile(_filename); + + //retrieve the optional 'root' element node + NodeList rootElements = doc.getElementsByTagName("root"); + + if (rootElements.getLength() == 0) + { + throw new LoggingFacadeException("Configuration contains no root element"); + } + + Element rootElement = (Element) rootElements.item(0); + Element levelElement = getPriorityOrLevelElement(rootElement); + + //update the element with the new level/priority + levelElement.setAttribute("value", level); + + //output the new file + writeUpdatedConfigFile(_filename, doc); + } + catch (IOException e) + { + throw new LoggingFacadeException(e); + } + catch (TransformerConfigurationException e) + { + throw new LoggingFacadeException(e); + } + } + + public List<String> getAvailableLoggerLevels() + { + return new ArrayList<String>() + {{ + add(Level.ALL.toString()); + add(Level.TRACE.toString()); + add(Level.DEBUG.toString()); + add(Level.INFO.toString()); + add(Level.WARN.toString()); + add(Level.ERROR.toString()); + add(Level.FATAL.toString()); + add(Level.OFF.toString()); + }}; + } + + public String retrieveRuntimeRootLoggerLevel() + { + Logger rootLogger = Logger.getRootLogger(); + return rootLogger.getLevel().toString(); + } + + public void setRuntimeRootLoggerLevel(String level) + { + Level newLevel = Level.toLevel(level); + + LOGGER.info("Setting RootLogger level to " + level); + + Logger log = Logger.getRootLogger(); + log.setLevel(newLevel); + } + + public void setRuntimeLoggerLevel(String loggerName, String level) throws LoggingFacadeException + { + Level newLevel = level == null ? null : Level.toLevel(level); + + Logger targetLogger = findRuntimeLogger(loggerName); + + if(targetLogger == null) + { + throw new LoggingFacadeException("Can't find logger " + loggerName); + } + + LOGGER.info("Setting level to " + newLevel + " for logger '" + targetLogger.getName() + "'"); + + targetLogger.setLevel(newLevel); + } + + public Map<String,String> retrieveRuntimeLoggersLevels() + { + LOGGER.info("Getting levels for currently active log4j loggers"); + + Map<String, String> levels = new HashMap<String, String>(); + @SuppressWarnings("unchecked") + Enumeration<Logger> loggers = LogManager.getCurrentLoggers(); + + while (loggers.hasMoreElements()) + { + Logger logger = loggers.nextElement(); + levels.put(logger.getName(), logger.getEffectiveLevel().toString()); + } + + return levels; + } + + private void writeUpdatedConfigFile(String log4jConfigFileName, Document doc) throws IOException, TransformerConfigurationException + { + 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; + transformer = TransformerFactory.newInstance().newTransformer(); + + 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.getAbsolutePath() + r.nextInt() + ".tmp"); + } + while(tmp.exists()); + + tmp.deleteOnExit(); + + try + { + StreamResult result = new StreamResult(new FileOutputStream(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"); + } + } + + //method to parse the XML configuration file, validating it in the process, and returning a DOM Document of the content. + private static Document parseConfigFile(String fileName) throws IOException + { + //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); + throw new IOException("Unable to parse the log4j XML file due to possible configuration error: ", e); + } + catch (SAXException e) + { + LOGGER.warn("The specified log4j XML file is invalid: ", e); + throw new IOException("The specified log4j XML file is invalid: ", e); + } + 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); + } + + return doc; + } + + private Logger findRuntimeLogger(String loggerName) + { + Logger targetLogger = null; + @SuppressWarnings("unchecked") + Enumeration<Logger> loggers = LogManager.getCurrentLoggers(); + while(loggers.hasMoreElements()) + { + targetLogger = loggers.nextElement(); + if (targetLogger.getName().equals(loggerName)) + { + return targetLogger; + } + } + return null; + } + + private List<Element> buildListOfCategoryOrLoggerElements(Document doc) + { + //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)); + } + return logElements; + } + + private Element getPriorityOrLevelElement(Element categoryOrLogger) throws LoggingFacadeException + { + //retrieve the optional 'priority' or 'level' sub-element value. + //It may not be the only child node, so request by tag name. + NodeList priorityElements = categoryOrLogger.getElementsByTagName("priority"); + NodeList levelElements = categoryOrLogger.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 + { + throw new LoggingFacadeException("Configuration " + categoryOrLogger.getNodeName() + + " element contains neither priority nor level child"); + } + return levelElement; + } + + private static class QpidLog4JSaxErrorHandler implements ErrorHandler + { + public void error(SAXParseException e) throws SAXException + { + if(LOGGER != null) + { + LOGGER.warn(constructMessage("Error parsing XML file", e)); + } + else + { + System.err.println(constructMessage("Error parsing XML file", e)); + } + } + + public void fatalError(SAXParseException e) throws SAXException + { + throw new SAXException(constructMessage("Fatal error parsing XML file", e)); + } + + public void warning(SAXParseException e) throws SAXException + { + if(LOGGER != null) + { + LOGGER.warn(constructMessage("Warning parsing XML file", e)); + } + else + { + System.err.println(constructMessage("Warning parsing XML file", e)); + } + } + + private static String constructMessage(final String msg, final SAXParseException ex) + { + return msg + ": Line " + ex.getLineNumber()+" column " +ex.getColumnNumber() + ": " + ex.getMessage(); + } + } +} + diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacadeException.java index 12d7f64a8d..468b06be34 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStoreFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/log4j/LoggingFacadeException.java @@ -17,24 +17,29 @@ * under the License. * */ -package org.apache.qpid.server.store.derby; +package org.apache.qpid.server.logging.log4j; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreFactory; - -public class DerbyMessageStoreFactory implements MessageStoreFactory +public class LoggingFacadeException extends Exception { - @Override - public MessageStore createMessageStore() + public LoggingFacadeException() + { + super(); + } + + public LoggingFacadeException(String message, Throwable cause) + { + super(message, cause); + } + + public LoggingFacadeException(String message) { - return new DerbyMessageStore(); + super(message); } - @Override - public String getStoreClassName() + public LoggingFacadeException(Throwable cause) { - return DerbyMessageStore.class.getSimpleName(); + super(cause); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java b/java/broker/src/main/java/org/apache/qpid/server/logging/management/LoggingManagementMBean.java deleted file mode 100644 index c699dff175..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties index 081f2bbca3..d3823a71a0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/MessageStore_logmessages.properties @@ -26,3 +26,5 @@ RECOVERY_START = MST-1004 : Recovery Start RECOVERED = MST-1005 : Recovered {0,number} messages RECOVERY_COMPLETE = MST-1006 : Recovery Complete PASSIVATE = MST-1007 : Store Passivated +OVERFULL = MST-1008 : Store overfull, flow control will be enforced +UNDERFULL = MST-1009 : Store overfull condition cleared diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties index 3e640c7929..5695026cbc 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties +++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties @@ -23,4 +23,6 @@ CREATED = VHT-1001 : Created : {0} CLOSED = VHT-1002 : Closed STATS_DATA = VHT-1003 : {0} : {1,choice,0#delivered|1#received} : {2,number,#.###} kB/s peak : {3,number,#} bytes total -STATS_MSGS = VHT-1004 : {0} : {1,choice,0#delivered|1#received} : {2,number,#.###} msg/s peak : {3,number,#} msgs total`
\ No newline at end of file +STATS_MSGS = VHT-1004 : {0} : {1,choice,0#delivered|1#received} : {2,number,#.###} msg/s peak : {3,number,#} msgs total + +ERRORED = VHT-1005 : Unexpected fatal error
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java b/java/broker/src/main/java/org/apache/qpid/server/management/AMQManagedObject.java deleted file mode 100644 index 5c57c01f6e..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java b/java/broker/src/main/java/org/apache/qpid/server/management/AbstractAMQManagedConnectionObject.java deleted file mode 100644 index 6cfc827046..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java b/java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java deleted file mode 100644 index 10d7503800..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java deleted file mode 100644 index 04a5b27991..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java +++ /dev/null @@ -1,491 +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.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; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; - -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 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.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.util.HashMap; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 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()); - 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 UsernamePrincipal usernamePrincipalFromSubject = UsernamePrincipal.getUsernamePrincipalFromSubject(subject); - connectionIdUsernameMap.put(connectionId, usernamePrincipalFromSubject.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/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java b/java/broker/src/main/java/org/apache/qpid/server/management/MBeanIntrospector.java deleted file mode 100644 index 89b74f939d..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java b/java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java deleted file mode 100644 index 651372db16..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java b/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java deleted file mode 100644 index 166a2a376d..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/management/Managable.java +++ /dev/null @@ -1,34 +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; - -/** - * 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 -{ - ManagedObject getManagedObject(); -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java b/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObject.java deleted file mode 100644 index 483b325455..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/management/ManagedObjectRegistry.java deleted file mode 100644 index b3323c569c..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java deleted file mode 100644 index e77350c3e4..0000000000 --- a/java/broker/src/main/java/org/apache/qpid/server/management/NoopManagedObjectRegistry.java +++ /dev/null @@ -1,58 +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 javax.management.JMException; - -/** - * 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 -{ - 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() - { - - } -} diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java b/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java index faac14f8a7..63bd1e45a0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/AMQMessageHeader.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java index e87b67d242..01c1021070 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java index 583f0c09a7..e890bf5ef8 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java index 7d030fe711..2cc1a92853 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_1_0.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java index 126e7c28cb..91384f7c22 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageTransferHeader.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java b/java/broker/src/main/java/org/apache/qpid/server/model/Attribute.java new file mode 100644 index 0000000000..4fccf47e0e --- /dev/null +++ b/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/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java index 44070f22ad..7a5927a365 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/TestableMemoryMessageStoreFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationMethod.java @@ -1,4 +1,5 @@ /* + * * 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 @@ -17,21 +18,16 @@ * under the License. * */ -package org.apache.qpid.server.store; +package org.apache.qpid.server.model; -public class TestableMemoryMessageStoreFactory implements MessageStoreFactory -{ +import java.util.Collection; - @Override - public MessageStore createMessageStore() - { - return new TestableMemoryMessageStore(); - } +public interface AuthenticationMethod extends ConfiguredObject +{ + // name is the SASL mech where this is a SASL authentication - @Override - public String getStoreClassName() - { - return TestableMemoryMessageStore.class.getSimpleName(); - } + // parents + VirtualHostAlias getVirtualHostAlias(); + AuthenticationProvider getAuthenticationProvider(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java b/java/broker/src/main/java/org/apache/qpid/server/model/AuthenticationProvider.java new file mode 100644 index 0000000000..6000886956 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java b/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java new file mode 100644 index 0000000000..08b01a1b65 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Broker.java @@ -0,0 +1,80 @@ +/* + * + * 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 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, + 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/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java index 6477633a9b..78b98faffe 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/ConfigurationChangeListener.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java index fb47a54d0a..414b2d083a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObject.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java new file mode 100644 index 0000000000..6a7d6f8f7b --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFinder.java @@ -0,0 +1,38 @@ +/* + * + * 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.Collection; + +public class ConfiguredObjectFinder +{ + 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/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java b/java/broker/src/main/java/org/apache/qpid/server/model/Connection.java new file mode 100644 index 0000000000..aaf6007afd --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/model/Event.java index a35db62b03..91b684f06e 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Event.java @@ -1,4 +1,5 @@ /* + * * 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 @@ -17,11 +18,10 @@ * under the License. * */ -package org.apache.qpid.server.store; -public interface MessageStoreFactory -{ - MessageStore createMessageStore(); +package org.apache.qpid.server.model; - String getStoreClassName(); +abstract public class Event<T extends EventType> +{ + abstract public T getEventType(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java b/java/broker/src/main/java/org/apache/qpid/server/model/EventType.java new file mode 100644 index 0000000000..edd5ce4250 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java index e872273d05..e63c71e955 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Exchange.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Model.java b/java/broker/src/main/java/org/apache/qpid/server/model/Model.java new file mode 100644 index 0000000000..fd429321c8 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java b/java/broker/src/main/java/org/apache/qpid/server/model/PasswordCredentialManagingAuthenticationProvider.java new file mode 100644 index 0000000000..1027e5ce8c --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Port.java b/java/broker/src/main/java/org/apache/qpid/server/model/Port.java new file mode 100644 index 0000000000..50c0ebcd14 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java b/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java new file mode 100644 index 0000000000..5d9de69f9a --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/Protocol.java @@ -0,0 +1,33 @@ +/* + * + * 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, + HTTPS +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java b/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java index 7c4f0de22b..bf703e6fbe 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Queue.java +++ b/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"; @@ -98,7 +99,7 @@ public interface Queue extends ConfiguredObject public static final String QUEUE_FLOW_STOPPED = "queueFlowStopped"; public static final String SORT_KEY = "sortKey"; public static final String TYPE = "type"; - + public static final String PRIORITIES = "priorities"; @@ -106,6 +107,7 @@ public interface Queue extends ConfiguredObject Collections.unmodifiableList( Arrays.asList(ID, NAME, + DESCRIPTION, STATE, DURABLE, LIFETIME_POLICY, @@ -130,7 +132,8 @@ public interface Queue extends ConfiguredObject ALERT_THRESHOLD_MESSAGE_SIZE, ALERT_THRESHOLD_QUEUE_DEPTH_BYTES, ALERT_THRESHOLD_QUEUE_DEPTH_MESSAGES, - ALERT_REPEAT_GAP + ALERT_REPEAT_GAP, + PRIORITIES )); //children @@ -143,4 +146,6 @@ public interface Queue extends ConfiguredObject void visit(QueueEntryVisitor visitor); void delete(); + + void setNotificationListener(QueueNotificationListener listener); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java b/java/broker/src/main/java/org/apache/qpid/server/model/QueueNotificationListener.java index 959ca03c80..ab601f685c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueNotificationListener.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/QueueType.java b/java/broker/src/main/java/org/apache/qpid/server/model/QueueType.java new file mode 100644 index 0000000000..96f2a7e2e5 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/QueueType.java @@ -0,0 +1,29 @@ +/* + * + * 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 QueueType +{ + STANDARD, + PRIORITY, + LVQ, + SORTED +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/Session.java b/java/broker/src/main/java/org/apache/qpid/server/model/Session.java new file mode 100644 index 0000000000..e813d0c129 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java b/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java index 2cb81eae82..92d6f47741 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/Statistics.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java b/java/broker/src/main/java/org/apache/qpid/server/model/Transport.java new file mode 100644 index 0000000000..03cd46be01 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java index d8493c6df4..36b6a454dc 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java +++ b/java/broker/src/main/java/org/apache/qpid/server/model/UUIDGenerator.java @@ -22,33 +22,59 @@ package org.apache.qpid.server.model; import java.util.UUID; -import org.apache.qpid.exchange.ExchangeDefaults; - - public class UUIDGenerator { - - public static UUID generateUUID() + //Generates a random UUID. Used primarily by tests. + public static UUID generateRandomUUID() { return UUID.randomUUID(); } - public static UUID generateUUID(String objectName, String virtualHostName) + private static UUID createUUID(String objectType, String... names) { StringBuilder sb = new StringBuilder(); - sb.append(virtualHostName).append(objectName); + sb.append(objectType); + + for(String name : names) + { + sb.append("/").append(name); + } + 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.")) - { - return generateUUID(echangeName, virtualHostName); - } - else - { - return generateUUID(); - } + return createUUID(Exchange.class.getName(), virtualHostName, exchangeName); + } + + public static UUID generateQueueUUID(String queueName, String virtualHostName) + { + return createUUID(Queue.class.getName(), virtualHostName, queueName); + } + + public static UUID generateBindingUUID(String exchangeName, String queueName, String bindingKey, String virtualHostName) + { + return createUUID(Binding.class.getName(), virtualHostName, exchangeName, queueName, bindingKey); + } + + public static UUID generateUserUUID(String authenticationProviderName, String userName) + { + return createUUID(User.class.getName(), authenticationProviderName, userName); + } + + public static UUID generateVhostUUID(String virtualHostName) + { + return createUUID(VirtualHost.class.getName(), virtualHostName); + } + + public static UUID generateVhostAliasUUID(String virtualHostName, String portName) + { + return createUUID(VirtualHostAlias.class.getName(), virtualHostName, portName); + } + + public static UUID generateConsumerUUID(String virtualHostName, String queueName, String connectionRemoteAddress, String channelNumber, String consumerName) + { + return createUUID(Consumer.class.getName(), virtualHostName, queueName, connectionRemoteAddress, channelNumber, consumerName); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/User.java b/java/broker/src/main/java/org/apache/qpid/server/model/User.java new file mode 100644 index 0000000000..d97bf46d31 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java new file mode 100644 index 0000000000..24a3d43386 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHost.java @@ -0,0 +1,152 @@ +/* + * + * 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; + + 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/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java b/java/broker/src/main/java/org/apache/qpid/server/model/VirtualHostAlias.java new file mode 100644 index 0000000000..31403d78e5 --- /dev/null +++ b/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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java new file mode 100644 index 0000000000..7d6aa9b2cb --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AbstractAdapter.java @@ -0,0 +1,283 @@ +/* + * + * 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(UUID id) + { + _id = id; + } + + 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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java new file mode 100644 index 0000000000..8c2bc98ba7 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/AuthenticationProviderAdapter.java @@ -0,0 +1,488 @@ +/* + * + * 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) + { + super(UUIDGenerator.generateRandomUUID()); + _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(UUIDGenerator.generateUserUUID(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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java new file mode 100644 index 0000000000..abd3160686 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BindingAdapter.java @@ -0,0 +1,232 @@ +/* + * + * 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.IllegalStateTransitionException; +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(binding.getId()); + _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; + } + + @Override + public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + if (desiredState == State.DELETED) + { + delete(); + return State.DELETED; + } + return super.setDesiredState(currentState, desiredState); + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java new file mode 100644 index 0000000000..f1cce2d45c --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/BrokerAdapter.java @@ -0,0 +1,494 @@ +/* + * + * 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.List; +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.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.UUIDGenerator; +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 Collection<HTTPPortAdapter> _httpManagementPorts; + + private final Map<AuthenticationManager, AuthenticationProviderAdapter> _authManagerAdapters = + new HashMap<AuthenticationManager, AuthenticationProviderAdapter>(); + + + public BrokerAdapter(final IApplicationRegistry instance) + { + super(UUIDGenerator.generateRandomUUID()); + _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() || _applicationRegistry.useHTTPSManagement()) + { + ArrayList<HTTPPortAdapter> httpPorts = new ArrayList<HTTPPortAdapter>(); + if (_applicationRegistry.useHTTPManagement()) + { + httpPorts.add(new HTTPPortAdapter(this, _applicationRegistry.getHTTPManagementPort())); + } + if (_applicationRegistry.useHTTPSManagement()) + { + httpPorts.add(new HTTPPortAdapter(this, _applicationRegistry.getHTTPSManagementPort(), Protocol.HTTPS, Transport.SSL)); + } + _httpManagementPorts = Collections.unmodifiableCollection(httpPorts); + } + } + } + + public Collection<Port> getPorts() + { + synchronized (_portAdapters) + { + final ArrayList<Port> ports = new ArrayList<Port>(_portAdapters.values()); + if(_httpManagementPorts != null) + { + ports.addAll(_httpManagementPorts); + } + 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(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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java new file mode 100644 index 0000000000..5439f6a560 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java @@ -0,0 +1,313 @@ +/* + * + * 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.model.UUIDGenerator; +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) + { + super(UUIDGenerator.generateRandomUUID()); + _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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ConsumerAdapter.java new file mode 100644 index 0000000000..031d518670 --- /dev/null +++ b/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.model.UUIDGenerator; +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(UUIDGenerator.generateConsumerUUID(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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java new file mode 100644 index 0000000000..df0f29fbc3 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/ExchangeAdapter.java @@ -0,0 +1,437 @@ +/* + * + * 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.protocol.AMQConstant; +import org.apache.qpid.server.binding.Binding; +import org.apache.qpid.server.exchange.ExchangeRegistry; +import org.apache.qpid.server.exchange.ExchangeType; +import org.apache.qpid.server.model.ConfiguredObject; +import org.apache.qpid.server.model.Exchange; +import org.apache.qpid.server.model.IllegalStateTransitionException; +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.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(exchange.getId()); + _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))) + { + virtualHost.getBindingFactory().replaceBinding(oldBinding.getId(), 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 + { + ExchangeRegistry exchangeRegistry = _vhost.getVirtualHost().getExchangeRegistry(); + if (exchangeRegistry.isReservedExchangeName(getName())) + { + throw new UnsupportedOperationException("'" + getName() + "' is a reserved exchange and can't be deleted"); + } + + if(_exchange.hasReferrers()) + { + throw new AMQException( AMQConstant.NOT_ALLOWED, "Exchange in use as an alternate exchange", null); + } + + synchronized(exchangeRegistry) + { + exchangeRegistry.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; + } + + @Override + public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + if (desiredState == State.DELETED) + { + delete(); + return State.DELETED; + } + return super.setDesiredState(currentState, desiredState); + } + + 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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java new file mode 100644 index 0000000000..823d27160b --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/HTTPPortAdapter.java @@ -0,0 +1,273 @@ +/* + * + * 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.UUIDGenerator; +import org.apache.qpid.server.model.VirtualHostAlias; + +public class HTTPPortAdapter extends AbstractAdapter implements Port +{ + private final BrokerAdapter _broker; + private final int _port; + private final Protocol _protocol; + private final Transport _transport; + + public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port) + { + this(brokerAdapter, port, Protocol.HTTP, Transport.TCP); + } + + public HTTPPortAdapter(BrokerAdapter brokerAdapter, int port, Protocol protocol, Transport transport) + { + super(UUIDGenerator.generateRandomUUID()); + _broker = brokerAdapter; + _port = port; + _protocol = protocol; + _transport = transport; + } + + @Override + public String getBindingAddress() + { + return "0.0.0.0"; + } + + @Override + public int getPort() + { + return _port; + } + + @Override + public Collection<Transport> getTransports() + { + return Collections.singleton(_transport); + } + + @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); + } + + @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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.java new file mode 100644 index 0000000000..03fdbd1e85 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/NoStatistics.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.adapter; + +import org.apache.qpid.server.model.Statistics; + +import java.util.Collection; +import java.util.Collections; + +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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java new file mode 100644 index 0000000000..7653fcc9b9 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java @@ -0,0 +1,320 @@ +/* + * + * 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.UUIDGenerator; +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) + { + super(UUIDGenerator.generateRandomUUID()); + _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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java new file mode 100644 index 0000000000..78f6d38d93 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/QueueAdapter.java @@ -0,0 +1,726 @@ +/* + * + * 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.IllegalStateTransitionException; +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-age"); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.ALERT_THRESHOLD_MESSAGE_SIZE, "x-qpid-maximum-message-size"); + 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, AMQQueueFactory.QPID_QUEUE_SORT_KEY); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_LAST_VALUE_QUEUE_KEY); + QueueAdapter.ATTRIBUTE_MAPPINGS.put(Queue.PRIORITIES, AMQQueueFactory.X_QPID_PRIORITIES); + } + + 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(queue.getId()); + _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 + { + QueueRegistry queueRegistry = _queue.getVirtualHost().getQueueRegistry(); + synchronized(queueRegistry) + { + _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(); + } + else if(PRIORITIES.equals(name)) + { + if(_queue instanceof AMQPriorityQueue) + { + return ((AMQPriorityQueue)_queue).getPriorities(); + } + } + 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); + } + } + + @Override + public State setDesiredState(State currentState, State desiredState) throws IllegalStateTransitionException, + AccessControlException + { + if (desiredState == State.DELETED) + { + delete(); + return State.DELETED; + } + return super.setDesiredState(currentState, desiredState); + } + +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java new file mode 100644 index 0000000000..d802697d67 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/SessionAdapter.java @@ -0,0 +1,240 @@ +/* + * + * 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.model.UUIDGenerator; +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) + { + super(UUIDGenerator.generateRandomUUID()); + _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)) + { + return _session.getConsumerCount(); + } + else if(name.equals(LOCAL_TRANSACTION_BEGINS)) + { + return _session.getTxnStart(); + } + else if(name.equals(LOCAL_TRANSACTION_OPEN)) + { + long open = _session.getTxnStart() - (_session.getTxnCommits() + _session.getTxnRejects()); + return (Boolean) (open > 0l); + } + else if(name.equals(LOCAL_TRANSACTION_ROLLBACKS)) + { + return _session.getTxnRejects(); + } + 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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java new file mode 100644 index 0000000000..28c46a0339 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/StatisticsAdapter.java @@ -0,0 +1,67 @@ +/* + * 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.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; + +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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java new file mode 100644 index 0000000000..35838e51d2 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAdapter.java @@ -0,0 +1,892 @@ +/* + * + * 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.QueueType; +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.getId()); + _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 + { + checkVHostStateIsActive(); + + try + { + ExchangeRegistry exchangeRegistry = _virtualHost.getExchangeRegistry(); + if (exchangeRegistry.isReservedExchangeName(name)) + { + throw new UnsupportedOperationException("'" + name + "' is a reserved exchange name"); + } + synchronized(exchangeRegistry) + { + org.apache.qpid.server.exchange.Exchange exchange = exchangeRegistry.getExchange(name); + if (exchange != null) + { + throw new IllegalArgumentException("Exchange with name '" + name + "' already exists"); + } + 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); + + if (attributes.containsKey(Queue.TYPE)) + { + String typeAttribute = getStringAttribute(Queue.TYPE, attributes, null); + QueueType queueType = null; + try + { + queueType = QueueType.valueOf(typeAttribute.toUpperCase()); + } + catch(Exception e) + { + throw new IllegalArgumentException("Unsupported queue type :" + typeAttribute); + } + if (queueType == QueueType.LVQ && attributes.get(Queue.LVQ_KEY) == null) + { + attributes.put(Queue.LVQ_KEY, AMQQueueFactory.QPID_LVQ_KEY); + } + else if (queueType == QueueType.PRIORITY && attributes.get(Queue.PRIORITIES) == null) + { + attributes.put(Queue.PRIORITIES, 10); + } + else if (queueType == QueueType.SORTED && attributes.get(Queue.SORT_KEY) == null) + { + throw new IllegalArgumentException("Sort key is not specified for sorted queue"); + } + } + 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 + { + checkVHostStateIsActive(); + + String owner = null; + if(exclusive) + { + Set<Principal> principals = + SecurityManager.getThreadSubject().getPrincipals(); + if(principals != null && !principals.isEmpty()) + { + owner = principals.iterator().next().getName(); + } + } + try + { + QueueRegistry queueRegistry = _virtualHost.getQueueRegistry(); + synchronized (queueRegistry) + { + if(_virtualHost.getQueueRegistry().getQueue(name)!=null) + { + throw new IllegalArgumentException("Queue with name "+name+" already exists"); + } + AMQQueue queue = + AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(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 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 void checkVHostStateIsActive() + { + if (!org.apache.qpid.server.virtualhost.State.ACTIVE.equals(_virtualHost.getState())) + { + throw new IllegalStateException("The virtual hosts state of " + _virtualHost.getState() + + " does not permit this operation."); + } + } + + + 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/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java new file mode 100644 index 0000000000..367d1ff518 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/model/adapter/VirtualHostAliasAdapter.java @@ -0,0 +1,143 @@ +/* + * + * 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.UUIDGenerator; +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(UUIDGenerator.generateVhostAliasUUID(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/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java index cfdcf7fb43..a68ac5439c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java +++ b/java/broker/src/main/java/org/apache/qpid/server/output/ProtocolOutputConverterImpl.java @@ -1,4 +1,3 @@ -package org.apache.qpid.server.output; /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -19,6 +18,7 @@ package org.apache.qpid.server.output; * under the License. * */ +package org.apache.qpid.server.output; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQBody; diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties index badeffca05..6479546355 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties +++ b/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,41 +58,66 @@ 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.server.ssl=7.6.3 +org.eclipse.jetty.server.nio=7.6.3 +org.eclipse.jetty.servlet=7.6.3 +org.eclipse.jetty.util.ssl=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.log4j=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 org.apache.qpid.server.queue=0.0.0 +org.apache.qpid.server.subscription=0.0.0 org.apache.qpid.server.registry=0.0.0 org.apache.qpid.server.security=0.0.0 org.apache.qpid.server.security.access=0.0.0 @@ -88,7 +125,11 @@ 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/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java index 407ce57ad6..74abbccd2b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java @@ -18,17 +18,20 @@ */ package org.apache.qpid.server.plugins; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; import org.apache.commons.configuration.ConfigurationException; import org.apache.felix.framework.Felix; import org.apache.felix.framework.util.StringMap; import org.apache.log4j.Logger; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.framework.BundleException; -import org.osgi.framework.Version; -import org.osgi.framework.launch.Framework; -import org.osgi.util.tracker.ServiceTracker; - import org.apache.qpid.common.Closeable; import org.apache.qpid.common.QpidProperties; import org.apache.qpid.server.configuration.TopicConfiguration; @@ -40,24 +43,23 @@ import org.apache.qpid.server.exchange.ExchangeType; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SecurityPluginFactory; import org.apache.qpid.server.security.access.plugins.LegacyAccess; +import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory; +import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager; +import org.apache.qpid.server.security.auth.manager.KerberosAuthenticationManager; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; +import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager; import org.apache.qpid.server.virtualhost.plugins.SlowConsumerDetection; import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory; import org.apache.qpid.server.virtualhost.plugins.policies.TopicDeletePolicy; import org.apache.qpid.slowconsumerdetection.policies.SlowConsumerPolicyPluginFactory; import org.apache.qpid.util.FileUtils; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; +import org.osgi.framework.Version; +import org.osgi.framework.launch.Framework; +import org.osgi.util.tracker.ServiceTracker; import static org.apache.felix.framework.util.FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP; import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_ACTION_PROPERY; @@ -100,18 +102,18 @@ public class PluginManager implements Closeable /** The default name of the OSGI system package list. */ private static final String DEFAULT_RESOURCE_NAME = "org/apache/qpid/server/plugins/OsgiSystemPackages.properties"; - + /** The name of the override system property that holds the name of the OSGI system package list. */ private static final String FILE_PROPERTY = "qpid.osgisystempackages.properties"; - + private static final String OSGI_SYSTEM_PACKAGES; - - static + + static { final String filename = System.getProperty(FILE_PROPERTY); final InputStream is = FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME, PluginManager.class.getClassLoader()); - + try { Version qpidReleaseVersion; @@ -123,14 +125,14 @@ public class PluginManager implements Closeable { qpidReleaseVersion = null; } - + final Properties p = new Properties(); p.load(is); - + final OsgiSystemPackageUtil osgiSystemPackageUtil = new OsgiSystemPackageUtil(qpidReleaseVersion, (Map)p); - + OSGI_SYSTEM_PACKAGES = osgiSystemPackageUtil.getFormattedSystemPackageString(); - + _logger.debug("List of OSGi system packages to be added: " + OSGI_SYSTEM_PACKAGES); } catch (IOException e) @@ -139,8 +141,8 @@ public class PluginManager implements Closeable throw new ExceptionInInitializerError(e); } } - - + + public PluginManager(String pluginPath, String cachePath, BundleContext bundleContext) throws Exception { // Store all non-OSGi plugins @@ -156,7 +158,12 @@ public class PluginManager implements Closeable new SlowConsumerDetectionConfigurationFactory(), new SlowConsumerDetectionPolicyConfigurationFactory(), new SlowConsumerDetectionQueueConfigurationFactory(), - PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY)) + PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY, + AnonymousAuthenticationManager.AnonymousAuthenticationManagerConfiguration.FACTORY, + KerberosAuthenticationManager.KerberosAuthenticationManagerConfiguration.FACTORY, + SimpleLDAPAuthenticationManager.SimpleLDAPAuthenticationManagerConfiguration.FACTORY, + ExternalAuthenticationManager.ExternalAuthenticationManagerConfiguration.FACTORY + )) { _configPlugins.put(configFactory.getParentPaths(), configFactory); } @@ -172,7 +179,9 @@ public class PluginManager implements Closeable } for (AuthenticationManagerPluginFactory<? extends Plugin> pluginFactory : Arrays.asList( - PrincipalDatabaseAuthenticationManager.FACTORY)) + PrincipalDatabaseAuthenticationManager.FACTORY, AnonymousAuthenticationManager.FACTORY, + KerberosAuthenticationManager.FACTORY, SimpleLDAPAuthenticationManager.FACTORY, + ExternalAuthenticationManager.FACTORY)) { _authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory); } @@ -265,7 +274,7 @@ public class PluginManager implements Closeable _virtualHostTracker = new ServiceTracker(bundleContext, VirtualHostPluginFactory.class.getName(), null); _virtualHostTracker.open(); _trackers.add(_virtualHostTracker); - + _policyTracker = new ServiceTracker(bundleContext, SlowConsumerPolicyPluginFactory.class.getName(), null); _policyTracker.open(); _trackers.add(_policyTracker); @@ -278,9 +287,9 @@ public class PluginManager implements Closeable } private static <T> Map<String, T> getServices(ServiceTracker tracker) - { + { Map<String, T> services = new HashMap<String, T>(); - + if ((tracker != null) && (tracker.getServices() != null)) { for (Object service : tracker.getServices()) @@ -300,16 +309,16 @@ public class PluginManager implements Closeable } public static <T> Map<String, T> getServices(ServiceTracker tracker, Map<String, T> plugins) - { + { Map<String, T> services = getServices(tracker); services.putAll(plugins); return services; } public Map<List<String>, ConfigurationPluginFactory> getConfigurationPlugins() - { + { Map<List<String>, ConfigurationPluginFactory> services = new IdentityHashMap<List<String>, ConfigurationPluginFactory>(); - + if (_configTracker != null && _configTracker.getServices() != null) { for (Object service : _configTracker.getServices()) @@ -318,19 +327,19 @@ public class PluginManager implements Closeable services.put(factory.getParentPaths(), factory); } } - + services.putAll(_configPlugins); return services; } public Map<String, VirtualHostPluginFactory> getVirtualHostPlugins() - { + { return getServices(_virtualHostTracker, _vhostPlugins); } public Map<String, SlowConsumerPolicyPluginFactory> getSlowConsumerPlugins() - { + { return getServices(_policyTracker, _policyPlugins); } @@ -338,7 +347,7 @@ public class PluginManager implements Closeable { return getServices(_exchangeTracker); } - + public Map<String, SecurityPluginFactory> getSecurityPlugins() { return getServices(_securityTracker, _securityPlugins); diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java index 5af3899890..36fafba1cd 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java @@ -31,24 +31,21 @@ import java.util.UUID; public interface AMQConnectionModel extends StatisticsGatherer { /** - * get a unique id for this connection. - * - * @return a {@link UUID} representing the connection - */ - public UUID getId(); - - /** * Close the underlying Connection - * + * * @param cause * @param message * @throws org.apache.qpid.AMQException */ public void close(AMQConstant cause, String message) throws AMQException; + public void block(); + + public void unblock(); + /** * Close the given requested Session - * + * * @param session * @param cause * @param message @@ -57,10 +54,10 @@ public interface AMQConnectionModel extends StatisticsGatherer public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException; public long getConnectionId(); - + /** * Get a list of all sessions using this connection. - * + * * @return a list of {@link AMQSessionModel}s */ public List<AMQSessionModel> getSessionModels(); @@ -73,4 +70,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/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java index b750b29952..1e649c3cb7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java @@ -20,8 +20,26 @@ */ package org.apache.qpid.server.protocol; -import org.apache.log4j.Logger; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import javax.security.auth.Subject; +import javax.security.sasl.SaslServer; +import org.apache.log4j.Logger; import org.apache.qpid.AMQChannelException; import org.apache.qpid.AMQConnectionException; import org.apache.qpid.AMQException; @@ -46,13 +64,10 @@ 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; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; import org.apache.qpid.server.state.AMQState; import org.apache.qpid.server.state.AMQStateManager; import org.apache.qpid.server.stats.StatisticsCounter; @@ -66,25 +81,7 @@ import org.apache.qpid.transport.TransportException; import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.util.BytesDataOutput; -import javax.management.JMException; -import javax.security.auth.Subject; -import javax.security.sasl.SaslServer; -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.SocketAddress; -import java.nio.ByteBuffer; -import java.security.Principal; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; -import java.util.concurrent.atomic.AtomicBoolean; - -public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig +public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSession, ConnectionConfig { private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class); @@ -109,8 +106,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr private AMQCodecFactory _codecFactory; - private AMQProtocolSessionMBean _managedObject; - private SaslServer _saslServer; private Object _lastReceived; @@ -147,12 +142,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr private long _maxFrameSize; private final AtomicBoolean _closing = new AtomicBoolean(false); - private final UUID _id; + private final UUID _qmfId; 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; @@ -160,14 +153,13 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr private volatile boolean _deferFlush; private long _lastReceivedTime; + private boolean _blocking; - public ManagedObject getManagedObject() - { - return _managedObject; - } + private final Lock _receivedLock; public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkConnection network, final long connectionId) { + _receivedLock = new ReentrantLock(); _stateManager = new AMQStateManager(virtualHostRegistry, this); _codecFactory = new AMQCodecFactory(true, this); @@ -179,12 +171,12 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _logSubject = new ConnectionLogSubject(this); _configStore = virtualHostRegistry.getConfigStore(); - _id = _configStore.createId(); + _qmfId = _configStore.createId(); _actor.message(ConnectionMessages.OPEN(null, null, null, false, false, false)); - _registry = virtualHostRegistry.getApplicationRegistry(); initialiseStatistics(); + } public void setNetworkConnection(NetworkConnection network) @@ -198,11 +190,6 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _sender = sender; } - private AMQProtocolSessionMBean createMBean() throws JMException - { - return new AMQProtocolSessionMBean(this); - } - public long getSessionID() { return _connectionID; @@ -244,6 +231,8 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr final long arrivalTime = System.currentTimeMillis(); _lastReceivedTime = arrivalTime; _lastIoTime = arrivalTime; + + _receivedLock.lock(); try { final ArrayList<AMQDataBlock> dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg); @@ -268,6 +257,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr _logger.error("Unexpected exception when processing datablock", e); closeProtocolSession(); } + finally + { + _receivedLock.unlock(); + } } private void receiveComplete() @@ -374,7 +367,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr // This sets the protocol version (and hence framing classes) for this session. setProtocolVersion(pv); - String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager().getMechanisms(); + String mechanisms = ApplicationRegistry.getInstance().getAuthenticationManager(getLocalAddress()).getMechanisms(); String locales = "en_US"; @@ -576,7 +569,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr public List<AMQChannel> getChannels() { - return new ArrayList<AMQChannel>(_channelMap.values()); + synchronized (_channelMap) + { + return new ArrayList<AMQChannel>(_channelMap.values()); + } } public AMQChannel getAndAssertChannel(int channelId) throws AMQException @@ -633,24 +629,21 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr } else { - _channelMap.put(channel.getChannelId(), channel); + synchronized (_channelMap) + { + _channelMap.put(channel.getChannelId(), channel); + + if(_blocking) + { + channel.block(); + } + } } if (((channelId & CHANNEL_CACHE_SIZE) == channelId)) { _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() @@ -735,10 +728,14 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr */ public void removeChannel(int channelId) { - _channelMap.remove(channelId); - if ((channelId & CHANNEL_CACHE_SIZE) == channelId) + synchronized (_channelMap) { - _cachedChannels[channelId] = null; + _channelMap.remove(channelId); + + if ((channelId & CHANNEL_CACHE_SIZE) == channelId) + { + _cachedChannels[channelId] = null; + } } } @@ -763,12 +760,14 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr */ private void closeAllChannels() throws AMQException { - for (AMQChannel channel : _channelMap.values()) + for (AMQChannel channel : getChannels()) { channel.close(); } - - _channelMap.clear(); + synchronized (_channelMap) + { + _channelMap.clear(); + } for (int i = 0; i <= CHANNEL_CACHE_SIZE; i++) { _cachedChannels[i] = null; @@ -780,6 +779,9 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr { if(_closing.compareAndSet(false,true)) { + // force sync of outstanding async work + receiveComplete(); + // REMOVE THIS SHOULD NOT BE HERE. if (CurrentActor.get() == null) { @@ -796,13 +798,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); @@ -835,7 +830,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr } } - public void closeConnection(int channelId, AMQConnectionException e) throws AMQException + private void closeConnection(int channelId, AMQConnectionException e) throws AMQException { try { @@ -846,12 +841,18 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr markChannelAwaitingCloseOk(channelId); closeSession(); - _stateManager.changeState(AMQState.CONNECTION_CLOSING); - writeFrame(e.getCloseFrame(channelId)); } finally { - closeProtocolSession(); + try + { + _stateManager.changeState(AMQState.CONNECTION_CLOSING); + writeFrame(e.getCloseFrame(channelId)); + } + finally + { + closeProtocolSession(); + } } @@ -983,16 +984,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) @@ -1026,7 +1017,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr public Principal getAuthorizedPrincipal() { - return _authorizedSubject == null ? null : UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject); + return _authorizedSubject == null ? null : _authorizedSubject.getPrincipals().iterator().next(); } public SocketAddress getRemoteAddress() @@ -1039,6 +1030,11 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr return _network.getLocalAddress(); } + public Principal getPeerPrincipal() + { + return _network.getPeerPrincipal(); + } + public MethodRegistry getMethodRegistry() { return _methodRegistry; @@ -1144,6 +1140,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; @@ -1199,9 +1205,10 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr return false; } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public long getConnectionId() @@ -1337,6 +1344,36 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr (Throwable) null)); } + public void block() + { + synchronized (_channelMap) + { + if(!_blocking) + { + _blocking = true; + for(AMQChannel channel : _channelMap.values()) + { + channel.block(); + } + } + } + } + + public void unblock() + { + synchronized (_channelMap) + { + if(_blocking) + { + _blocking = false; + for(AMQChannel channel : _channelMap.values()) + { + channel.unblock(); + } + } + } + } + public boolean isClosed() { return _closed; @@ -1344,12 +1381,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() @@ -1359,21 +1391,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); } @@ -1407,29 +1433,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) @@ -1466,4 +1489,9 @@ public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQPr { return _reference; } + + public Lock getReceivedLock() + { + return _receivedLock; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java index 6cd5b21f89..ba806c04bd 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java @@ -20,12 +20,14 @@ */ package org.apache.qpid.server.protocol; +import java.net.SocketAddress; +import java.security.Principal; import java.util.List; +import java.util.concurrent.locks.Lock; import javax.security.auth.Subject; import javax.security.sasl.SaslServer; -import org.apache.qpid.AMQConnectionException; import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.framing.FieldTable; @@ -60,6 +62,13 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth long getLastReceivedTime(); + /** + * Return the local socket address for the connection + * + * @return the socket address + */ + SocketAddress getLocalAddress(); + public static interface Task { public void doTask(AMQProtocolSession session) throws AMQException; @@ -145,10 +154,6 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth void closeProtocolSession(); - /** This must be called to close the session in order to free up any resources managed by the session. */ - void closeConnection(int channelId, AMQConnectionException e) throws AMQException; - - /** @return a key that uniquely identifies this session */ Object getKey(); @@ -210,4 +215,7 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Auth void mgmtCloseChannel(int channelId); + public Principal getPeerPrincipal(); + + Lock getReceivedLock(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java deleted file mode 100644 index e70720600e..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java index fa171815ca..a8f62b0fa2 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java @@ -37,26 +37,26 @@ import org.apache.qpid.server.queue.SimpleAMQQueue; public interface AMQSessionModel extends Comparable<AMQSessionModel> { /** Unique session ID across entire broker*/ - public UUID getId(); + public UUID getQMFId(); public AMQConnectionModel getConnectionModel(); public String getClientID(); - + public void close() throws AMQException; public LogSubject getLogSubject(); - + /** * This method is called from the housekeeping thread to check the status of * transactions on this session and react appropriately. - * + * * If a transaction is open for too long or idle for too long then a warning * 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. - * + * from the time the transaction was started. An idle transaction is one that + * 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 * @param idleWarn time in milliseconds before alerting on idle transaction @@ -68,6 +68,22 @@ public interface AMQSessionModel extends Comparable<AMQSessionModel> void unblock(AMQQueue queue); + void block(); + + void unblock(); + + boolean getBlocking(); boolean onSameConnection(InboundMessage inbound); + + int getUnacknowledgedMessageCount(); + + Long getTxnCount(); + Long getTxnStart(); + Long getTxnCommits(); + Long getTxnRejects(); + + int getChannelId(); + + int getConsumerCount(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 652ffee004..5c92aa95b6 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -302,7 +302,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public ServerProtocolEngine getProtocolEngine() { final ConnectionDelegate connDelegate = - new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn); + new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn, _appRegistry.getAuthenticationManager(getLocalAddress())); ServerConnection conn = new ServerConnection(_id); conn.setConnectionDelegate(connDelegate); diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java index 182ef1ed82..fd6e9300ec 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java @@ -47,7 +47,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol private long _readBytes; private long _writtenBytes; private ServerConnection _connection; - private final UUID _id; + private final UUID _qmfId; private final IApplicationRegistry _appRegistry; private long _createTime = System.currentTimeMillis(); @@ -59,7 +59,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol _connection = conn; _connection.setConnectionConfig(this); - _id = appRegistry.getConfigStore().createId(); + _qmfId = appRegistry.getConfigStore().createId(); _appRegistry = appRegistry; if(network != null) @@ -88,7 +88,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol _network = network; _connection.setSender(new Disassembler(sender, MAX_FRAME_SIZE)); - + _connection.setPeerPrincipal(_network.getPeerPrincipal()); // FIXME Two log messages to maintain compatibility with earlier protocol versions _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, null, false, false, false)); _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", null, false, true, false)); @@ -180,9 +180,10 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol return _appRegistry.getConfigStore(); } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public ConnectionConfigType getConfigType() diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java index f31ad5052b..e6282315c6 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0.java @@ -26,12 +26,13 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; import java.util.logging.Level; import java.util.logging.Logger; -import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; import org.apache.qpid.amqp_1_0.codec.FrameWriter; import org.apache.qpid.amqp_1_0.framing.AMQFrame; import org.apache.qpid.amqp_1_0.framing.FrameHandler; import org.apache.qpid.amqp_1_0.framing.OversizeFrameException; -import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource; +import org.apache.qpid.amqp_1_0.transport.SaslServerProvider; import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; import org.apache.qpid.amqp_1_0.transport.Container; import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; @@ -95,7 +96,7 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa } private State _state = State.A; - + public ProtocolEngine_1_0_0(final IApplicationRegistry appRegistry, long id) @@ -143,8 +144,9 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa Container container = new Container(_appRegistry.getBrokerId().toString()); - _conn = new ConnectionEndpoint(container,asCallbackHandlerSource(_appRegistry.getAuthenticationManager())); - _conn.setConnectionEventListener(new Connection_1_0(_appRegistry)); + _conn = new ConnectionEndpoint(container, asSaslServerProvider(_appRegistry.getAuthenticationManager( + getLocalAddress()))); + _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId)); _conn.setFrameOutputHandler(this); _conn.setRemoteAddress(_network.getRemoteAddress()); @@ -155,14 +157,14 @@ public class ProtocolEngine_1_0_0 implements ServerProtocolEngine, FrameOutputHa _sender.flush(); } - private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager) + private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager) { - return new CallbackHandlerSource() + return new SaslServerProvider() { @Override - public CallbackHandler getHandler(String mechanism) + public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException { - return authenticationManager.getHandler(mechanism); + return authenticationManager.createSaslServer(mechanism, fqdn, null); } }; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java index ffd5e750b4..a48441bf30 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_1_0_0_SASL.java @@ -26,13 +26,14 @@ import java.nio.ByteBuffer; import java.util.UUID; import java.util.logging.Level; import java.util.logging.Logger; -import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; import org.apache.qpid.amqp_1_0.codec.FrameWriter; import org.apache.qpid.amqp_1_0.codec.ProtocolHandler; import org.apache.qpid.amqp_1_0.framing.AMQFrame; import org.apache.qpid.amqp_1_0.framing.OversizeFrameException; import org.apache.qpid.amqp_1_0.framing.SASLFrameHandler; -import org.apache.qpid.amqp_1_0.transport.CallbackHandlerSource; +import org.apache.qpid.amqp_1_0.transport.SaslServerProvider; import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; import org.apache.qpid.amqp_1_0.transport.Container; import org.apache.qpid.amqp_1_0.transport.FrameOutputHandler; @@ -57,7 +58,7 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut private long _createTime = System.currentTimeMillis(); private ConnectionEndpoint _conn; private long _connectionId; - + private static final ByteBuffer HEADER = ByteBuffer.wrap(new byte[] { @@ -163,9 +164,9 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut Container container = new Container(_appRegistry.getBrokerId().toString()); - _conn = new ConnectionEndpoint(container, asCallbackHandlerSource(ApplicationRegistry.getInstance() - .getAuthenticationManager())); - _conn.setConnectionEventListener(new Connection_1_0(_appRegistry)); + _conn = new ConnectionEndpoint(container, asSaslServerProvider(ApplicationRegistry.getInstance() + .getAuthenticationManager(getLocalAddress()))); + _conn.setConnectionEventListener(new Connection_1_0(_appRegistry, _conn, _connectionId)); _conn.setRemoteAddress(getRemoteAddress()); @@ -200,14 +201,14 @@ public class ProtocolEngine_1_0_0_SASL implements ServerProtocolEngine, FrameOut } - private CallbackHandlerSource asCallbackHandlerSource(final AuthenticationManager authenticationManager) + private SaslServerProvider asSaslServerProvider(final AuthenticationManager authenticationManager) { - return new CallbackHandlerSource() + return new SaslServerProvider() { @Override - public CallbackHandler getHandler(String mechanism) + public SaslServer getSaslServer(String mechanism, String fqdn) throws SaslException { - return authenticationManager.getHandler(mechanism); + return authenticationManager.createSaslServer(mechanism, fqdn, null); } }; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java index 318a240b27..f429d8ba9f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Connection_1_0.java @@ -20,21 +20,35 @@ */ package org.apache.qpid.server.protocol.v1_0; +import java.text.MessageFormat; +import java.util.Collection; +import org.apache.qpid.AMQException; +import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; import org.apache.qpid.amqp_1_0.transport.ConnectionEventListener; import org.apache.qpid.amqp_1_0.transport.SessionEndpoint; +import org.apache.qpid.protocol.AMQConstant; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT; + public class Connection_1_0 implements ConnectionEventListener { private IApplicationRegistry _appRegistry; private VirtualHost _vhost; + private final ConnectionEndpoint _conn; + private final long _connectionId; + private final Collection<Session_1_0> _sessions = Collections.synchronizedCollection(new ArrayList<Session_1_0>()); public static interface Task @@ -48,18 +62,27 @@ public class Connection_1_0 implements ConnectionEventListener - public Connection_1_0(IApplicationRegistry appRegistry) + public Connection_1_0(IApplicationRegistry appRegistry, ConnectionEndpoint conn, long connectionId) { _appRegistry = appRegistry; _vhost = _appRegistry.getVirtualHostRegistry().getDefaultVirtualHost(); + _conn = conn; + _connectionId = connectionId; + _vhost.getConnectionRegistry().registerConnection(_model); + } public void remoteSessionCreation(SessionEndpoint endpoint) { Session_1_0 session = new Session_1_0(_vhost, _appRegistry, this); + _sessions.add(session); endpoint.setSessionEventListener(session); } + void sessionEnded(Session_1_0 session) + { + _sessions.remove(session); + } void removeConnectionCloseTask(final Task task) { @@ -86,6 +109,8 @@ public class Connection_1_0 implements ConnectionEventListener { _closeTasks.clear(); } + _vhost.getConnectionRegistry().deregisterConnection(_model); + } @@ -94,5 +119,174 @@ public class Connection_1_0 implements ConnectionEventListener closeReceived(); } + private final AMQConnectionModel _model = new AMQConnectionModel() + { + private final StatisticsCounter _messageDeliveryStatistics = new StatisticsCounter(); + private final StatisticsCounter _messageReceiptStatistics = new StatisticsCounter(); + private final StatisticsCounter _dataDeliveryStatistics = new StatisticsCounter(); + private final StatisticsCounter _dataReceiptStatistics = new StatisticsCounter(); + + private final LogSubject _logSubject = new LogSubject() + { + @Override + public String toLogString() + { + return "[" + + MessageFormat.format(CONNECTION_FORMAT, + getConnectionId(), + getClientId(), + getRemoteAddressString(), + _vhost.getName()) + + "] "; + + } + }; + + @Override + public void close(AMQConstant cause, String message) throws AMQException + { + // TODO + } + + @Override + public void block() + { + // TODO + } + + @Override + public void unblock() + { + // TODO + } + + @Override + public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException + { + // TODO + } + + @Override + public long getConnectionId() + { + return _connectionId; + } + + @Override + public List<AMQSessionModel> getSessionModels() + { + return new ArrayList<AMQSessionModel>(_sessions); + } + + @Override + public LogSubject getLogSubject() + { + return _logSubject; + } + + @Override + public String getUserName() + { + return getPrincipalAsString(); + } + + @Override + public boolean isSessionNameUnique(byte[] name) + { + return true; // TODO + } + + @Override + public String getRemoteAddressString() + { + return String.valueOf(_conn.getRemoteAddress()); + } + + @Override + public String getClientId() + { + return _conn.getRemoteContainerId(); + } + + @Override + public String getClientVersion() + { + return ""; //TODO + } + + @Override + public String getPrincipalAsString() + { + return String.valueOf(_conn.getUser()); + } + + @Override + public long getSessionCountLimit() + { + return 0; // TODO + } + + @Override + public long getLastIoTime() + { + return 0; // TODO + } + + @Override + public void initialiseStatistics() + { + // TODO + } + + @Override + public void registerMessageReceived(long messageSize, long timestamp) + { + // TODO + } + + @Override + public void registerMessageDelivered(long messageSize) + { + // TODO + } + + @Override + public StatisticsCounter getMessageDeliveryStatistics() + { + return _messageDeliveryStatistics; + } + + @Override + public StatisticsCounter getMessageReceiptStatistics() + { + return _messageReceiptStatistics; + } + + @Override + public StatisticsCounter getDataDeliveryStatistics() + { + return _dataDeliveryStatistics; + } + + @Override + public StatisticsCounter getDataReceiptStatistics() + { + return _dataReceiptStatistics; + } + + @Override + public void resetStatistics() + { + // TODO + } + + + }; + + AMQConnectionModel getModel() + { + return _model; + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java index 42eea05d37..0bb9a15968 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/LinkRegistry.java @@ -1,3 +1,23 @@ +/* + * + * 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.protocol.v1_0; import java.util.HashMap; diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java index 6da5081185..46b9682c74 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/ReceivingLinkAttachment.java @@ -1,3 +1,23 @@ +/* + * + * 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.protocol.v1_0; import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler; diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java index 9d7af24135..09a2ddea3a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLinkAttachment.java @@ -1,3 +1,23 @@ +/* + * + * 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.protocol.v1_0; import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler; diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java index b3e9a74d04..75235c7ef0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java @@ -200,7 +200,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS if(queue == null) { queue = AMQQueueFactory.createAMQQueueImpl( - UUIDGenerator.generateUUID(), + UUIDGenerator.generateQueueUUID(name, _vhost.getName()), name, isDurable, null, diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java index 48a551e42a..999ffc55e5 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Session_1_0.java @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.protocol.v1_0; +import java.text.MessageFormat; import org.apache.qpid.amqp_1_0.transport.LinkEndpoint; import org.apache.qpid.amqp_1_0.transport.ReceivingLinkEndpoint; import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint; @@ -35,18 +36,26 @@ import org.apache.qpid.amqp_1_0.type.transport.*; import org.apache.qpid.amqp_1_0.type.transport.Error; import org.apache.qpid.AMQException; import org.apache.qpid.AMQSecurityException; +import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.model.UUIDGenerator; +import org.apache.qpid.server.protocol.AMQConnectionModel; +import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.registry.IApplicationRegistry; +import org.apache.qpid.server.transport.ServerConnection; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.*; -public class Session_1_0 implements SessionEventListener +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; + +public class Session_1_0 implements SessionEventListener, AMQSessionModel, LogSubject { private static final Symbol LIFETIME_POLICY = Symbol.valueOf("lifetime-policy"); private IApplicationRegistry _appRegistry; @@ -56,6 +65,7 @@ public class Session_1_0 implements SessionEventListener private final LinkedHashMap<Integer, ServerTransaction> _openTransactions = new LinkedHashMap<Integer, ServerTransaction>(); private final Connection_1_0 _connection; + private UUID _id = UUID.randomUUID(); public Session_1_0(VirtualHost vhost, IApplicationRegistry appRegistry, final Connection_1_0 connection) @@ -319,7 +329,7 @@ public class Session_1_0 implements SessionEventListener ? null : (LifetimePolicy) properties.get(LIFETIME_POLICY); - final AMQQueue tempQueue = queue = AMQQueueFactory.createAMQQueueImpl( UUIDGenerator.generateUUID(), + final AMQQueue tempQueue = queue = AMQQueueFactory.createAMQQueueImpl( UUIDGenerator.generateQueueUUID(queueName, _vhost.getName()), queueName, false, // durable null, // owner @@ -405,6 +415,8 @@ public class Session_1_0 implements SessionEventListener iter.remove(); } + _connection.sessionEnded(this); + } Integer binaryToInteger(final Binary txnId) @@ -443,4 +455,153 @@ public class Session_1_0 implements SessionEventListener public void forceEnd() { } + + @Override + public UUID getQMFId() + { + return _id; + } + + @Override + public AMQConnectionModel getConnectionModel() + { + return _connection.getModel(); + } + + @Override + public String getClientID() + { + // TODO + return ""; + } + + @Override + public void close() throws AMQException + { + // TODO - required for AMQSessionModel / management initiated closing + } + + @Override + public LogSubject getLogSubject() + { + return this; + } + + @Override + public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException + { + // TODO - required for AMQSessionModel / long running transaction detection + } + + @Override + public void block(AMQQueue queue) + { + // TODO - required for AMQSessionModel / producer side flow control + } + + @Override + public void unblock(AMQQueue queue) + { + // TODO - required for AMQSessionModel / producer side flow control + } + + @Override + public void block() + { + // TODO - required for AMQSessionModel / producer side flow control + } + + @Override + public void unblock() + { + // TODO - required for AMQSessionModel / producer side flow control + } + + @Override + public boolean getBlocking() + { + // TODO + return false; + } + + @Override + public boolean onSameConnection(InboundMessage inbound) + { + // TODO + return false; + } + + @Override + public int getUnacknowledgedMessageCount() + { + // TODO + return 0; + } + + @Override + public Long getTxnCount() + { + // TODO + return 0l; + } + + @Override + public Long getTxnStart() + { + // TODO + return 0l; + } + + @Override + public Long getTxnCommits() + { + // TODO + return 0l; + } + + @Override + public Long getTxnRejects() + { + // TODO + return 0l; + } + + @Override + public int getChannelId() + { + // TODO + return 0; + } + + @Override + public int getConsumerCount() + { + // TODO + return 0; + } + + @Override + public int compareTo(AMQSessionModel o) + { + return getQMFId().compareTo(o.getQMFId()); + } + + + + public String toLogString() + { + long connectionId = getConnectionModel().getConnectionId(); + + String remoteAddress = getConnectionModel().getRemoteAddressString(); + + return "[" + + MessageFormat.format(CHANNEL_FORMAT, + connectionId, + getClientID(), + remoteAddress, + _vhost.getName(), // TODO - virtual host + 0) // TODO - channel) + + "] "; + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java index 08926d000d..8a3d3716c7 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/Subscription_1_0.java +++ b/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; @@ -66,7 +67,7 @@ class Subscription_1_0 implements Subscription private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this); private final long _id; private final boolean _acquires; - private AMQQueue.Context _queueContext; + private volatile AMQQueue.Context _queueContext; private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>(); private ReentrantLock _stateChangeLock = new ReentrantLock(); @@ -631,4 +632,46 @@ class Subscription_1_0 implements Subscription { _filters = filters; } + + @Override + public AMQSessionModel getSessionModel() + { + // TODO + return getSession(); + } + + @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/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java index c497cc5146..0fee4086b4 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/v1_0/UnsettledAction.java @@ -1,3 +1,23 @@ +/* + * + * 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.protocol.v1_0; import org.apache.qpid.amqp_1_0.type.DeliveryState; diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index e643338c3d..d3efd63ee0 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java index f2b7d7c56b..3a18fae2ec 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueFactory.java +++ b/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"; @@ -169,29 +171,7 @@ public class AMQQueueFactory }; /** - * Creates a new queue with a random id. - * - * @see #createAMQQueueImpl(UUID, String, boolean, String, boolean, boolean, VirtualHost, Map) - * @deprecated because only called from unit tests - * */ - @Deprecated - public static AMQQueue createAMQQueueImpl(AMQShortString name, - boolean durable, - AMQShortString owner, - boolean autoDelete, - boolean exclusive, - VirtualHost virtualHost, final FieldTable arguments) throws AMQException - { - return createAMQQueueImpl(UUIDGenerator.generateUUID(), - name == null ? null : name.toString(), - durable, - owner == null ? null : owner.toString(), - autoDelete, - exclusive, virtualHost, FieldTable.convertToMap(arguments)); - } - - /** - * @param id the id to use. If default then one is generated from queueName. TODO check correctness of calls that pass a null value. + * @param id the id to use. */ public static AMQQueue createAMQQueueImpl(UUID id, String queueName, @@ -300,7 +280,7 @@ public class AMQQueueFactory if(dlExchange == null) { - dlExchange = exchangeFactory.createExchange(UUIDGenerator.generateUUID(dlExchangeName, virtualHost.getName()), new AMQShortString(dlExchangeName), ExchangeDefaults.FANOUT_EXCHANGE_CLASS, true, false, 0); + dlExchange = exchangeFactory.createExchange(UUIDGenerator.generateExchangeUUID(dlExchangeName, virtualHost.getName()), new AMQShortString(dlExchangeName), ExchangeDefaults.FANOUT_EXCHANGE_CLASS, true, false, 0); exchangeRegistry.registerExchange(dlExchange); @@ -322,7 +302,7 @@ public class AMQQueueFactory args.put(X_QPID_DLQ_ENABLED, false); args.put(X_QPID_MAXIMUM_DELIVERY_COUNT, 0); - dlQueue = createAMQQueueImpl(UUIDGenerator.generateUUID(dlQueueName, virtualHost.getName()), dlQueueName, true, owner, false, exclusive, virtualHost, args); + dlQueue = createAMQQueueImpl(UUIDGenerator.generateQueueUUID(dlQueueName, virtualHost.getName()), dlQueueName, true, owner, false, exclusive, virtualHost, args); //enter the dlq in the persistent store virtualHost.getMessageStore().createQueue(dlQueue, FieldTable.convertToFieldTable(args)); @@ -350,42 +330,16 @@ 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()); + UUID id = UUIDGenerator.generateQueueUUID(queueName, host.getName()); AMQQueue q = createAMQQueueImpl(id, queueName, durable, owner, autodelete, exclusive, host, arguments); q.configure(config); return q; } - /** * Validates DLQ and DLE names * <p> @@ -475,4 +429,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/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java deleted file mode 100644 index b0d4cb3486..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java index 6a2e4f155d..53420ded9b 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ConflationQueueList.java @@ -24,17 +24,25 @@ package org.apache.qpid.server.queue; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.txn.AutoCommitTransaction; import org.apache.qpid.server.txn.ServerTransaction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.util.Collections; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicReference; public class ConflationQueueList extends SimpleQueueEntryList { + private static final Logger LOGGER = LoggerFactory.getLogger(ConflationQueueList.class); private final String _conflationKey; private final ConcurrentHashMap<Object, AtomicReference<QueueEntry>> _latestValuesMap = new ConcurrentHashMap<Object, AtomicReference<QueueEntry>>(); + private final QueueEntry _deleteInProgress = new SimpleQueueEntryImpl(this); + private final QueueEntry _newerEntryAlreadyBeenAndGone = new SimpleQueueEntryImpl(this); + public ConflationQueueList(AMQQueue queue, String conflationKey) { super(queue); @@ -52,48 +60,98 @@ public class ConflationQueueList extends SimpleQueueEntryList return new ConflationQueueEntry(this, message); } - + /** + * Updates the list using super.add and also updates {@link #_latestValuesMap} and discards entries as necessary. + */ @Override public ConflationQueueEntry add(final ServerMessage message) { - ConflationQueueEntry entry = (ConflationQueueEntry) (super.add(message)); - AtomicReference<QueueEntry> latestValueReference = null; + final ConflationQueueEntry addedEntry = (ConflationQueueEntry) (super.add(message)); - Object value = message.getMessageHeader().getHeader(_conflationKey); - if(value != null) + final Object keyValue = message.getMessageHeader().getHeader(_conflationKey); + if (keyValue != null) { - latestValueReference = _latestValuesMap.get(value); - if(latestValueReference == null) + if(LOGGER.isDebugEnabled()) { - _latestValuesMap.putIfAbsent(value, new AtomicReference<QueueEntry>(entry)); - latestValueReference = _latestValuesMap.get(value); + LOGGER.debug("Adding entry " + addedEntry + " for message " + message.getMessageNumber() + " with conflation key " + keyValue); } - QueueEntry oldEntry; + final AtomicReference<QueueEntry> referenceToEntry = new AtomicReference<QueueEntry>(addedEntry); + AtomicReference<QueueEntry> entryReferenceFromMap = null; + QueueEntry entryFromMap; + + // Iterate until we have got a valid atomic reference object and either the referent is newer than the current + // entry, or the current entry has replaced it in the reference. Note that the _deletedEntryPlaceholder is a special value + // indicating that the reference object is no longer valid (it is being removed from the map). + boolean keepTryingToUpdateEntryReference = true; do { - oldEntry = latestValueReference.get(); + do + { + entryReferenceFromMap = getOrPutIfAbsent(keyValue, referenceToEntry); + + // entryFromMap can be either an older entry, a newer entry (added recently by another thread), or addedEntry (if it's for a new key value) + entryFromMap = entryReferenceFromMap.get(); + } + while(entryFromMap == _deleteInProgress); + + boolean entryFromMapIsOlder = entryFromMap != _newerEntryAlreadyBeenAndGone && entryFromMap.compareTo(addedEntry) < 0; + + keepTryingToUpdateEntryReference = entryFromMapIsOlder + && !entryReferenceFromMap.compareAndSet(entryFromMap, addedEntry); } - while(oldEntry.compareTo(entry) < 0 && !latestValueReference.compareAndSet(oldEntry, entry)); + while(keepTryingToUpdateEntryReference); - if(oldEntry.compareTo(entry) < 0) + if (entryFromMap == _newerEntryAlreadyBeenAndGone) + { + discardEntry(addedEntry); + } + else if (entryFromMap.compareTo(addedEntry) > 0) { - // We replaced some other entry to become the newest value - if(oldEntry.acquire()) + if(LOGGER.isDebugEnabled()) { - discardEntry(oldEntry); + LOGGER.debug("New entry " + addedEntry.getEntryId() + " for message " + addedEntry.getMessage().getMessageNumber() + " being immediately discarded because a newer entry arrived. The newer entry is: " + entryFromMap + " for message " + entryFromMap.getMessage().getMessageNumber()); } + discardEntry(addedEntry); } - else if (oldEntry.compareTo(entry) > 0) + else if (entryFromMap.compareTo(addedEntry) < 0) { - // A newer entry came along - discardEntry(entry); - + if(LOGGER.isDebugEnabled()) + { + LOGGER.debug("Entry " + addedEntry + " for message " + addedEntry.getMessage().getMessageNumber() + " replacing older entry " + entryFromMap + " for message " + entryFromMap.getMessage().getMessageNumber()); + } + discardEntry(entryFromMap); } + + addedEntry.setLatestValueReference(entryReferenceFromMap); } - entry.setLatestValueReference(latestValueReference); - return entry; + return addedEntry; + } + + /** + * Returns: + * + * <ul> + * <li>the existing entry reference if the value already exists in the map, or</li> + * <li>referenceToValue if none exists, or</li> + * <li>a reference to {@link #_newerEntryAlreadyBeenAndGone} if another thread concurrently + * adds and removes during execution of this method.</li> + * </ul> + */ + private AtomicReference<QueueEntry> getOrPutIfAbsent(final Object key, final AtomicReference<QueueEntry> referenceToAddedValue) + { + AtomicReference<QueueEntry> latestValueReference = _latestValuesMap.putIfAbsent(key, referenceToAddedValue); + + if(latestValueReference == null) + { + latestValueReference = _latestValuesMap.get(key); + if(latestValueReference == null) + { + return new AtomicReference<QueueEntry>(_newerEntryAlreadyBeenAndGone); + } + } + return latestValueReference; } private void discardEntry(final QueueEntry entry) @@ -104,11 +162,13 @@ public class ConflationQueueList extends SimpleQueueEntryList txn.dequeue(entry.getQueue(),entry.getMessage(), new ServerTransaction.Action() { + @Override public void postCommit() { entry.discard(); } + @Override public void onRollback() { @@ -120,7 +180,6 @@ public class ConflationQueueList extends SimpleQueueEntryList private final class ConflationQueueEntry extends SimpleQueueEntryImpl { - private AtomicReference<QueueEntry> _latestValueReference; public ConflationQueueEntry(SimpleQueueEntryList queueEntryList, ServerMessage message) @@ -128,25 +187,56 @@ public class ConflationQueueList extends SimpleQueueEntryList super(queueEntryList, message); } - + @Override public void release() { super.release(); - if(_latestValueReference != null) + discardIfReleasedEntryIsNoLongerLatest(); + } + + @Override + public boolean delete() + { + if(super.delete()) { - if(_latestValueReference.get() != this) + if(_latestValueReference != null && _latestValueReference.compareAndSet(this, _deleteInProgress)) { - discardEntry(this); + Object key = getMessageHeader().getHeader(_conflationKey); + _latestValuesMap.remove(key,_latestValueReference); } + return true; + } + else + { + return false; } - } public void setLatestValueReference(final AtomicReference<QueueEntry> latestValueReference) { _latestValueReference = latestValueReference; } + + private void discardIfReleasedEntryIsNoLongerLatest() + { + if(_latestValueReference != null) + { + if(_latestValueReference.get() != this) + { + discardEntry(this); + } + } + } + + } + + /** + * Exposed purposes of unit test only. + */ + Map<Object, AtomicReference<QueueEntry>> getLatestValuesMap() + { + return Collections.unmodifiableMap(_latestValuesMap); } static class Factory implements QueueEntryListFactory @@ -163,5 +253,4 @@ public class ConflationQueueList extends SimpleQueueEntryList return new ConflationQueueList(queue, _conflationKey); } } - } diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java index 2493974d45..27a9e13617 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/DefaultQueueRegistry.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java b/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java index c1ebbe412f..3efef9ab98 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/NotificationCheck.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java index 1d13ee66c0..66315af9fb 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/PriorityQueueList.java @@ -37,7 +37,7 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl> _priorityOffset = 5-((priorities + 1)/2); for(int i = 0; i < priorities; i++) { - _priorityLists[i] = new PriorityQueueEntrySubList(queue); + _priorityLists[i] = new PriorityQueueEntrySubList(queue, i); } } @@ -164,9 +164,12 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl> private static class PriorityQueueEntrySubList extends SimpleQueueEntryList { - public PriorityQueueEntrySubList(AMQQueue queue) + private int _listPriority; + + public PriorityQueueEntrySubList(AMQQueue queue, int listPriority) { super(queue); + _listPriority = listPriority; } @Override @@ -174,6 +177,11 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl> { return new PriorityQueueEntryImpl(this, message); } + + public int getListPriority() + { + return _listPriority; + } } private static class PriorityQueueEntryImpl extends SimpleQueueEntryImpl @@ -186,8 +194,9 @@ public class PriorityQueueList implements QueueEntryList<SimpleQueueEntryImpl> @Override public int compareTo(final QueueEntry o) { - byte thisPriority = getMessageHeader().getPriority(); - byte otherPriority = o.getMessageHeader().getPriority(); + PriorityQueueEntrySubList pqel = (PriorityQueueEntrySubList)((PriorityQueueEntryImpl)o).getQueueEntryList(); + int otherPriority = pqel.getListPriority(); + int thisPriority = ((PriorityQueueEntrySubList) getQueueEntryList()).getListPriority(); if(thisPriority != otherPriority) { diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java index c33309b6d3..be2ab8b3ae 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java @@ -1,9 +1,3 @@ -package org.apache.qpid.server.queue; - -import org.apache.qpid.AMQException; -import org.apache.qpid.server.message.ServerMessage; -import org.apache.qpid.server.subscription.Subscription; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -24,6 +18,12 @@ import org.apache.qpid.server.subscription.Subscription; * under the License. * */ +package org.apache.qpid.server.queue; + +import org.apache.qpid.AMQException; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.subscription.Subscription; + public interface QueueEntry extends Comparable<QueueEntry>, Filterable { diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java index 209553e8fa..25e771a9cf 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java index 1578d21321..9ecaf6dafd 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryVisitor.java @@ -1,21 +1,21 @@ -package org.apache.qpid.server.queue; - -/** +/* * 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. */ +package org.apache.qpid.server.queue; + public interface QueueEntryVisitor { boolean visit(QueueEntry entry); diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java index 72a54c9889..e8c34128e9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRegistry.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index d7eb304c92..d42bd6cf03 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/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; @@ -28,12 +30,11 @@ import java.util.UUID; import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; +import java.util.concurrent.RejectedExecutionException; 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 +53,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 +70,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 +78,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 +117,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 +130,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 +174,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; @@ -185,12 +185,19 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes //TODO : persist creation time private long _createTime = System.currentTimeMillis(); + private UUID _qmfId; private ConfigurationPlugin _queueConfiguration; /** the maximum delivery count for each message on this queue or 0 if maximum delivery count is not to be enforced. */ 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,17 +234,16 @@ 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; - + _qmfId = getConfigStore().createId(); _asyncDelivery = ReferenceCountingExecutorService.getInstance().acquireExecutorService(); _logSubject = new QueueLogSubject(this); @@ -255,16 +261,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")) @@ -302,7 +298,22 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes public void execute(Runnable runnable) { - _asyncDelivery.execute(runnable); + try + { + _asyncDelivery.execute(runnable); + } + catch (RejectedExecutionException ree) + { + if (_stopped.get()) + { + // Ignore - SubFlusherRunner or QueueRunner submitted execution as queue was being stopped. + } + else + { + _logger.error("Unexpected rejected execution", ree); + throw ree; + } + } } public AMQShortString getNameShortString() @@ -320,6 +331,12 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes return _id; } + @Override + public UUID getQMFId() + { + return _qmfId; + } + public QueueConfigType getConfigType() { return QueueConfigType.getInstance(); @@ -339,15 +356,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 +380,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 +430,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { throw new AMQSecurityException("Permission denied"); } - - + + if (hasExclusiveSubscriber()) { throw new ExistingExclusiveSubscription(); @@ -463,15 +463,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 +516,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 +543,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 +621,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 +649,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes public void removeBinding(final Binding binding) { _bindings.remove(binding); - + reconfigure(); } @@ -718,10 +763,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } } - if(_managedObject != null) - { - _managedObject.checkForNotification(entry.getMessage()); - } + checkForNotification(entry.getMessage()); if(action != null) { @@ -738,8 +780,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 +830,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 +839,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 +872,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes setLastSeenEntry(sub, entry); _deliveredMessages.incrementAndGet(); - incrementUnackedMsgCount(); + incrementUnackedMsgCount(entry); sub.send(entry, batch); } @@ -833,12 +886,15 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private void setLastSeenEntry(final Subscription sub, final QueueEntry entry) { QueueContext subContext = (QueueContext) sub.getQueueContext(); - QueueEntry releasedEntry = subContext.getReleasedEntry(); - - QueueContext._lastSeenUpdater.set(subContext, entry); - if(releasedEntry == entry) + if (subContext != null) { - QueueContext._releasedUpdater.compareAndSet(subContext, releasedEntry, null); + QueueEntry releasedEntry = subContext.getReleasedEntry(); + + QueueContext._lastSeenUpdater.set(subContext, entry); + if(releasedEntry == entry) + { + QueueContext._releasedUpdater.compareAndSet(subContext, releasedEntry, null); + } } } @@ -887,7 +943,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { _deliveredMessages.decrementAndGet(); } - + if(sub != null && sub.isSessionTransactional()) { incrementTxnDequeueStats(entry); @@ -940,11 +996,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } } + + public int getConsumerCount() { return _subscriptionList.size(); } - + public int getConsumerCountHigh() { return _counsumerCountHigh.get(); @@ -1148,7 +1206,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 +1253,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 +1265,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 +1284,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes } public long clearQueue() throws AMQException - { + { return clear(0l); } @@ -1422,7 +1295,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 +1362,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { throw new AMQSecurityException("Permission denied: " + getName()); } - + if (!_deleted.getAndSet(true)) { @@ -1617,12 +1490,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 +1968,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 +2099,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 +2189,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes return _queueConfiguration; } - public String getResourceName() - { - return _resourceName; - } - - public ConfigStore getConfigStore() { return getVirtualHost().getConfigStore(); @@ -2355,22 +2208,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 +2260,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 +2307,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/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java index 8f3b7ae4ce..47a7d733dd 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java +++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SubFlushRunner.java @@ -1,4 +1,3 @@ -package org.apache.qpid.server.queue; /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -19,6 +18,7 @@ package org.apache.qpid.server.queue; * under the License. * */ +package org.apache.qpid.server.queue; import org.apache.log4j.Logger; diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java index 4ed28b965d..e0e317f75d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java +++ b/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,24 +35,18 @@ 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.plugins.Plugin; +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.SecurityManager.SecurityConfiguration; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; -import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory; +import org.apache.qpid.server.security.auth.manager.AuthenticationManagerRegistry; +import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.transport.QpidAcceptor; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -60,13 +54,8 @@ import org.apache.qpid.server.virtualhost.VirtualHostImpl; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import java.net.InetSocketAddress; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Timer; -import java.util.TimerTask; -import java.util.UUID; +import java.net.SocketAddress; +import java.util.*; import java.util.concurrent.atomic.AtomicReference; @@ -78,19 +67,19 @@ 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); private final ServerConfiguration _configuration; - private final Map<InetSocketAddress, QpidAcceptor> _acceptors = new HashMap<InetSocketAddress, QpidAcceptor>(); - - private ManagedObjectRegistry _managedObjectRegistry; + private final Map<InetSocketAddress, QpidAcceptor> _acceptors = + Collections.synchronizedMap(new HashMap<InetSocketAddress, QpidAcceptor>()); - private AuthenticationManager _authenticationManager; + private IAuthenticationManagerRegistry _authenticationManagerRegistry; - private VirtualHostRegistry _virtualHostRegistry; + private final VirtualHostRegistry _virtualHostRegistry = new VirtualHostRegistry(this); private SecurityManager _securityManager; @@ -106,39 +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; - protected static Logger get_logger() - { - return _logger; - } + private final List<PortBindingListener> _portBindingListeners = new ArrayList<PortBindingListener>(); - protected Map<InetSocketAddress, QpidAcceptor> getAcceptors() - { - return _acceptors; - } + private int _httpManagementPort = -1, _httpsManagementPort = -1; - protected void setManagedObjectRegistry(ManagedObjectRegistry managedObjectRegistry) - { - _managedObjectRegistry = managedObjectRegistry; - } + private LogRecorder _logRecorder; - protected void setAuthenticationManager(AuthenticationManager authenticationManager) - { - _authenticationManager = authenticationManager; - } + 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) @@ -205,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 { @@ -222,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) { @@ -297,18 +279,32 @@ 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(); + } + if (_configuration.getHTTPSManagementEnabled()) + { + _httpsManagementPort = _configuration.getHTTPSManagementPort(); + } + + _broker = new BrokerAdapter(this); configure(); @@ -316,13 +312,23 @@ public abstract class ApplicationRegistry implements IApplicationRegistry logStartupMessages(CurrentActor.get()); - _virtualHostRegistry = new VirtualHostRegistry(this); - _securityManager = new SecurityManager(_configuration, _pluginManager); - _authenticationManager = createAuthenticationManager(); + _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 { @@ -333,7 +339,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry try { initialiseVirtualHosts(); - initialiseStatistics(); initialiseStatisticsReporting(); } finally @@ -343,52 +348,10 @@ public abstract class ApplicationRegistry implements IApplicationRegistry } } - - /** - * Iterates across all discovered authentication manager factories, offering the security configuration to each. - * Expects <b>exactly</b> one authentication manager to configure and initialise itself. - * - * It is an error to configure more than one authentication manager, or to configure none. - * - * @return authentication manager - * @throws ConfigurationException - */ - protected AuthenticationManager createAuthenticationManager() throws ConfigurationException + protected IAuthenticationManagerRegistry createAuthenticationManagerRegistry(ServerConfiguration _configuration, PluginManager _pluginManager) + throws ConfigurationException { - final SecurityConfiguration securityConfiguration = _configuration.getConfiguration(SecurityConfiguration.class.getName()); - final Collection<AuthenticationManagerPluginFactory<? extends Plugin>> factories = _pluginManager.getAuthenticationManagerPlugins().values(); - - if (factories.size() == 0) - { - throw new ConfigurationException("No authentication manager factory plugins found. Check the desired authentication" + - "manager plugin has been placed in the plugins directory."); - } - - AuthenticationManager authMgr = null; - - for (final Iterator<AuthenticationManagerPluginFactory<? extends Plugin>> iterator = factories.iterator(); iterator.hasNext();) - { - final AuthenticationManagerPluginFactory<? extends Plugin> factory = (AuthenticationManagerPluginFactory<? extends Plugin>) iterator.next(); - final AuthenticationManager tmp = factory.newInstance(securityConfiguration); - if (tmp != null) - { - if (authMgr != null) - { - throw new ConfigurationException("Cannot configure more than one authentication manager." - + " Both " + tmp.getClass() + " and " + authMgr.getClass() + " are configured." - + " Remove configuration for one of the authentication manager, or remove the plugin JAR" - + " from the classpath."); - } - authMgr = tmp; - } - } - - if (authMgr == null) - { - throw new ConfigurationException("No authentication managers configured within the configure file."); - } - - return authMgr; + return new AuthenticationManagerRegistry(_configuration, _pluginManager); } protected void initialiseVirtualHosts() throws Exception @@ -400,23 +363,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), @@ -545,15 +503,13 @@ public abstract class ApplicationRegistry implements IApplicationRegistry //Shutdown virtualhosts close(_virtualHostRegistry); - close(_authenticationManager); + close(_authenticationManagerRegistry); close(_qmfService); close(_pluginManager); - close(_managedObjectRegistry); - - BrokerConfig broker = getBroker(); + BrokerConfig broker = getBrokerConfig(); if(broker != null) { broker.getSystem().removeBroker(broker); @@ -569,12 +525,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(); @@ -587,6 +545,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() @@ -600,6 +568,13 @@ public abstract class ApplicationRegistry implements IApplicationRegistry { _acceptors.put(bindAddress, acceptor); } + synchronized (_portBindingListeners) + { + for(PortBindingListener listener : _portBindingListeners) + { + listener.bound(acceptor, bindAddress); + } + } } public VirtualHostRegistry getVirtualHostRegistry() @@ -612,14 +587,16 @@ public abstract class ApplicationRegistry implements IApplicationRegistry return _securityManager; } - public ManagedObjectRegistry getManagedObjectRegistry() + @Override + public AuthenticationManager getAuthenticationManager(SocketAddress address) { - return _managedObjectRegistry; + return _authenticationManagerRegistry.getAuthenticationManager(address); } - public AuthenticationManager getAuthenticationManager() + @Override + public IAuthenticationManagerRegistry getAuthenticationManagerRegistry() { - return _authenticationManager; + return _authenticationManagerRegistry; } public PluginManager getPluginManager() @@ -636,7 +613,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry { return _rootMessageLogger; } - + public RootMessageLogger getCompositeStartupMessageLogger() { return _startupMessageLogger; @@ -652,69 +629,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(); @@ -723,25 +694,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())); @@ -755,4 +713,60 @@ 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; + } + + @Override + public boolean useHTTPSManagement() + { + return _httpsManagementPort != -1; + } + + @Override + public int getHTTPSManagementPort() + { + return _httpsManagementPort; + } + + 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/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java index db436b99e8..950a090b43 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java @@ -44,13 +44,13 @@ public class BrokerConfigAdapter implements BrokerConfig private final Map<UUID, VirtualHostConfig> _vhosts = new ConcurrentHashMap<UUID, VirtualHostConfig>(); private final long _createTime = System.currentTimeMillis(); - private UUID _id; + private UUID _qmfId; private String _federationTag; public BrokerConfigAdapter(final IApplicationRegistry instance) { _instance = instance; - _id = instance.getConfigStore().createId(); + _qmfId = instance.getConfigStore().createId(); _federationTag = UUID.randomUUID().toString(); } @@ -114,7 +114,7 @@ public class BrokerConfigAdapter implements BrokerConfig public void addVirtualHost(final VirtualHostConfig virtualHost) { - _vhosts.put(virtualHost.getId(), virtualHost); + _vhosts.put(virtualHost.getQMFId(), virtualHost); getConfigStore().addConfiguredObject(virtualHost); } @@ -141,9 +141,10 @@ public class BrokerConfigAdapter implements BrokerConfig vhost.createBrokerConnection(transport, host, port, "", durable, authMechanism, username, password); } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public BrokerConfigType getConfigType() @@ -184,7 +185,7 @@ public class BrokerConfigAdapter implements BrokerConfig public String toString() { return "BrokerConfigAdapter{" + - "_id=" + _id + + "_id=" + _qmfId + ", _system=" + _system + ", _vhosts=" + _vhosts + ", _createTime=" + _createTime + diff --git a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java index b28e3d6c89..774d0338ef 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java index 59bf250590..88c3c93156 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java @@ -27,16 +27,19 @@ 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; 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 @@ -60,9 +63,18 @@ public interface IApplicationRegistry extends StatisticsGatherer */ ServerConfiguration getConfiguration(); - ManagedObjectRegistry getManagedObjectRegistry(); + /** + * Get the AuthenticationManager for the given socket address + * + * If no AuthenticationManager has been specifically set for the given address, then use the default + * AuthenticationManager + * + * @param address The (listening) socket address for which the AuthenticationManager is required + * @return the AuthenticationManager + */ + AuthenticationManager getAuthenticationManager(SocketAddress address); - AuthenticationManager getAuthenticationManager(); + IAuthenticationManagerRegistry getAuthenticationManagerRegistry(); VirtualHostRegistry getVirtualHostRegistry(); @@ -85,15 +97,39 @@ public interface IApplicationRegistry extends StatisticsGatherer QMFService getQMFService(); - void setBroker(BrokerConfig broker); + void setBrokerConfig(BrokerConfig broker); - BrokerConfig getBroker(); + BrokerConfig getBrokerConfig(); + + 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(); + + boolean useHTTPSManagement(); + + int getHTTPSManagementPort(); + + void addRegistryChangeListener(IAuthenticationManagerRegistry.RegistryChangeListener registryChangeListener); + + public interface PortBindingListener + { + public void bound(QpidAcceptor acceptor, InetSocketAddress bindAddress); + public void unbound(QpidAcceptor acceptor); + + } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java index 7088fae50c..cac60a5283 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/AbstractPasswordFilePrincipalDatabase.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java deleted file mode 100644 index 1314a5d6a6..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java new file mode 100644 index 0000000000..5676c43754 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManager.java @@ -0,0 +1,192 @@ +/* + * 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.manager; + +import java.security.Principal; +import java.util.Arrays; +import java.util.List; +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousInitialiser; +import org.apache.qpid.server.security.auth.sasl.anonymous.AnonymousSaslServer; + +public class AnonymousAuthenticationManager implements AuthenticationManager +{ + private static final Logger _logger = Logger.getLogger(AnonymousAuthenticationManager.class); + + private static final AnonymousInitialiser SASL_INITIALISER = new AnonymousInitialiser(); + + private static final String ANONYMOUS = SASL_INITIALISER.getMechanismName(); + + private static final Principal ANONYMOUS_PRINCIPAL = new UsernamePrincipal("ANONYMOUS"); + + public static final Subject ANONYMOUS_SUBJECT = new Subject(); + static + { + ANONYMOUS_SUBJECT.getPrincipals().add(ANONYMOUS_PRINCIPAL); + } + + private static final AuthenticationResult ANONYMOUS_AUTHENTICATION = new AuthenticationResult(ANONYMOUS_SUBJECT); + + + private static CallbackHandler _callbackHandler = SASL_INITIALISER.getCallbackHandler(); + + static final AnonymousAuthenticationManager INSTANCE = new AnonymousAuthenticationManager(); + + public static class AnonymousAuthenticationManagerConfiguration extends ConfigurationPlugin + { + + public static final ConfigurationPluginFactory FACTORY = + new ConfigurationPluginFactory() + { + public List<String> getParentPaths() + { + return Arrays.asList("security.anonymous-auth-manager"); + } + + public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException + { + final ConfigurationPlugin instance = new AnonymousAuthenticationManagerConfiguration(); + + instance.setConfiguration(path, config); + return instance; + } + }; + + public String[] getElementsProcessed() + { + return new String[0]; + } + + public void validateConfiguration() throws ConfigurationException + { + } + + } + + + public static final AuthenticationManagerPluginFactory<AnonymousAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<AnonymousAuthenticationManager>() + { + public AnonymousAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException + { + AnonymousAuthenticationManagerConfiguration configuration = + config == null + ? null + : (AnonymousAuthenticationManagerConfiguration) config.getConfiguration(AnonymousAuthenticationManagerConfiguration.class.getName()); + + // If there is no configuration for this plugin then don't load it. + if (configuration == null) + { + _logger.info("No authentication-manager configuration found for AnonymousAuthenticationManager"); + return null; + } + return INSTANCE; + } + + public Class<AnonymousAuthenticationManager> getPluginClass() + { + return AnonymousAuthenticationManager.class; + } + + public String getPluginName() + { + return AnonymousAuthenticationManager.class.getName(); + } + }; + + + private AnonymousAuthenticationManager() + { + } + + @Override + public void initialise() + { + + } + + @Override + public String getMechanisms() + { + return ANONYMOUS; + } + + @Override + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException + { + if(ANONYMOUS.equals(mechanism)) + { + return new AnonymousSaslServer(); + } + else + { + throw new SaslException("Unknown mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(SaslServer server, byte[] response) + { + try + { + // Process response from the client + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + if (server.isComplete()) + { + return ANONYMOUS_AUTHENTICATION; + } + else + { + return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); + } + } + catch (SaslException e) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + + @Override + public AuthenticationResult authenticate(String username, String password) + { + return ANONYMOUS_AUTHENTICATION; + } + + @Override + public void close() + { + } + + @Override + public void configure(ConfigurationPlugin config) throws ConfigurationException + { + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java index 6c1a917d5b..ccddcb7669 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.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 @@ -20,25 +20,24 @@ */ package org.apache.qpid.server.security.auth.manager; +import java.security.Principal; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; import org.apache.qpid.common.Closeable; import org.apache.qpid.server.plugins.Plugin; import org.apache.qpid.server.security.auth.AuthenticationResult; -import javax.security.auth.callback.CallbackHandler; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; - /** * Implementations of the AuthenticationManager are responsible for determining * the authenticity of a user's credentials. - * + * * If the authentication is successful, the manager is responsible for producing a populated * {@link javax.security.auth.Subject} containing the user's identity and zero or more principals representing * groups to which the user belongs. * <p> * The {@link #initialise()} method is responsible for registering SASL mechanisms required by * the manager. The {@link #close()} method must reverse this registration. - * + * */ public interface AuthenticationManager extends Closeable, Plugin { @@ -64,11 +63,11 @@ public interface AuthenticationManager extends Closeable, Plugin * * @param mechanism mechanism name * @param localFQDN domain name - * + * @param externalPrincipal externally authenticated Principal * @return SASL server * @throws SaslException */ - SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException; + SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException; /** * Authenticates a user using SASL negotiation. @@ -90,5 +89,4 @@ public interface AuthenticationManager extends Closeable, Plugin */ AuthenticationResult authenticate(String username, String password); - CallbackHandler getHandler(String mechanism); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java new file mode 100644 index 0000000000..89a4d8ae66 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistry.java @@ -0,0 +1,203 @@ +/* + * 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.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; +import org.apache.qpid.common.Closeable; +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.plugins.Plugin; +import org.apache.qpid.server.plugins.PluginManager; +import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration; + +/** + * A concrete implementation of {@link IAuthenticationManagerRegistry} that registers all {@link AuthenticationManager} + * instances defined in the configuration, building an optional mapping between port number and AuthenticationManager. + * + * <p>The default AuthenticationManager is either the one nominated as default within the configuration with + * {@link ServerConfiguration#getDefaultAuthenticationManager()}, or if there is only one, it is implicitly + * the default.</p> + * + * <p>It is important to {@link #close()} the registry after use and this allows the AuthenticationManagers + * to reverse any security registrations they have performed.</p> + */ +public class AuthenticationManagerRegistry implements Closeable, IAuthenticationManagerRegistry +{ + 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 + { + final Collection<AuthenticationManagerPluginFactory<? extends Plugin>> factories = _pluginManager.getAuthenticationManagerPlugins().values(); + + if (factories.size() == 0) + { + throw new ConfigurationException("No authentication manager factory plugins found. Check the desired authentication" + + " manager plugin has been placed in the plugins directory."); + } + + final SecurityConfiguration securityConfiguration = serverConfiguration.getConfiguration(SecurityConfiguration.class.getName()); + + boolean willClose = true; + try + { + createAuthenticationManagersRejectingDuplicates(factories, securityConfiguration); + + if(_classToAuthManagerMap.isEmpty()) + { + throw new ConfigurationException("No authentication managers configured within the configuration file."); + } + + _defaultAuthenticationManager = getDefaultAuthenticationManager(serverConfiguration); + + _portToAuthenticationManagerMap = getPortToAuthenticationManagerMap(serverConfiguration); + willClose = false; + } + finally + { + // if anything went wrong whilst configuring the registry, try to close all the AuthentcationManagers instantiated so far. + // This is done to allow the AuthenticationManager to undo any security registrations that they have performed. + if (willClose) + { + close(); + } + } + } + + @Override + public AuthenticationManager getAuthenticationManager(SocketAddress address) + { + AuthenticationManager authManager = + address instanceof InetSocketAddress + ? _portToAuthenticationManagerMap.get(((InetSocketAddress)address).getPort()) + : null; + + return authManager == null ? _defaultAuthenticationManager : authManager; + } + + @Override + public void close() + { + for (AuthenticationManager authManager : _classToAuthManagerMap.values()) + { + authManager.close(); + } + } + + private void createAuthenticationManagersRejectingDuplicates( + final Collection<AuthenticationManagerPluginFactory<? extends Plugin>> factories, + final SecurityConfiguration securityConfiguration) + throws ConfigurationException + { + for(AuthenticationManagerPluginFactory<? extends Plugin> factory : factories) + { + final AuthenticationManager tmp = factory.newInstance(securityConfiguration); + if (tmp != null) + { + if(_classToAuthManagerMap.containsKey(tmp.getClass().getSimpleName())) + { + throw new ConfigurationException("Cannot configure more than one authentication manager of type " + + tmp.getClass().getSimpleName() + "." + + " Remove configuration for one of the authentication managers."); + } + _classToAuthManagerMap.put(tmp.getClass().getSimpleName(),tmp); + + for(RegistryChangeListener listener : _listeners) + { + listener.authenticationManagerRegistered(tmp); + } + } + } + } + + private AuthenticationManager getDefaultAuthenticationManager( + ServerConfiguration serverConfiguration) + throws ConfigurationException + { + final AuthenticationManager defaultAuthenticationManager; + if(_classToAuthManagerMap.size() == 1) + { + defaultAuthenticationManager = _classToAuthManagerMap.values().iterator().next(); + } + else if(serverConfiguration.getDefaultAuthenticationManager() != null) + { + defaultAuthenticationManager = _classToAuthManagerMap.get(serverConfiguration.getDefaultAuthenticationManager()); + if(defaultAuthenticationManager == null) + { + throw new ConfigurationException("No authentication managers configured of type " + + serverConfiguration.getDefaultAuthenticationManager() + + " which is specified as the default. Available managers are: " + + _classToAuthManagerMap.keySet()); + } + } + else + { + throw new ConfigurationException("If more than one authentication manager is configured a default MUST be specified."); + } + return defaultAuthenticationManager; + } + + private Map<Integer,AuthenticationManager> getPortToAuthenticationManagerMap( + ServerConfiguration serverConfiguration) + throws ConfigurationException + { + Map<Integer,AuthenticationManager> portToAuthenticationManagerMap = new HashMap<Integer, AuthenticationManager>(); + + for(Map.Entry<Integer,String> portMapping : serverConfiguration.getPortAuthenticationMappings().entrySet()) + { + + AuthenticationManager authenticationManager = _classToAuthManagerMap.get(portMapping.getValue()); + if(authenticationManager == null) + { + throw new ConfigurationException("Unknown authentication manager class " + portMapping.getValue() + + " configured for port " + portMapping.getKey()); + } + portToAuthenticationManagerMap.put(portMapping.getKey(), authenticationManager); + } + + 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/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java new file mode 100644 index 0000000000..2d6866b657 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManager.java @@ -0,0 +1,177 @@ +/* + * 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.manager; + +import java.security.Principal; +import java.util.Arrays; +import java.util.List; +import javax.security.auth.Subject; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.sasl.external.ExternalSaslServer; + +public class ExternalAuthenticationManager implements AuthenticationManager +{ + private static final Logger _logger = Logger.getLogger(ExternalAuthenticationManager.class); + + private static final String EXTERNAL = "EXTERNAL"; + + static final ExternalAuthenticationManager INSTANCE = new ExternalAuthenticationManager(); + + public static class ExternalAuthenticationManagerConfiguration extends ConfigurationPlugin + { + + public static final ConfigurationPluginFactory FACTORY = + new ConfigurationPluginFactory() + { + public List<String> getParentPaths() + { + return Arrays.asList("security.external-auth-manager"); + } + + public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException + { + final ConfigurationPlugin instance = new ExternalAuthenticationManagerConfiguration(); + + instance.setConfiguration(path, config); + return instance; + } + }; + + public String[] getElementsProcessed() + { + return new String[0]; + } + + public void validateConfiguration() throws ConfigurationException + { + } + + } + + + public static final AuthenticationManagerPluginFactory<ExternalAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<ExternalAuthenticationManager>() + { + public ExternalAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException + { + ExternalAuthenticationManagerConfiguration configuration = + config == null + ? null + : (ExternalAuthenticationManagerConfiguration) config.getConfiguration(ExternalAuthenticationManagerConfiguration.class.getName()); + + // If there is no configuration for this plugin then don't load it. + if (configuration == null) + { + _logger.info("No authentication-manager configuration found for ExternalAuthenticationManager"); + return null; + } + return INSTANCE; + } + + public Class<ExternalAuthenticationManager> getPluginClass() + { + return ExternalAuthenticationManager.class; + } + + public String getPluginName() + { + return ExternalAuthenticationManager.class.getName(); + } + }; + + + private ExternalAuthenticationManager() + { + } + + @Override + public void initialise() + { + + } + + @Override + public String getMechanisms() + { + return EXTERNAL; + } + + @Override + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException + { + if(EXTERNAL.equals(mechanism)) + { + return new ExternalSaslServer(externalPrincipal); + } + else + { + throw new SaslException("Unknown mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(SaslServer server, byte[] response) + { + // Process response from the client + try + { + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + Principal principal = ((ExternalSaslServer)server).getAuthenticatedPrincipal(); + + if(principal != null) + { + final Subject subject = new Subject(); + subject.getPrincipals().add(principal); + return new AuthenticationResult(subject); + } + else + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + } + catch (SaslException e) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR,e); + } + + } + + @Override + public AuthenticationResult authenticate(String username, String password) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + + @Override + public void close() + { + } + + @Override + public void configure(ConfigurationPlugin config) throws ConfigurationException + { + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.java new file mode 100644 index 0000000000..485ca2e1e9 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/IAuthenticationManagerRegistry.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.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. + * + * <p>A lookup method {@link #getAuthenticationManager(SocketAddress)} allows a caller to determine + * the AuthenticationManager associated with a particular port number.</p> + * + * <p>It is important to {@link #close()} the registry after use and this allows the AuthenticationManagers + * to reverse any security registrations they have performed.</p> + */ +public interface IAuthenticationManagerRegistry extends Closeable +{ + /** + * Returns the {@link AuthenticationManager} associated with a particular {@link SocketAddress}. + * If no authentication manager is associated with this address, a default authentication manager will be + * returned. Null is never returned. + * + * @param address + * @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/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java new file mode 100644 index 0000000000..d735ecb1d4 --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/KerberosAuthenticationManager.java @@ -0,0 +1,213 @@ +/* + * 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.manager; + +import java.io.IOException; +import java.security.Principal; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; + +public class KerberosAuthenticationManager implements AuthenticationManager +{ + private static final Logger _logger = Logger.getLogger(KerberosAuthenticationManager.class); + + private static final String GSSAPI_MECHANISM = "GSSAPI"; + private final CallbackHandler _callbackHandler = new GssApiCallbackHandler(); + + public static class KerberosAuthenticationManagerConfiguration extends ConfigurationPlugin + { + + public static final ConfigurationPluginFactory FACTORY = + new ConfigurationPluginFactory() + { + public List<String> getParentPaths() + { + return Arrays.asList("security.kerberos-auth-manager"); + } + + public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException + { + final ConfigurationPlugin instance = new KerberosAuthenticationManagerConfiguration(); + + instance.setConfiguration(path, config); + return instance; + } + }; + + public String[] getElementsProcessed() + { + return new String[0]; + } + + public void validateConfiguration() throws ConfigurationException + { + } + + } + + + public static final AuthenticationManagerPluginFactory<KerberosAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<KerberosAuthenticationManager>() + { + public KerberosAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException + { + KerberosAuthenticationManagerConfiguration configuration = + config == null + ? null + : (KerberosAuthenticationManagerConfiguration) config.getConfiguration(KerberosAuthenticationManagerConfiguration.class.getName()); + + // If there is no configuration for this plugin then don't load it. + if (configuration == null) + { + _logger.info("No authentication-manager configuration found for KerberosAuthenticationManager"); + return null; + } + KerberosAuthenticationManager kerberosAuthenticationManager = new KerberosAuthenticationManager(); + kerberosAuthenticationManager.configure(configuration); + return kerberosAuthenticationManager; + } + + public Class<KerberosAuthenticationManager> getPluginClass() + { + return KerberosAuthenticationManager.class; + } + + public String getPluginName() + { + return KerberosAuthenticationManager.class.getName(); + } + }; + + + private KerberosAuthenticationManager() + { + } + + @Override + public void initialise() + { + + } + + @Override + public String getMechanisms() + { + return GSSAPI_MECHANISM; + } + + @Override + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException + { + if(GSSAPI_MECHANISM.equals(mechanism)) + { + try + { + return Sasl.createSaslServer(GSSAPI_MECHANISM, "AMQP", localFQDN, + new HashMap<String, Object>(), _callbackHandler); + } + catch (SaslException e) + { + e.printStackTrace(System.err); + throw e; + } + } + else + { + throw new SaslException("Unknown mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(SaslServer server, byte[] response) + { + try + { + // Process response from the client + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + if (server.isComplete()) + { + final Subject subject = new Subject(); + _logger.debug("Authenticated as " + server.getAuthorizationID()); + subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID())); + return new AuthenticationResult(subject); + } + else + { + return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); + } + } + catch (SaslException e) + { + e.printStackTrace(System.err); + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + + @Override + public AuthenticationResult authenticate(String username, String password) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR); + } + + @Override + public void close() + { + } + + @Override + public void configure(ConfigurationPlugin config) throws ConfigurationException + { + } + + private static class GssApiCallbackHandler implements CallbackHandler + { + + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + for(Callback callback : callbacks) + { + if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(true); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java index b5d70d9200..e6498919a1 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java @@ -14,12 +14,13 @@ * "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. + * under the License. + * * - * */ package org.apache.qpid.server.security.auth.manager; +import java.security.Principal; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.log4j.Logger; @@ -31,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; @@ -60,9 +60,9 @@ import java.util.TreeMap; * Concrete implementation of the AuthenticationManager that determines if supplied * user credentials match those appearing in a PrincipalDatabase. The implementation * of the PrincipalDatabase is determined from the configuration. - * + * * This implementation also registers the JMX UserManagemement MBean. - * + * * This plugin expects configuration such as: * * <pre> @@ -97,13 +97,14 @@ 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 { - final PrincipalDatabaseAuthenticationManagerConfiguration configuration = config.getConfiguration(PrincipalDatabaseAuthenticationManagerConfiguration.class.getName()); + final PrincipalDatabaseAuthenticationManagerConfiguration configuration = + config == null + ? null + : (PrincipalDatabaseAuthenticationManagerConfiguration) config.getConfiguration(PrincipalDatabaseAuthenticationManagerConfiguration.class.getName()); // If there is no configuration for this plugin then don't load it. if (configuration == null) @@ -130,7 +131,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan }; public static class PrincipalDatabaseAuthenticationManagerConfiguration extends ConfigurationPlugin { - + public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() { public List<String> getParentPaths() @@ -141,7 +142,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException { final ConfigurationPlugin instance = new PrincipalDatabaseAuthenticationManagerConfiguration(); - + instance.setConfiguration(path, config); return instance; } @@ -157,16 +158,16 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan public void validateConfiguration() throws ConfigurationException { } - + public String getPrincipalDatabaseClass() { return getConfig().getString("principal-database.class"); } - + public Map<String,String> getPdClassAttributeMap() throws ConfigurationException { - final List<String> argumentNames = getConfig().getList("principal-database.attributes.attribute.name"); - final List<String> argumentValues = getConfig().getList("principal-database.attributes.attribute.value"); + final List<String> argumentNames = (List) getConfig().getList("principal-database.attributes.attribute.name"); + final List<String> argumentValues = (List) getConfig().getList("principal-database.attributes.attribute.value"); final Map<String,String> attributes = new HashMap<String,String>(argumentNames.size()); for (int i = 0; i < argumentNames.size(); i++) @@ -181,7 +182,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan } } - protected PrincipalDatabaseAuthenticationManager() + protected PrincipalDatabaseAuthenticationManager() { } @@ -207,11 +208,9 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan { _logger.warn("No additional SASL providers registered."); } - - registerManagement(); } - private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database) + private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database) { if (database == null || database.getMechanisms().size() == 0) { @@ -259,7 +258,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan _principalDatabase = createPrincipalDatabaseImpl(pdClazz); - configPrincipalDatabase(_principalDatabase, pdamConfig); + configPrincipalDatabase(_principalDatabase, pdamConfig); } public String getMechanisms() @@ -267,7 +266,7 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan return _mechanisms; } - public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException { return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism), _callbackHandlerMap.get(mechanism)); @@ -300,11 +299,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan } } - public CallbackHandler getHandler(String mechanism) - { - return _callbackHandlerMap.get(mechanism); - } - /** * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String) */ @@ -333,8 +327,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan { _mechanisms = null; Security.removeProvider(PROVIDER_NAME); - - unregisterManagement(); } private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException @@ -408,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)) @@ -428,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/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java new file mode 100644 index 0000000000..64b24e28bc --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/SimpleLDAPAuthenticationManager.java @@ -0,0 +1,389 @@ +/* + * 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.manager; + +import java.io.IOException; +import java.security.Principal; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import javax.naming.Context; +import javax.naming.NamingEnumeration; +import javax.naming.NamingException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; +import javax.naming.directory.SearchControls; +import javax.naming.directory.SearchResult; +import javax.security.auth.Subject; +import javax.security.auth.callback.Callback; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.callback.NameCallback; +import javax.security.auth.callback.UnsupportedCallbackException; +import javax.security.sasl.AuthorizeCallback; +import javax.security.sasl.Sasl; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.log4j.Logger; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; +import org.apache.qpid.server.security.auth.sasl.plain.PlainPasswordCallback; + +public class SimpleLDAPAuthenticationManager implements AuthenticationManager +{ + private static final Logger _logger = Logger.getLogger(SimpleLDAPAuthenticationManager.class); + + private static final String PLAIN_MECHANISM = "PLAIN"; + private static final String DEFAULT_LDAP_CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory"; + private String _providerSearchURL; + private String _searchContext; + private String _searchFilter; + private String _providerAuthURL; + private String _ldapContextFactory; + + public static class SimpleLDAPAuthenticationManagerConfiguration extends ConfigurationPlugin + { + + public static final ConfigurationPluginFactory FACTORY = + new ConfigurationPluginFactory() + { + public List<String> getParentPaths() + { + return Arrays.asList("security.simple-ldap-auth-manager"); + } + + public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException + { + final ConfigurationPlugin instance = new SimpleLDAPAuthenticationManagerConfiguration(); + + instance.setConfiguration(path, config); + return instance; + } + }; + + private static final String PROVIDER_URL = "provider-url"; + private static final String PROVIDER_SEARCH_URL = "provider-search-url"; + private static final String PROVIDER_AUTH_URL = "provider-auth-url"; + private static final String SEARCH_CONTEXT = "search-context"; + private static final String SEARCH_FILTER = "search-filter"; + private static final String LDAP_CONTEXT_FACTORY = "ldap-context-factory"; + + public String[] getElementsProcessed() + { + return new String[] {PROVIDER_URL, PROVIDER_SEARCH_URL, PROVIDER_AUTH_URL, SEARCH_CONTEXT, SEARCH_FILTER, + LDAP_CONTEXT_FACTORY}; + } + + public void validateConfiguration() throws ConfigurationException + { + } + + public String getLDAPContextFactory() + { + return getConfig().getString(LDAP_CONTEXT_FACTORY, DEFAULT_LDAP_CONTEXT_FACTORY); + } + + + public String getProviderURL() + { + return getConfig().getString(PROVIDER_URL); + } + + public String getProviderSearchURL() + { + return getConfig().getString(PROVIDER_SEARCH_URL, getProviderURL()); + } + + public String getSearchContext() + { + return getConfig().getString(SEARCH_CONTEXT); + } + + public String getSearchFilter() + { + return getConfig().getString(SEARCH_FILTER); + } + + public String getProviderAuthURL() + { + return getConfig().getString(PROVIDER_AUTH_URL, getProviderURL()); + } + } + + + public static final AuthenticationManagerPluginFactory<SimpleLDAPAuthenticationManager> FACTORY = new AuthenticationManagerPluginFactory<SimpleLDAPAuthenticationManager>() + { + public SimpleLDAPAuthenticationManager newInstance(final ConfigurationPlugin config) throws ConfigurationException + { + SimpleLDAPAuthenticationManagerConfiguration configuration = + config == null + ? null + : (SimpleLDAPAuthenticationManagerConfiguration) config.getConfiguration(SimpleLDAPAuthenticationManagerConfiguration.class.getName()); + + // If there is no configuration for this plugin then don't load it. + if (configuration == null) + { + _logger.info("No authentication-manager configuration found for SimpleLDAPAuthenticationManager"); + return null; + } + SimpleLDAPAuthenticationManager simpleLDAPAuthenticationManager = new SimpleLDAPAuthenticationManager(); + simpleLDAPAuthenticationManager.configure(configuration); + return simpleLDAPAuthenticationManager; + } + + public Class<SimpleLDAPAuthenticationManager> getPluginClass() + { + return SimpleLDAPAuthenticationManager.class; + } + + public String getPluginName() + { + return SimpleLDAPAuthenticationManager.class.getName(); + } + }; + + + private SimpleLDAPAuthenticationManager() + { + } + + @Override + public void initialise() + { + + } + + @Override + public String getMechanisms() + { + return PLAIN_MECHANISM; + } + + @Override + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException + { + if(PLAIN_MECHANISM.equals(mechanism)) + { + return Sasl.createSaslServer(PLAIN_MECHANISM, "AMQP", localFQDN, + new HashMap<String, Object>(), new PlainCallbackHandler()); + + } + else + { + throw new SaslException("Unknown mechanism: " + mechanism); + } + } + + @Override + public AuthenticationResult authenticate(SaslServer server, byte[] response) + { + try + { + // Process response from the client + byte[] challenge = server.evaluateResponse(response != null ? response : new byte[0]); + + if (server.isComplete()) + { + final Subject subject = new Subject(); + _logger.debug("Authenticated as " + server.getAuthorizationID()); + subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID())); + return new AuthenticationResult(subject); + } + else + { + return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.CONTINUE); + } + } + catch (SaslException e) + { + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + + @Override + public AuthenticationResult authenticate(String username, String password) + { + + try + { + return doLDAPNameAuthentication(getNameFromId(username), password); + } + catch (NamingException e) + { + + return new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + + } + } + + private AuthenticationResult doLDAPNameAuthentication(String username, String password) throws NamingException + { + Hashtable<Object,Object> env = new Hashtable<Object,Object>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory); + env.put(Context.PROVIDER_URL, _providerAuthURL); + + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + + env.put(Context.SECURITY_PRINCIPAL, username); + env.put(Context.SECURITY_CREDENTIALS, password); + DirContext ctx = new InitialDirContext(env); + ctx.close(); + final Subject subject = new Subject(); + subject.getPrincipals().add(new UsernamePrincipal(username)); + return new AuthenticationResult(subject); + } + + @Override + public void close() + { + } + + @Override + public void configure(ConfigurationPlugin config) throws ConfigurationException + { + SimpleLDAPAuthenticationManagerConfiguration ldapConfig = (SimpleLDAPAuthenticationManagerConfiguration) config; + + _ldapContextFactory = ldapConfig.getLDAPContextFactory(); + _providerSearchURL = ldapConfig.getProviderSearchURL(); + _providerAuthURL = ldapConfig.getProviderAuthURL(); + _searchContext = ldapConfig.getSearchContext(); + _searchFilter = ldapConfig.getSearchFilter(); + + Hashtable<String,Object> env = new Hashtable<String, Object>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory); + env.put(Context.PROVIDER_URL, _providerSearchURL); + env.put(Context.SECURITY_AUTHENTICATION, "none"); + + try + { + new InitialDirContext(env); + } + catch (NamingException e) + { + throw new ConfigurationException("Unable to establish anonymous connection to the ldap server at " + _providerSearchURL, e); + } + } + + private class PlainCallbackHandler implements CallbackHandler + { + + @Override + public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException + { + String name = null; + String password = null; + AuthenticationResult authenticated = null; + for(Callback callback : callbacks) + { + if (callback instanceof NameCallback) + { + String id = ((NameCallback) callback).getDefaultName(); + try + { + name = getNameFromId(id); + } + catch (NamingException e) + { + _logger.info("SASL Authentication Error", e); + } + if(password != null) + { + try + { + authenticated = doLDAPNameAuthentication(name, password); + + } + catch (NamingException e) + { + authenticated = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + } + else if (callback instanceof PlainPasswordCallback) + { + password = ((PlainPasswordCallback)callback).getPlainPassword(); + if(name != null) + { + try + { + authenticated = doLDAPNameAuthentication(name, password); + if(authenticated.getStatus()== AuthenticationResult.AuthenticationStatus.SUCCESS) + { + ((PlainPasswordCallback)callback).setAuthenticated(true); + } + } + catch (NamingException e) + { + authenticated = new AuthenticationResult(AuthenticationResult.AuthenticationStatus.ERROR, e); + } + } + } + else if (callback instanceof AuthorizeCallback) + { + ((AuthorizeCallback) callback).setAuthorized(authenticated != null && authenticated.getStatus() == AuthenticationResult.AuthenticationStatus.SUCCESS); + } + else + { + throw new UnsupportedCallbackException(callback); + } + } + } + } + + private String getNameFromId(String id) throws NamingException + { + Hashtable<Object,Object> env = new Hashtable<Object,Object>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, _ldapContextFactory); + env.put(Context.PROVIDER_URL, _providerSearchURL); + + + env.put(Context.SECURITY_AUTHENTICATION, "none"); + DirContext ctx = null; + + ctx = new InitialDirContext(env); + + try + { + SearchControls searchControls = new SearchControls(); + searchControls.setReturningAttributes(new String[] {}); + searchControls.setCountLimit(1l); + searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE); + NamingEnumeration<?> namingEnum = null; + String name = null; + + namingEnum = ctx.search(_searchContext, _searchFilter, new String[] { id }, searchControls); + if(namingEnum.hasMore()) + { + SearchResult result = (SearchResult) namingEnum.next(); + name = result.getNameInNamespace(); + } + return name; + } + finally + { + ctx.close(); + } + + } +} diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java index e27fd99f90..2e21cfbb07 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.java new file mode 100644 index 0000000000..9c2bca2d0b --- /dev/null +++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/external/ExternalSaslServer.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.security.auth.sasl.external; + +import java.security.Principal; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; + + +public class ExternalSaslServer implements SaslServer +{ + public static final String MECHANISM = "EXTERNAL"; + + private boolean _complete = false; + private final Principal _externalPrincipal; + + public ExternalSaslServer(Principal externalPrincipal) + { + _externalPrincipal = externalPrincipal; + } + + public String getMechanismName() + { + return MECHANISM; + } + + public byte[] evaluateResponse(byte[] response) throws SaslException + { + _complete = true; + return null; + } + + public boolean isComplete() + { + return _complete; + } + + public String getAuthorizationID() + { + return null; + } + + public byte[] unwrap(byte[] incoming, int offset, int len) throws SaslException + { + throw new SaslException("Unsupported operation"); + } + + public byte[] wrap(byte[] outgoing, int offset, int len) throws SaslException + { + throw new SaslException("Unsupported operation"); + } + + public Object getNegotiatedProperty(String propName) + { + return null; + } + + public void dispose() throws SaslException + { + } + + public Principal getAuthenticatedPrincipal() + { + return _externalPrincipal; + } +}
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java index f97b77a4fe..f352bbdd2c 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java @@ -32,7 +32,9 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.AMQMethodEvent; import org.apache.qpid.protocol.AMQMethodListener; import org.apache.qpid.server.protocol.AMQProtocolSession; +import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.virtualhost.VirtualHostRegistry; import java.util.concurrent.CopyOnWriteArraySet; @@ -61,6 +63,18 @@ public class AMQStateManager implements AMQMethodListener } + /** + * Get the ApplicationRegistry associated with this AMQStateManager + * + * returns the application registry associated with the VirtualHostRegistry of the AMQStateManager + * + * @return the ApplicationRegistry + */ + public IApplicationRegistry getApplicationRegistry() + { + return _virtualHostRegistry.getApplicationRegistry(); + } + public AMQState getCurrentState() { return _currentState; @@ -142,4 +156,14 @@ public class AMQStateManager implements AMQMethodListener SecurityManager.setThreadSubject(_protocolSession.getAuthorizedSubject()); return _protocolSession; } + + /** + * Get the AuthenticationManager associated with the ProtocolSession of the AMQStateManager + * + * @return the AuthenticationManager + */ + public AuthenticationManager getAuthenticationManager() + { + return getApplicationRegistry().getAuthenticationManager(getProtocolSession().getLocalAddress()); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java b/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java index 2bd17cfa2f..f382f90010 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java b/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java index 36fec4025a..37d87bb628 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java index 1307b1dbd4..ede01d247e 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java @@ -28,20 +28,21 @@ import java.util.UUID; public interface ConfigurationRecoveryHandler { - QueueRecoveryHandler begin(MessageStore store); + ExchangeRecoveryHandler begin(MessageStore store); - public static interface QueueRecoveryHandler + public static interface ExchangeRecoveryHandler { - void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments); - ExchangeRecoveryHandler completeQueueRecovery(); + void exchange(UUID id, String exchangeName, String type, boolean autoDelete); + QueueRecoveryHandler completeExchangeRecovery(); } - public static interface ExchangeRecoveryHandler + public static interface QueueRecoveryHandler { - void exchange(UUID id, String exchangeName, String type, boolean autoDelete); - BindingRecoveryHandler completeExchangeRecovery(); + void queue(UUID id, String queueName, String owner, boolean exclusive, FieldTable arguments, UUID alternateExchangeId); + BindingRecoveryHandler completeQueueRecovery(); } + public static interface BindingRecoveryHandler { void binding(UUID bindingId, UUID exchangeId, UUID queueId, String bindingName, ByteBuffer buf); diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java b/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java index 1a67fdf540..7356e1ae83 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/ConfiguredObjectHelper.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/store/Event.java b/java/broker/src/main/java/org/apache/qpid/server/store/Event.java index bbde11ab4c..c681126c11 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/Event.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/Event.java @@ -23,10 +23,20 @@ public enum Event { BEFORE_INIT, AFTER_INIT, + BEFORE_ACTIVATE, AFTER_ACTIVATE, + BEFORE_PASSIVATE, AFTER_PASSIVATE, + BEFORE_CLOSE, - AFTER_CLOSE + AFTER_CLOSE, + + BEFORE_QUIESCE, + AFTER_QUIESCE, + BEFORE_RESTART, + + PERSISTENT_MESSAGE_SIZE_OVERFULL, + PERSISTENT_MESSAGE_SIZE_UNDERFULL } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java b/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java index 21ae3924b8..bf3de2611d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/EventManager.java @@ -24,9 +24,12 @@ import java.util.EnumMap; import java.util.List; import java.util.Map; +import org.apache.log4j.Logger; + public class EventManager { private Map<Event, List<EventListener>> _listeners = new EnumMap<Event, List<EventListener>> (Event.class); + private static final Logger _LOGGER = Logger.getLogger(EventManager.class); public synchronized void addEventListener(EventListener listener, Event... events) { @@ -46,6 +49,11 @@ public class EventManager { if (_listeners.containsKey(event)) { + if(_LOGGER.isDebugEnabled()) + { + _LOGGER.debug("Received event " + event); + } + for (EventListener listener : _listeners.get(event)) { listener.event(event); diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java b/java/broker/src/main/java/org/apache/qpid/server/store/HAMessageStore.java index 8724f102c6..59483751ca 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStoreFactory.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/HAMessageStore.java @@ -19,19 +19,11 @@ */ package org.apache.qpid.server.store; -public class MemoryMessageStoreFactory implements MessageStoreFactory +public interface HAMessageStore extends MessageStore { - - @Override - public MessageStore createMessageStore() - { - return new MemoryMessageStore(); - } - - @Override - public String getStoreClassName() - { - return MemoryMessageStore.class.getSimpleName(); - } - + /** + * Used to indicate that a store requires to make itself unavailable for read and read/write + * operations. + */ + void passivate(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java index 59624b7a75..262d7d0213 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MemoryMessageStore.java @@ -83,19 +83,19 @@ public class MemoryMessageStore extends NullMessageStore @Override public void configureConfigStore(String name, ConfigurationRecoveryHandler recoveryHandler, Configuration config) throws Exception { - _stateManager.attainState(State.CONFIGURING); + _stateManager.attainState(State.INITIALISING); } @Override public void configureMessageStore(String name, MessageStoreRecoveryHandler recoveryHandler, TransactionLogRecoveryHandler tlogRecoveryHandler, Configuration config) throws Exception { - _stateManager.attainState(State.CONFIGURED); + _stateManager.attainState(State.INITIALISED); } @Override public void activate() throws Exception { - _stateManager.attainState(State.RECOVERING); + _stateManager.attainState(State.ACTIVATING); _stateManager.attainState(State.ACTIVE); } @@ -134,4 +134,10 @@ public class MemoryMessageStore extends NullMessageStore { _eventManager.addEventListener(eventListener, events); } + + @Override + public String getStoreType() + { + return "Memory"; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java index cf08ee00ff..0acaf164d9 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStore.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java index aba7456a44..728da23f28 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/MessageStoreConstants.java @@ -23,5 +23,7 @@ public class MessageStoreConstants { public static final String ENVIRONMENT_PATH_PROPERTY = "environment-path"; + public static final String OVERFULL_SIZE_PROPERTY = "overfull-size"; + public static final String UNDERFULL_SIZE_PROPERTY = "underfull-size"; } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java index 34c7d2d933..be08e309e6 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/NullMessageStore.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java b/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java index caff17daa5..4ab1a3ab05 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/OperationalLoggingListener.java @@ -33,7 +33,14 @@ public class OperationalLoggingListener implements EventListener private OperationalLoggingListener(final MessageStore store, LogSubject logSubject) { _logSubject = logSubject; - store.addEventListener(this, Event.BEFORE_INIT, Event.AFTER_INIT, Event.BEFORE_ACTIVATE, Event.AFTER_ACTIVATE, Event.AFTER_CLOSE); + store.addEventListener(this, + Event.BEFORE_INIT, + Event.AFTER_INIT, + Event.BEFORE_ACTIVATE, + Event.AFTER_ACTIVATE, + Event.AFTER_CLOSE, + Event.PERSISTENT_MESSAGE_SIZE_OVERFULL, + Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); _store = store; } @@ -62,7 +69,13 @@ public class OperationalLoggingListener implements EventListener case AFTER_CLOSE: CurrentActor.get().message(_logSubject,MessageStoreMessages.CLOSED()); break; - + case PERSISTENT_MESSAGE_SIZE_OVERFULL: + CurrentActor.get().message(_logSubject,MessageStoreMessages.OVERFULL()); + break; + case PERSISTENT_MESSAGE_SIZE_UNDERFULL: + CurrentActor.get().message(_logSubject,MessageStoreMessages.UNDERFULL()); + break; + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/State.java b/java/broker/src/main/java/org/apache/qpid/server/store/State.java index 7cbdede85e..2783637b2a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/State.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/State.java @@ -20,19 +20,30 @@ */ package org.apache.qpid.server.store; +import org.apache.qpid.server.configuration.ConfiguredObject; + public enum State { - + /** The initial state of the store. In practice, the store immediately transitions to the subsequent states. */ INITIAL, - CONFIGURING, - CONFIGURED, - RECOVERING, + + INITIALISING, + /** + * The initial set-up of the store has completed. + * If the store is persistent, it has not yet loaded configuration for {@link ConfiguredObject}'s from disk. + * + * From the point of view of the user, the store is essentially stopped. + */ + INITIALISED, + + ACTIVATING, ACTIVE, - QUIESCING, - QUIESCED, + CLOSING, - CLOSED; - + CLOSED, + QUIESCING, + /** The virtual host (and implicitly also the store) has been manually paused by the user to allow configuration changes to take place */ + QUIESCED; }
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java b/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java index 5998be5bb6..613b329beb 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/StateManager.java @@ -24,6 +24,8 @@ package org.apache.qpid.server.store; import java.util.EnumMap; import java.util.Map; +import org.apache.qpid.server.store.StateManager.Transition; + public class StateManager { private State _state = State.INITIAL; @@ -70,16 +72,23 @@ public class StateManager } - public static final Transition CONFIGURE = new Transition(State.INITIAL, State.CONFIGURING, Event.BEFORE_INIT); - public static final Transition CONFIGURE_COMPLETE = new Transition(State.CONFIGURING, State.CONFIGURED, Event.AFTER_INIT); - public static final Transition RECOVER = new Transition(State.CONFIGURED, State.RECOVERING, Event.BEFORE_ACTIVATE); - public static final Transition ACTIVATE = new Transition(State.RECOVERING, State.ACTIVE, Event.AFTER_ACTIVATE); + public static final Transition INITIALISE = new Transition(State.INITIAL, State.INITIALISING, Event.BEFORE_INIT); + public static final Transition INITALISE_COMPLETE = new Transition(State.INITIALISING, State.INITIALISED, Event.AFTER_INIT); + + public static final Transition ACTIVATE = new Transition(State.INITIALISED, State.ACTIVATING, Event.BEFORE_ACTIVATE); + public static final Transition ACTIVATE_COMPLETE = new Transition(State.ACTIVATING, State.ACTIVE, Event.AFTER_ACTIVATE); + + public static final Transition CLOSE_INITIALISED = new Transition(State.INITIALISED, State.CLOSING, Event.BEFORE_CLOSE);; public static final Transition CLOSE_ACTIVE = new Transition(State.ACTIVE, State.CLOSING, Event.BEFORE_CLOSE); public static final Transition CLOSE_QUIESCED = new Transition(State.QUIESCED, State.CLOSING, Event.BEFORE_CLOSE); public static final Transition CLOSE_COMPLETE = new Transition(State.CLOSING, State.CLOSED, Event.AFTER_CLOSE); - public static final Transition QUIESCE = new Transition(State.ACTIVE, State.QUIESCING, Event.BEFORE_PASSIVATE); - public static final Transition QUIESCE_COMPLETE = new Transition(State.QUIESCING, State.QUIESCED, Event.BEFORE_PASSIVATE); - public static final Transition RESTART = new Transition(State.QUIESCED, State.RECOVERING, Event.BEFORE_ACTIVATE); + + public static final Transition PASSIVATE = new Transition(State.ACTIVE, State.INITIALISED, Event.BEFORE_PASSIVATE); + + public static final Transition QUIESCE = new Transition(State.ACTIVE, State.QUIESCING, Event.BEFORE_QUIESCE); + public static final Transition QUIESCE_COMPLETE = new Transition(State.QUIESCING, State.QUIESCED, Event.AFTER_QUIESCE); + + public static final Transition RESTART = new Transition(State.QUIESCED, State.ACTIVATING, Event.BEFORE_RESTART); public StateManager(final EventManager eventManager) @@ -105,16 +114,6 @@ public class StateManager return _state; } - public synchronized void stateTransition(final State current, final State desired) - { - if (_state != current) - { - throw new IllegalStateException("Cannot transition to the state: " + desired + "; need to be in state: " + current - + "; currently in state: " + _state); - } - attainState(desired); - } - public synchronized void attainState(State desired) { Transition transition = null; diff --git a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java index 0371cdcfcb..154d7e6535 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java +++ b/java/broker/src/main/java/org/apache/qpid/server/store/derby/DerbyMessageStore.java @@ -31,6 +31,7 @@ import java.lang.ref.SoftReference; import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.sql.Blob; +import java.sql.CallableStatement; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; @@ -59,6 +60,7 @@ import org.apache.qpid.server.federation.BrokerLink; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.store.ConfigurationRecoveryHandler; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler; import org.apache.qpid.server.store.ConfiguredObjectHelper; import org.apache.qpid.server.store.ConfiguredObjectRecord; import org.apache.qpid.server.store.Event; @@ -77,6 +79,9 @@ import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.store.Transaction; import org.apache.qpid.server.store.TransactionLogRecoveryHandler; import org.apache.qpid.server.store.TransactionLogResource; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler.BindingRecoveryHandler; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecoveryHandler; +import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler; /** * An implementation of a {@link MessageStore} that uses Apache Derby as the persistence @@ -111,6 +116,7 @@ public class DerbyMessageStore implements MessageStore private static Class<Driver> DRIVER_CLASS; + public static final String MEMORY_STORE_LOCATION = ":memory:"; private final AtomicLong _messageId = new AtomicLong(0); private AtomicBoolean _closed = new AtomicBoolean(false); @@ -230,10 +236,17 @@ 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(); + private long _totalStoreSize; + private boolean _limitBusted; + private long _persistentSizeLowThreshold; + private long _persistentSizeHighThreshold; + private MessageStoreRecoveryHandler _messageRecoveryHandler; private TransactionLogRecoveryHandler _tlogRecoveryHandler; @@ -253,7 +266,7 @@ public class DerbyMessageStore implements MessageStore ConfigurationRecoveryHandler configRecoveryHandler, Configuration storeConfiguration) throws Exception { - _stateManager.attainState(State.CONFIGURING); + _stateManager.attainState(State.INITIALISING); _configRecoveryHandler = configRecoveryHandler; commonConfiguration(name, storeConfiguration); @@ -269,13 +282,13 @@ public class DerbyMessageStore implements MessageStore _tlogRecoveryHandler = tlogRecoveryHandler; _messageRecoveryHandler = recoveryHandler; - _stateManager.attainState(State.CONFIGURED); + _stateManager.attainState(State.INITIALISED); } @Override public void activate() throws Exception { - _stateManager.attainState(State.RECOVERING); + _stateManager.attainState(State.ACTIVATING); // this recovers durable exchanges, queues, and bindings recoverConfiguration(_configRecoveryHandler); @@ -296,19 +309,39 @@ public class DerbyMessageStore implements MessageStore final String databasePath = storeConfiguration.getString(MessageStoreConstants.ENVIRONMENT_PATH_PROPERTY, System.getProperty("QPID_WORK") + File.separator + "derbyDB"); - File environmentPath = new File(databasePath); - if (!environmentPath.exists()) + if(!MEMORY_STORE_LOCATION.equals(databasePath)) { - if (!environmentPath.mkdirs()) + File environmentPath = new File(databasePath); + if (!environmentPath.exists()) { - throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. " - + "Ensure the path is correct and that the permissions are correct."); + if (!environmentPath.mkdirs()) + { + throw new IllegalArgumentException("Environment path " + environmentPath + " could not be read or created. " + + "Ensure the path is correct and that the permissions are correct."); + } } } _storeLocation = databasePath; + _persistentSizeHighThreshold = storeConfiguration.getLong(MessageStoreConstants.OVERFULL_SIZE_PROPERTY, -1l); + _persistentSizeLowThreshold = storeConfiguration.getLong(MessageStoreConstants.UNDERFULL_SIZE_PROPERTY, _persistentSizeHighThreshold); + if(_persistentSizeLowThreshold > _persistentSizeHighThreshold || _persistentSizeLowThreshold < 0l) + { + _persistentSizeLowThreshold = _persistentSizeHighThreshold; + } + createOrOpenDatabase(name, databasePath); + + Connection conn = newAutoCommitConnection();; + try + { + _totalStoreSize = getSizeOnDisk(conn); + } + finally + { + conn.close(); + } } private static synchronized void initialiseDriver() throws ClassNotFoundException @@ -322,7 +355,7 @@ public class DerbyMessageStore implements MessageStore private void createOrOpenDatabase(String name, final String environmentPath) throws SQLException { //FIXME this the _vhost name should not be added here, but derby wont use an empty directory as was possibly just created. - _connectionURL = "jdbc:derby:" + environmentPath + "/" + name + ";create=true"; + _connectionURL = "jdbc:derby" + (environmentPath.equals(MEMORY_STORE_LOCATION) ? environmentPath : ":" + environmentPath + "/") + name + ";create=true"; Connection conn = newAutoCommitConnection(); @@ -529,16 +562,17 @@ public class DerbyMessageStore implements MessageStore try { List<ConfiguredObjectRecord> configuredObjects = loadConfiguredObjects(); - ConfigurationRecoveryHandler.QueueRecoveryHandler qrh = recoveryHandler.begin(this); - _configuredObjectHelper.recoverQueues(qrh, configuredObjects); - ConfigurationRecoveryHandler.ExchangeRecoveryHandler erh = qrh.completeQueueRecovery(); + ExchangeRecoveryHandler erh = recoveryHandler.begin(this); _configuredObjectHelper.recoverExchanges(erh, configuredObjects); - ConfigurationRecoveryHandler.BindingRecoveryHandler brh = erh.completeExchangeRecovery(); + QueueRecoveryHandler qrh = erh.completeExchangeRecovery(); + _configuredObjectHelper.recoverQueues(qrh, configuredObjects); + + BindingRecoveryHandler brh = qrh.completeQueueRecovery(); _configuredObjectHelper.recoverBindings(brh, configuredObjects); - ConfigurationRecoveryHandler.BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery(); + BrokerLinkRecoveryHandler lrh = brh.completeBindingRecovery(); recoverBrokerLinks(lrh); } catch (SQLException e) @@ -689,7 +723,7 @@ public class DerbyMessageStore implements MessageStore public void close() throws Exception { _closed.getAndSet(true); - _stateManager.stateTransition(State.ACTIVE, State.CLOSING); + _stateManager.attainState(State.CLOSING); try { @@ -710,7 +744,7 @@ public class DerbyMessageStore implements MessageStore } } - _stateManager.stateTransition(State.CLOSING, State.CLOSED); + _stateManager.attainState(State.CLOSED); } @Override @@ -956,8 +990,8 @@ public class DerbyMessageStore implements MessageStore try { - stmt.setLong(1, link.getId().getLeastSignificantBits()); - stmt.setLong(2, link.getId().getMostSignificantBits()); + stmt.setLong(1, link.getQMFId().getLeastSignificantBits()); + stmt.setLong(2, link.getQMFId().getMostSignificantBits()); ResultSet rs = stmt.executeQuery(); try { @@ -970,8 +1004,8 @@ public class DerbyMessageStore implements MessageStore try { - insertStmt.setLong(1, link.getId().getLeastSignificantBits()); - insertStmt.setLong(2, link.getId().getMostSignificantBits()); + insertStmt.setLong(1, link.getQMFId().getLeastSignificantBits()); + insertStmt.setLong(2, link.getQMFId().getMostSignificantBits()); insertStmt.setLong(3, link.getCreateTime()); byte[] argumentBytes = convertStringMapToBytes(link.getArguments()); @@ -1048,8 +1082,8 @@ public class DerbyMessageStore implements MessageStore { conn = newAutoCommitConnection(); stmt = conn.prepareStatement(DELETE_FROM_LINKS); - stmt.setLong(1, link.getId().getLeastSignificantBits()); - stmt.setLong(2, link.getId().getMostSignificantBits()); + stmt.setLong(1, link.getQMFId().getLeastSignificantBits()); + stmt.setLong(2, link.getQMFId().getMostSignificantBits()); int results = stmt.executeUpdate(); if (results == 0) @@ -1085,7 +1119,7 @@ public class DerbyMessageStore implements MessageStore try { - UUID id = bridge.getId(); + UUID id = bridge.getQMFId(); stmt.setLong(1, id.getLeastSignificantBits()); stmt.setLong(2, id.getMostSignificantBits()); ResultSet rs = stmt.executeQuery(); @@ -1105,7 +1139,7 @@ public class DerbyMessageStore implements MessageStore insertStmt.setLong(3, bridge.getCreateTime()); - UUID linkId = bridge.getLink().getId(); + UUID linkId = bridge.getLink().getQMFId(); insertStmt.setLong(4, linkId.getLeastSignificantBits()); insertStmt.setLong(5, linkId.getMostSignificantBits()); @@ -1151,8 +1185,8 @@ public class DerbyMessageStore implements MessageStore { conn = newAutoCommitConnection(); stmt = conn.prepareStatement(DELETE_FROM_BRIDGES); - stmt.setLong(1, bridge.getId().getLeastSignificantBits()); - stmt.setLong(2, bridge.getId().getMostSignificantBits()); + stmt.setLong(1, bridge.getQMFId().getLeastSignificantBits()); + stmt.setLong(2, bridge.getQMFId().getMostSignificantBits()); int results = stmt.executeUpdate(); if (results == 0) @@ -1541,7 +1575,7 @@ public class DerbyMessageStore implements MessageStore buf = buf.slice(); MessageMetaDataType type = MessageMetaDataType.values()[dataAsBytes[0]]; StorableMessageMetaData metaData = type.getFactory().createMetaData(buf); - StoredDerbyMessage message = new StoredDerbyMessage(messageId, metaData, false); + StoredDerbyMessage message = new StoredDerbyMessage(messageId, metaData, true); messageHandler.message(message); } @@ -1921,6 +1955,7 @@ public class DerbyMessageStore implements MessageStore private class DerbyTransaction implements Transaction { private final ConnectionWrapper _connWrapper; + private int _storeSizeIncrease; private DerbyTransaction() @@ -1938,18 +1973,19 @@ public class DerbyMessageStore implements MessageStore @Override public void enqueueMessage(TransactionLogResource queue, EnqueableMessage message) throws AMQStoreException { - if(message.getStoredMessage() instanceof StoredDerbyMessage) + final StoredMessage storedMessage = message.getStoredMessage(); + if(storedMessage instanceof StoredDerbyMessage) { try { - ((StoredDerbyMessage)message.getStoredMessage()).store(_connWrapper.getConnection()); + ((StoredDerbyMessage) storedMessage).store(_connWrapper.getConnection()); } catch (SQLException e) { throw new AMQStoreException("Exception on enqueuing message " + _messageId, e); } } - + _storeSizeIncrease += storedMessage.getMetaData().getContentSize(); DerbyMessageStore.this.enqueueMessage(_connWrapper, queue, message.getMessageNumber()); } @@ -1964,12 +2000,15 @@ public class DerbyMessageStore implements MessageStore public void commitTran() throws AMQStoreException { DerbyMessageStore.this.commitTran(_connWrapper); + storedSizeChange(_storeSizeIncrease); } @Override public StoreFuture commitTranAsync() throws AMQStoreException { - return DerbyMessageStore.this.commitTranAsync(_connWrapper); + final StoreFuture storeFuture = DerbyMessageStore.this.commitTranAsync(_connWrapper); + storedSizeChange(_storeSizeIncrease); + return storeFuture; } @Override @@ -1998,6 +2037,8 @@ public class DerbyMessageStore implements MessageStore { private final long _messageId; + private final boolean _isRecovered; + private StorableMessageMetaData _metaData; private volatile SoftReference<StorableMessageMetaData> _metaDataRef; private byte[] _data; @@ -2006,21 +2047,21 @@ public class DerbyMessageStore implements MessageStore StoredDerbyMessage(long messageId, StorableMessageMetaData metaData) { - this(messageId, metaData, true); + this(messageId, metaData, false); } StoredDerbyMessage(long messageId, - StorableMessageMetaData metaData, boolean persist) + StorableMessageMetaData metaData, boolean isRecovered) { _messageId = messageId; + _isRecovered = isRecovered; - - _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); - if(persist) + if(!_isRecovered) { _metaData = metaData; } + _metaDataRef = new SoftReference<StorableMessageMetaData>(metaData); } @Override @@ -2101,16 +2142,17 @@ public class DerbyMessageStore implements MessageStore @Override public synchronized StoreFuture flushToStore() { + Connection conn = null; try { - if(_metaData != null) + if(!stored()) { - Connection conn = newConnection(); + conn = newConnection(); store(conn); conn.commit(); - conn.close(); + storedSizeChange(getMetaData().getContentSize()); } } catch (SQLException e) @@ -2121,12 +2163,24 @@ public class DerbyMessageStore implements MessageStore } throw new RuntimeException(e); } + finally + { + closeConnection(conn); + } return StoreFuture.IMMEDIATE_FUTURE; } + @Override + public void remove() + { + int delta = getMetaData().getContentSize(); + DerbyMessageStore.this.removeMessage(_messageId); + storedSizeChange(-delta); + } + private synchronized void store(final Connection conn) throws SQLException { - if(_metaData != null) + if (!stored()) { try { @@ -2139,18 +2193,17 @@ public class DerbyMessageStore implements MessageStore _metaData = null; _data = null; } - } - if(_logger.isDebugEnabled()) - { - _logger.debug("Storing message " + _messageId + " to store"); + if(_logger.isDebugEnabled()) + { + _logger.debug("Storing message " + _messageId + " to store"); + } } } - @Override - public void remove() + private boolean stored() { - DerbyMessageStore.this.removeMessage(_messageId); + return _metaData == null || _isRecovered; } } @@ -2446,4 +2499,181 @@ public class DerbyMessageStore implements MessageStore } return results; } + + private synchronized void storedSizeChange(final int delta) + { + if(getPersistentSizeHighThreshold() > 0) + { + synchronized(this) + { + // the delta supplied is an approximation of a store size change. we don;t want to check the statistic every + // time, so we do so only when there's been enough change that it is worth looking again. We do this by + // assuming the total size will change by less than twice the amount of the message data change. + long newSize = _totalStoreSize += 3*delta; + + Connection conn = null; + try + { + + if(!_limitBusted && newSize > getPersistentSizeHighThreshold()) + { + conn = newAutoCommitConnection(); + _totalStoreSize = getSizeOnDisk(conn); + if(_totalStoreSize > getPersistentSizeHighThreshold()) + { + _limitBusted = true; + _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); + } + } + else if(_limitBusted && newSize < getPersistentSizeLowThreshold()) + { + long oldSize = _totalStoreSize; + conn = newAutoCommitConnection(); + _totalStoreSize = getSizeOnDisk(conn); + if(oldSize <= _totalStoreSize) + { + + reduceSizeOnDisk(conn); + + _totalStoreSize = getSizeOnDisk(conn); + } + + if(_totalStoreSize < getPersistentSizeLowThreshold()) + { + _limitBusted = false; + _eventManager.notifyEvent(Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); + } + + + } + } + catch (SQLException e) + { + closeConnection(conn); + throw new RuntimeException("Exception will processing store size change", e); + } + } + } + } + + private void reduceSizeOnDisk(Connection conn) + { + CallableStatement cs = null; + PreparedStatement stmt = null; + try + { + String tableQuery = + "SELECT S.SCHEMANAME, T.TABLENAME FROM SYS.SYSSCHEMAS S, SYS.SYSTABLES T WHERE S.SCHEMAID = T.SCHEMAID AND T.TABLETYPE='T'"; + stmt = conn.prepareStatement(tableQuery); + ResultSet rs = null; + + List<String> schemas = new ArrayList<String>(); + List<String> tables = new ArrayList<String>(); + + try + { + rs = stmt.executeQuery(); + while(rs.next()) + { + schemas.add(rs.getString(1)); + tables.add(rs.getString(2)); + } + } + finally + { + if(rs != null) + { + rs.close(); + } + } + + + cs = conn.prepareCall + ("CALL SYSCS_UTIL.SYSCS_COMPRESS_TABLE(?, ?, ?)"); + + for(int i = 0; i < schemas.size(); i++) + { + cs.setString(1, schemas.get(i)); + cs.setString(2, tables.get(i)); + cs.setShort(3, (short) 0); + cs.execute(); + } + } + catch (SQLException e) + { + closeConnection(conn); + throw new RuntimeException("Error reducing on disk size", e); + } + finally + { + closePreparedStatement(stmt); + closePreparedStatement(cs); + } + + } + + private long getSizeOnDisk(Connection conn) + { + PreparedStatement stmt = null; + try + { + String sizeQuery = "SELECT SUM(T2.NUMALLOCATEDPAGES * T2.PAGESIZE) TOTALSIZE" + + " FROM " + + " SYS.SYSTABLES systabs," + + " TABLE (SYSCS_DIAG.SPACE_TABLE(systabs.tablename)) AS T2" + + " WHERE systabs.tabletype = 'T'"; + + stmt = conn.prepareStatement(sizeQuery); + + ResultSet rs = null; + long size = 0l; + + try + { + rs = stmt.executeQuery(); + while(rs.next()) + { + size = rs.getLong(1); + } + } + finally + { + if(rs != null) + { + rs.close(); + } + } + + return size; + + } + catch (SQLException e) + { + closeConnection(conn); + throw new RuntimeException("Error establishing on disk size", e); + } + finally + { + closePreparedStatement(stmt); + } + + } + + + private long getPersistentSizeLowThreshold() + { + return _persistentSizeLowThreshold; + } + + private long getPersistentSizeHighThreshold() + { + return _persistentSizeHighThreshold; + } + + @Override + public String getStoreType() + { + return DERBY_STORE_TYPE; + } + }
\ No newline at end of file diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java index 6b2dff7165..efedad1181 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java index 62e94f6f2e..f38e23b342 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java index cf2754862d..8f3822be6c 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/ExplicitAcceptDispositionChangeListener.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java index 1e37675c98..826082cc65 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/ImplicitAcceptDispositionChangeListener.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java index 66825caa24..8911754a66 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java index 1f25c215cc..c92853e400 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java +++ b/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; @@ -75,7 +76,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE); - private AMQQueue.Context _queueContext; + private volatile AMQQueue.Context _queueContext; private final ClientDeliveryMethod _deliveryMethod; private final RecordDeliveryMethod _recordMethod; @@ -90,10 +91,15 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage private final long _subscriptionID; private LogSubject _logSubject; private LogActor _logActor; - private UUID _id; + private UUID _qmfId; 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(); @@ -389,7 +391,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage } _queue = queue; - _id = getConfigStore().createId(); + _qmfId = getConfigStore().createId(); getConfigStore().addConfiguredObject(this); _logSubject = new SubscriptionLogSubject(this); @@ -468,11 +470,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage _deleted.set(true); } - public boolean filtersMessages() - { - return _filters != null || _noLocal; - } - public boolean hasInterest(QueueEntry entry) { //check that the message hasn't been rejected @@ -508,13 +505,6 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage } - private String id = String.valueOf(System.identityHashCode(this)); - - private String debugIdentity() - { - return id; - } - private boolean checkFilters(QueueEntry msg) { return (_filters == null) || _filters.allAllow(msg); @@ -599,6 +589,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 +682,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage { _deliveryMethod.deliverToClient(this,entry,deliveryTag); _deliveredCount.incrementAndGet(); + _deliveredBytes.addAndGet(entry.getSize()); } @@ -771,9 +767,10 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage return true; } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public boolean isDurable() @@ -832,4 +829,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/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java index 76d975a789..dfd9315226 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java +++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java @@ -98,7 +98,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private final Lock _stateChangeLock = new ReentrantLock(); private final AtomicReference<State> _state = new AtomicReference<State>(State.ACTIVE); - private AMQQueue.Context _queueContext; + private volatile AMQQueue.Context _queueContext; private final AtomicBoolean _deleted = new AtomicBoolean(false); @@ -125,11 +125,15 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr private LogActor _logActor; private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>(); - private UUID _id; + private UUID _qmfId; private String _traceExclude; 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,10 +189,10 @@ 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(); + _qmfId = getConfigStore().createId(); getConfigStore().addConfiguredObject(this); String filterLogString = null; @@ -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() @@ -990,9 +1011,10 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr return _flowMode.toString(); } - public UUID getId() + @Override + public UUID getQMFId() { - return _id; + return _qmfId; } public String getName() @@ -1073,4 +1095,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/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java b/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java index 637ea7dffc..7c4188bfcd 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java +++ b/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/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java index c38f3d0761..f21026794f 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java @@ -20,6 +20,14 @@ */ package org.apache.qpid.server.transport; +import java.security.Principal; +import java.text.MessageFormat; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicLong; +import javax.security.auth.Subject; import org.apache.qpid.AMQException; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.configuration.ConnectionConfig; @@ -28,12 +36,9 @@ 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; -import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.Connection; @@ -48,17 +53,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; -import javax.management.JMException; -import javax.security.auth.Subject; -import java.security.Principal; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicLong; - -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; @@ -67,24 +62,19 @@ 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; + private Principal _peerPrincipal; + public ServerConnection(final long connectionId) { _connectionId = connectionId; } - public UUID getId() - { - return _config.getId(); - } - public Object getReference() { return _reference; @@ -100,12 +90,12 @@ public class ServerConnection extends Connection implements Managable, AMQConnec protected void setState(State state) { super.setState(state); - + if (state == State.OPEN) { if (_onOpenTask != null) { - _onOpenTask.run(); + _onOpenTask.run(); } _actor.message(ConnectionMessages.OPEN(getClientId(), "0-10", getClientVersion(), true, true, true)); @@ -118,7 +108,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec { _virtualHost.getConnectionRegistry().deregisterConnection(this); } - unregisterConnectionMbean(); } if (state == State.CLOSED) @@ -156,8 +145,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec _virtualHost = virtualHost; initialiseStatistics(); - - registerConnectionMbean(); } public void setConnectionConfig(final ConnectionConfig config) @@ -193,7 +180,7 @@ public class ServerConnection extends Connection implements Managable, AMQConnec ((ServerSession)session).close(); } - + public LogSubject getLogSubject() { return (LogSubject) this; @@ -273,7 +260,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 { @@ -286,6 +272,46 @@ public class ServerConnection extends Connection implements Managable, AMQConnec close(replyCode, message); } + public synchronized void block() + { + if(!_blocking) + { + _blocking = true; + for(AMQSessionModel ssn : getSessionModels()) + { + ssn.block(); + } + } + } + + public synchronized void unblock() + { + if(_blocking) + { + _blocking = false; + for(AMQSessionModel ssn : getSessionModels()) + { + ssn.unblock(); + } + } + } + + @Override + public synchronized void registerSession(final Session ssn) + { + super.registerSession(ssn); + if(_blocking) + { + ((ServerSession)ssn).block(); + } + } + + @Override + public synchronized void removeSession(final Session ssn) + { + super.removeSession(ssn); + } + public List<AMQSessionModel> getSessionModels() { List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>(); @@ -298,44 +324,38 @@ 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); } - + 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(); @@ -346,25 +366,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 */ @@ -389,7 +396,7 @@ public class ServerConnection extends Connection implements Managable, AMQConnec else { _authorizedSubject = authorizedSubject; - _authorizedPrincipal = UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject); + _authorizedPrincipal = authorizedSubject.getPrincipals().iterator().next(); } } @@ -408,6 +415,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(); @@ -436,12 +448,6 @@ public class ServerConnection extends Connection implements Managable, AMQConnec } } - - public ManagedObject getManagedObject() - { - return _mBean; - } - @Override public void send(ProtocolEvent event) { @@ -449,53 +455,38 @@ public class ServerConnection extends Connection implements Managable, AMQConnec super.send(event); } - public AtomicLong getLastIoTime() + public long getLastIoTime() { - return _lastIoTime; + return _lastIoTime.longValue(); } - void checkForNotification() + public String getClientId() { - int channelsCount = getSessionModels().size(); - if (_mBean != null && channelsCount >= getConnectionDelegate().getChannelMax()) - { - _mBean.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value"); - } + return getConnectionDelegate().getClientId(); } - private void registerConnectionMbean() + public String getClientVersion() { - try - { - _mBean = new ServerConnectionMBean(this); - _mBean.register(); - } - catch (JMException jme) - { - log.error("Unable to register mBean for ServerConnection", jme); - } + return getConnectionDelegate().getClientVersion(); } - private void unregisterConnectionMbean() + public String getPrincipalAsString() { - if (_mBean != null) - { - if (log.isDebugEnabled()) - { - log.debug("Unregistering mBean for ServerConnection" + _mBean); - } - _mBean.unregister(); - _mBean = null; - } + return getAuthorizedPrincipal().getName(); } - public String getClientId() + public long getSessionCountLimit() { - return getConnectionDelegate().getClientId(); + return getChannelMax(); } - public String getClientVersion() + public Principal getPeerPrincipal() { - return getConnectionDelegate().getClientVersion(); + return _peerPrincipal; + } + + public void setPeerPrincipal(Principal peerPrincipal) + { + _peerPrincipal = peerPrincipal; } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java index 5460c89eab..c13f63b44d 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java @@ -20,18 +20,26 @@ */ package org.apache.qpid.server.transport; -import static org.apache.qpid.transport.Connection.State.CLOSE_RCVD; - +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 java.util.StringTokenizer; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; import org.apache.qpid.common.ServerPropertyNames; import org.apache.qpid.properties.ConnectionStartProperties; import org.apache.qpid.protocol.ProtocolEngine; import org.apache.qpid.server.configuration.BrokerConfig; import org.apache.qpid.server.protocol.AMQConnectionModel; -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.auth.AuthenticationResult; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; +import org.apache.qpid.server.security.auth.manager.AuthenticationManager; import org.apache.qpid.server.subscription.Subscription_0_10; import org.apache.qpid.server.virtualhost.State; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -39,16 +47,7 @@ import org.apache.qpid.transport.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import javax.security.sasl.SaslException; -import javax.security.sasl.SaslServer; -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 java.util.StringTokenizer; +import static org.apache.qpid.transport.Connection.State.CLOSE_RCVD; public class ServerConnectionDelegate extends ServerDelegate { @@ -58,22 +57,25 @@ public class ServerConnectionDelegate extends ServerDelegate private final IApplicationRegistry _appRegistry; private int _maxNoOfChannels; private Map<String,Object> _clientProperties; + private final AuthenticationManager _authManager; - public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN) + public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN, AuthenticationManager authManager) { - this(createConnectionProperties(appRegistry.getBroker()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN); + this(createConnectionProperties(appRegistry.getBrokerConfig()), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN, authManager); } - public ServerConnectionDelegate(Map<String, Object> properties, + private ServerConnectionDelegate(Map<String, Object> properties, List<Object> locales, IApplicationRegistry appRegistry, - String localFQDN) + String localFQDN, + AuthenticationManager authManager) { - super(properties, parseToList(appRegistry.getAuthenticationManager().getMechanisms()), locales); - + super(properties, parseToList(authManager.getMechanisms()), locales); + _appRegistry = appRegistry; _localFQDN = localFQDN; - _maxNoOfChannels = ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount(); + _maxNoOfChannels = appRegistry.getConfiguration().getMaxChannelCount(); + _authManager = authManager; } private static Map<String, Object> createConnectionProperties(final BrokerConfig brokerConfig) @@ -108,18 +110,17 @@ public class ServerConnectionDelegate extends ServerDelegate return ssn; } - protected SaslServer createSaslServer(String mechanism) throws SaslException + protected SaslServer createSaslServer(Connection conn, String mechanism) throws SaslException { - return _appRegistry.getAuthenticationManager().createSaslServer(mechanism, _localFQDN); + return _authManager.createSaslServer(mechanism, _localFQDN, ((ServerConnection) conn).getPeerPrincipal()); } protected void secure(final SaslServer ss, final Connection conn, final byte[] response) { - final AuthenticationResult authResult = _appRegistry.getAuthenticationManager().authenticate(ss, response); final ServerConnection sconn = (ServerConnection) conn; - - + final AuthenticationResult authResult = _authManager.authenticate(ss, response); + if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus())) { tuneAuthorizedConnection(sconn); @@ -168,7 +169,7 @@ public class ServerConnectionDelegate extends ServerDelegate vhost = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhostName); SecurityManager.setThreadSubject(sconn.getAuthorizedSubject()); - + if(vhost != null) { sconn.setVirtualHost(vhost); @@ -194,7 +195,7 @@ public class ServerConnectionDelegate extends ServerDelegate sconn.setState(Connection.State.CLOSING); sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown virtualhost '"+vhostName+"'")); } - + } @Override @@ -216,7 +217,7 @@ public class ServerConnectionDelegate extends ServerDelegate setConnectionTuneOkChannelMax(sconn, okChannelMax); } - + @Override protected int getHeartbeatMax() { @@ -225,7 +226,7 @@ public class ServerConnectionDelegate extends ServerDelegate } @Override - protected int getChannelMax() + public int getChannelMax() { return _maxNoOfChannels; } @@ -265,7 +266,6 @@ public class ServerConnectionDelegate extends ServerDelegate if(isSessionNameUnique(atc.getName(), conn)) { super.sessionAttach(conn, atc); - ((ServerConnection)conn).checkForNotification(); } else { diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionMBean.java deleted file mode 100644 index bb545164fb..0000000000 --- a/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/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java index 6f979e035e..f82b25b3d6 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java @@ -20,17 +20,11 @@ */ package org.apache.qpid.server.transport; -import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; -import org.apache.qpid.server.message.InboundMessage; -import org.apache.qpid.server.message.MessageMetaData_0_10; -import org.apache.qpid.server.message.MessageTransferMessage; -import org.apache.qpid.server.txn.RollbackOnlyDtxException; -import org.apache.qpid.server.txn.TimeoutDtxException; -import static org.apache.qpid.util.Serial.gt; - import java.security.Principal; import java.text.MessageFormat; import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -40,18 +34,16 @@ import java.util.SortedMap; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentSkipListMap; -import java.util.concurrent.ConcurrentSkipListSet; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; - import javax.security.auth.Subject; - import org.apache.qpid.AMQException; import org.apache.qpid.AMQStoreException; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.server.TransactionTimeoutHelper; import org.apache.qpid.server.configuration.ConfigStore; import org.apache.qpid.server.configuration.ConfiguredObject; import org.apache.qpid.server.configuration.ConnectionConfig; @@ -63,7 +55,10 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.GenericActor; import org.apache.qpid.server.logging.messages.ChannelMessages; import org.apache.qpid.server.logging.subjects.ChannelLogSubject; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.message.MessageMetaData_0_10; import org.apache.qpid.server.message.MessageReference; +import org.apache.qpid.server.message.MessageTransferMessage; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.protocol.AMQConnectionModel; import org.apache.qpid.server.protocol.AMQSessionModel; @@ -82,20 +77,25 @@ import org.apache.qpid.server.txn.IncorrectDtxStateException; import org.apache.qpid.server.txn.JoinAndResumeDtxException; import org.apache.qpid.server.txn.LocalTransaction; import org.apache.qpid.server.txn.NotAssociatedDtxException; +import org.apache.qpid.server.txn.RollbackOnlyDtxException; import org.apache.qpid.server.txn.ServerTransaction; import org.apache.qpid.server.txn.SuspendAndFailDtxException; +import org.apache.qpid.server.txn.TimeoutDtxException; import org.apache.qpid.server.txn.UnknownDtxBranchException; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.transport.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class ServerSession extends Session - implements AuthorizationHolder, SessionConfig, +import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT; +import static org.apache.qpid.util.Serial.gt; + +public class ServerSession extends Session + implements AuthorizationHolder, SessionConfig, AMQSessionModel, LogSubject, AsyncAutoCommitTransaction.FutureRecorder { private static final Logger _logger = LoggerFactory.getLogger(ServerSession.class); - + private static final String NULL_DESTINTATION = UUID.randomUUID().toString(); private static final int PRODUCER_CREDIT_TOPUP_THRESHOLD = 1 << 30; private static final int UNFINISHED_COMMAND_QUEUE_THRESHOLD = 500; @@ -105,7 +105,7 @@ public class ServerSession extends Session private long _createTime = System.currentTimeMillis(); private LogActor _actor = GenericActor.getInstance(this); - private final Set<AMQQueue> _blockingQueues = new ConcurrentSkipListSet<AMQQueue>(); + private final Set<Object> _blockingEntities = Collections.synchronizedSet(new HashSet<Object>()); private final AtomicBoolean _blocking = new AtomicBoolean(false); private ChannelLogSubject _logSubject; @@ -145,6 +145,8 @@ public class ServerSession extends Session private final List<Task> _taskList = new CopyOnWriteArrayList<Task>(); + private final TransactionTimeoutHelper _transactionTimeoutHelper; + ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry) { this(connection, delegate, name, expiry, ((ServerConnection)connection).getConfig()); @@ -158,6 +160,8 @@ public class ServerSession extends Session _logSubject = new ChannelLogSubject(this); _id = getConfigStore().createId(); getConfigStore().addConfiguredObject(this); + + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject); } protected void setState(State state) @@ -167,9 +171,19 @@ public class ServerSession extends Session if (state == State.OPEN) { _actor.message(ChannelMessages.CREATE()); + if(_blocking.get()) + { + invokeBlock(); + } } } + private void invokeBlock() + { + invoke(new MessageSetFlowMode("", MessageFlowMode.CREDIT)); + invoke(new MessageStop("")); + } + private ConfigStore getConfigStore() { return getConnectionConfig().getConfigStore(); @@ -455,7 +469,7 @@ public class ServerSession extends Session { return _transaction.isTransactional(); } - + public boolean inTransaction() { return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0; @@ -621,16 +635,26 @@ 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(); } - + public Subject getAuthorizedSubject() { return getConnection().getAuthorizedSubject(); @@ -661,7 +685,8 @@ public class ServerSession extends Session return (VirtualHost) _connectionConfig.getVirtualHost(); } - public UUID getId() + @Override + public UUID getQMFId() { return _id; } @@ -755,63 +780,85 @@ public class ServerSession extends Session long openTime = currentTime - _transaction.getTransactionStartTime(); long idleTime = currentTime - _txnUpdateTime.get(); - // Log a warning on idle or open transactions - if (idleWarn > 0L && idleTime > idleWarn) - { - CurrentActor.get().message(getLogSubject(), ChannelMessages.IDLE_TXN(idleTime)); - _logger.warn("IDLE TRANSACTION ALERT " + getLogSubject().toString() + " " + idleTime + " ms"); - } - else if (openWarn > 0L && openTime > openWarn) - { - CurrentActor.get().message(getLogSubject(), ChannelMessages.OPEN_TXN(openTime)); - _logger.warn("OPEN TRANSACTION ALERT " + getLogSubject().toString() + " " + openTime + " ms"); - } - - // Close connection for idle or open transactions that have timed out - if (idleClose > 0L && idleTime > idleClose) + _transactionTimeoutHelper.logIfNecessary(idleTime, idleWarn, ChannelMessages.IDLE_TXN(idleTime), + TransactionTimeoutHelper.IDLE_TRANSACTION_ALERT); + if (_transactionTimeoutHelper.isTimedOut(idleTime, idleClose)) { getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Idle transaction timed out"); + return; } - else if (openClose > 0L && openTime > openClose) + + _transactionTimeoutHelper.logIfNecessary(openTime, openWarn, ChannelMessages.OPEN_TXN(openTime), + TransactionTimeoutHelper.OPEN_TRANSACTION_ALERT); + if (_transactionTimeoutHelper.isTimedOut(openTime, openClose)) { getConnectionModel().closeSession(this, AMQConstant.RESOURCE_ERROR, "Open transaction timed out"); + return; } } } public void block(AMQQueue queue) { + block(queue, queue.getName()); + } + + public void block() + { + block(this, "** All Queues **"); + } - if(_blockingQueues.add(queue)) - { - if(_blocking.compareAndSet(false,true)) + private void block(Object queue, String name) + { + synchronized (_blockingEntities) + { + if(_blockingEntities.add(queue)) { - invoke(new MessageSetFlowMode("", MessageFlowMode.CREDIT)); - invoke(new MessageStop("")); - _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(queue.getNameShortString().toString())); - } + + if(_blocking.compareAndSet(false,true)) + { + if(getState() == State.OPEN) + { + invokeBlock(); + } + _actor.message(_logSubject, ChannelMessages.FLOW_ENFORCED(name)); + } + } } } public void unblock(AMQQueue queue) { - if(_blockingQueues.remove(queue) && _blockingQueues.isEmpty()) + unblock((Object)queue); + } + + public void unblock() + { + unblock(this); + } + + private void unblock(Object queue) + { + synchronized(_blockingEntities) { - if(_blocking.compareAndSet(true,false) && !isClosing()) + if(_blockingEntities.remove(queue) && _blockingEntities.isEmpty()) { + if(_blocking.compareAndSet(true,false) && !isClosing()) + { - _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); - MessageFlow mf = new MessageFlow(); - mf.setUnit(MessageCreditUnit.MESSAGE); - mf.setDestination(""); - _outstandingCredit.set(Integer.MAX_VALUE); - mf.setValue(Integer.MAX_VALUE); - invoke(mf); + _actor.message(_logSubject, ChannelMessages.FLOW_REMOVED()); + MessageFlow mf = new MessageFlow(); + mf.setUnit(MessageCreditUnit.MESSAGE); + mf.setDestination(""); + _outstandingCredit.set(Integer.MAX_VALUE); + mf.setValue(Integer.MAX_VALUE); + invoke(mf); + } } } } @@ -1020,7 +1067,12 @@ public class ServerSession extends Session public int compareTo(AMQSessionModel session) { - return getId().compareTo(session.getId()); + return getQMFId().compareTo(session.getQMFId()); } + @Override + public int getConsumerCount() + { + return _subscriptions.values().size(); + } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java index 79a8bc0e4c..05963ee874 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java +++ b/java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java @@ -99,9 +99,9 @@ public class ServerSessionDelegate extends SessionDelegate Object newOutstanding = ((ServerSession)session).getAsyncCommandMark(); if(newOutstanding == null || newOutstanding == asyncCommandMark) { - session.processed(method); + session.processed(method); } - + if(newOutstanding != null) { ((ServerSession)session).completeAsyncCommands(); @@ -240,13 +240,13 @@ public class ServerSessionDelegate extends SessionDelegate } FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L); - + FilterManager filterManager = null; - try + try { filterManager = FilterManagerFactory.createManager(method.getArguments()); - } - catch (AMQException amqe) + } + catch (AMQException amqe) { exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Exception Creating FilterManager"); return; @@ -257,7 +257,7 @@ public class ServerSessionDelegate extends SessionDelegate method.getAcceptMode(), method.getAcquireMode(), MessageFlowMode.WINDOW, - creditManager, + creditManager, filterManager, method.getArguments()); @@ -297,13 +297,13 @@ public class ServerSessionDelegate extends SessionDelegate final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr); messageMetaData.setConnectionReference(((ServerSession)ssn).getReference()); - + if (!getVirtualHost(ssn).getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName())) { ExecutionErrorCode errorCode = ExecutionErrorCode.UNAUTHORIZED_ACCESS; String description = "Permission denied: exchange-name '" + exchange.getName() + "'"; exception(ssn, xfr, errorCode, description); - + return; } @@ -807,7 +807,7 @@ public class ServerSessionDelegate extends SessionDelegate } } - // TODO decouple AMQException and AMQConstant error codes + // TODO decouple AMQException and AMQConstant error codes private void exception(Session session, Method method, AMQException exception, String message) { ExecutionErrorCode errorCode = ExecutionErrorCode.INTERNAL_ERROR; @@ -823,7 +823,7 @@ public class ServerSessionDelegate extends SessionDelegate } } String description = message + "': " + exception.getMessage(); - + exception(session, method, errorCode, description); } @@ -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); } @@ -1349,9 +1345,9 @@ public class ServerSessionDelegate extends SessionDelegate + " as exclusive queue with same name " + "declared on another session"; ExecutionErrorCode errorCode = ExecutionErrorCode.RESOURCE_LOCKED; - + exception(session, method, errorCode, description); - + return; } } @@ -1389,7 +1385,7 @@ public class ServerSessionDelegate extends SessionDelegate { String owner = body.getExclusive() ? session.getClientID() : null; - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateUUID(), queueName, body.getDurable(), owner, + final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateQueueUUID(queueName, virtualHost.getName()), queueName, body.getDurable(), owner, body.getAutoDelete(), body.getExclusive(), virtualHost, body.getArguments()); return queue; @@ -1436,7 +1432,7 @@ public class ServerSessionDelegate extends SessionDelegate else { VirtualHost virtualHost = getVirtualHost(session); - + try { queue.delete(); diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java index d446434d24..efd7850a49 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AsyncAutoCommitTransaction.java @@ -44,11 +44,16 @@ import java.util.List; */ public class AsyncAutoCommitTransaction implements ServerTransaction { + static final String QPID_STRICT_ORDER_WITH_MIXED_DELIVERY_MODE = "qpid.strict_order_with_mixed_delivery_mode"; + protected static final Logger _logger = Logger.getLogger(AsyncAutoCommitTransaction.class); private final MessageStore _messageStore; private final FutureRecorder _futureRecorder; + //Set true to ensure strict ordering when enqueing messages with mixed delivery mode, i.e. disable async persistence + private boolean _strictOrderWithMixedDeliveryMode = Boolean.getBoolean(QPID_STRICT_ORDER_WITH_MIXED_DELIVERY_MODE); + public static interface FutureRecorder { public void recordFuture(StoreFuture future, Action action); @@ -129,6 +134,23 @@ public class AsyncAutoCommitTransaction implements ServerTransaction } } + private void addEnqueueFuture(final StoreFuture future, final Action action, boolean persistent) + { + if(action != null) + { + // For persistent messages, do not synchronously invoke postCommit even if the future is completed. + // Otherwise, postCommit (which actually does the enqueuing) might be called on successive messages out of order. + if(future.isComplete() && !persistent && !_strictOrderWithMixedDeliveryMode) + { + action.postCommit(); + } + else + { + _futureRecorder.recordFuture(future, action); + } + } + } + public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction) { Transaction txn = null; @@ -203,7 +225,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction { future = StoreFuture.IMMEDIATE_FUTURE; } - addFuture(future, postTransactionAction); + addEnqueueFuture(future, postTransactionAction, message.isPersistent()); postTransactionAction = null; } catch (AMQException e) @@ -257,7 +279,7 @@ public class AsyncAutoCommitTransaction implements ServerTransaction { future = StoreFuture.IMMEDIATE_FUTURE; } - addFuture(future, postTransactionAction); + addEnqueueFuture(future, postTransactionAction, message.isPersistent()); postTransactionAction = null; diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java index 3ac71fc6a6..fb32b654ce 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxBranch.java @@ -98,12 +98,29 @@ public class DtxBranch public void setTimeout(long timeout) { + if(_logger.isDebugEnabled()) + { + _logger.debug("Setting timeout to " + timeout + "s for DtxBranch " + _xid); + } + if(_timeoutFuture != null) { - _timeoutFuture.cancel(false); + if(_logger.isDebugEnabled()) + { + _logger.debug("Attempting to cancel previous timeout task future for DtxBranch " + _xid); + } + + boolean succeeded = _timeoutFuture.cancel(false); + + if(_logger.isDebugEnabled()) + { + _logger.debug("Cancelling previous timeout task " + (succeeded ? "succeeded" : "failed") + + " for DtxBranch " + _xid); + } } + _timeout = timeout; - _expiration = timeout == 0 ? 0 : System.currentTimeMillis() + timeout; + _expiration = timeout == 0 ? 0 : System.currentTimeMillis() + (1000 * timeout); if(_timeout == 0) { @@ -111,10 +128,23 @@ public class DtxBranch } else { - _timeoutFuture = _vhost.scheduleTask(_timeout, new Runnable() + long delay = 1000*_timeout; + + if(_logger.isDebugEnabled()) + { + _logger.debug("Scheduling timeout and rollback after " + delay/1000 + + "s for DtxBranch " + _xid); + } + + _timeoutFuture = _vhost.scheduleTask(delay, new Runnable() { public void run() { + if(_logger.isDebugEnabled()) + { + _logger.debug("Timing out DtxBranch " + _xid); + } + setState(State.TIMEDOUT); try { @@ -122,8 +152,7 @@ public class DtxBranch } catch (AMQStoreException e) { - _logger.error("Unexpected error when attempting to rollback XA transaction ("+ - _xid + ") due to timeout", e); + _logger.error("Unexpected error when attempting to rollback DtxBranch "+ _xid + " due to timeout", e); throw new RuntimeException(e); } } @@ -199,6 +228,10 @@ public class DtxBranch public void prepare() throws AMQStoreException { + if(_logger.isDebugEnabled()) + { + _logger.debug("Performing prepare for DtxBranch " + _xid); + } Transaction txn = _store.newTransaction(); txn.recordXid(_xid.getFormat(), @@ -213,12 +246,27 @@ public class DtxBranch public synchronized void rollback() throws AMQStoreException { + if(_logger.isDebugEnabled()) + { + _logger.debug("Performing rollback for DtxBranch " + _xid); + } + if(_timeoutFuture != null) { - _timeoutFuture.cancel(false); + if(_logger.isDebugEnabled()) + { + _logger.debug("Attempting to cancel previous timeout task future for DtxBranch " + _xid); + } + + boolean succeeded = _timeoutFuture.cancel(false); _timeoutFuture = null; - } + if(_logger.isDebugEnabled()) + { + _logger.debug("Cancelling previous timeout task " + (succeeded ? "succeeded" : "failed") + + " for DtxBranch " + _xid); + } + } if(_transaction != null) { @@ -240,10 +288,26 @@ public class DtxBranch public void commit() throws AMQStoreException { + if(_logger.isDebugEnabled()) + { + _logger.debug("Performing commit for DtxBranch " + _xid); + } + if(_timeoutFuture != null) { - _timeoutFuture.cancel(false); + if(_logger.isDebugEnabled()) + { + _logger.debug("Attempting to cancel previous timeout task future for DtxBranch " + _xid); + } + + boolean succeeded = _timeoutFuture.cancel(false); _timeoutFuture = null; + + if(_logger.isDebugEnabled()) + { + _logger.debug("Cancelling previous timeout task " + (succeeded ? "succeeded" : "failed") + + " for DtxBranch " + _xid); + } } if(_transaction == null) @@ -342,7 +406,7 @@ public class DtxBranch } catch(AMQStoreException e) { - _logger.error("Error while closing XA branch", e); + _logger.error("Error while closing DtxBranch " + _xid, e); } } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java index 5c54c1164f..117beb82ef 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/DtxRegistry.java @@ -37,7 +37,7 @@ public class DtxRegistry private static final class ComparableXid { private final Xid _xid; - + private ComparableXid(Xid xid) { _xid = xid; @@ -58,7 +58,7 @@ public class DtxRegistry ComparableXid that = (ComparableXid) o; return compareBytes(_xid.getBranchId(), that._xid.getBranchId()) - && compareBytes(_xid.getGlobalId(), that._xid.getGlobalId()); + && compareBytes(_xid.getGlobalId(), that._xid.getGlobalId()); } private static boolean compareBytes(byte[] a, byte[] b) @@ -94,7 +94,7 @@ public class DtxRegistry return result; } } - + public synchronized DtxBranch getBranch(Xid xid) { return _branches.get(new ComparableXid(xid)); @@ -116,7 +116,7 @@ public class DtxRegistry return (_branches.remove(new ComparableXid(branch.getXid())) != null); } - public void commit(Xid id, boolean onePhase) + public synchronized void commit(Xid id, boolean onePhase) throws IncorrectDtxStateException, UnknownDtxBranchException, AMQStoreException, RollbackOnlyDtxException, TimeoutDtxException { DtxBranch branch = getBranch(id); @@ -204,7 +204,7 @@ public class DtxRegistry } } - public void rollback(Xid id) + public synchronized void rollback(Xid id) throws IncorrectDtxStateException, UnknownDtxBranchException, AMQStoreException, TimeoutDtxException @@ -318,6 +318,7 @@ public class DtxRegistry branch.disassociateSession(session); } } + } diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java index 11401ebd65..3fbcff7e2c 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java +++ b/java/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java @@ -1,4 +1,3 @@ -package org.apache.qpid.server.txn; /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -19,7 +18,9 @@ package org.apache.qpid.server.txn; * under the License. * */ +package org.apache.qpid.server.txn; +import org.apache.qpid.server.store.StoreFuture; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,6 +51,7 @@ public class LocalTransaction implements ServerTransaction private volatile Transaction _transaction; private MessageStore _transactionLog; private long _txnStartTime = 0L; + private StoreFuture _asyncTran; public LocalTransaction(MessageStore transactionLog) { @@ -68,11 +70,13 @@ public class LocalTransaction implements ServerTransaction public void addPostTransactionAction(Action postTransactionAction) { + sync(); _postTransactionActions.add(postTransactionAction); } public void dequeue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction) { + sync(); _postTransactionActions.add(postTransactionAction); if(message.isPersistent() && queue.isDurable()) @@ -98,6 +102,7 @@ public class LocalTransaction implements ServerTransaction public void dequeue(Collection<QueueEntry> queueEntries, Action postTransactionAction) { + sync(); _postTransactionActions.add(postTransactionAction); try @@ -131,10 +136,7 @@ public class LocalTransaction implements ServerTransaction { try { - for(Action action : _postTransactionActions) - { - action.onRollback(); - } + doRollbackActions(); } finally { @@ -151,7 +153,7 @@ public class LocalTransaction implements ServerTransaction } finally { - resetDetails(); + resetDetails(); } } @@ -176,6 +178,7 @@ public class LocalTransaction implements ServerTransaction public void enqueue(BaseQueue queue, EnqueableMessage message, Action postTransactionAction) { + sync(); _postTransactionActions.add(postTransactionAction); if(message.isPersistent() && queue.isDurable()) @@ -201,6 +204,7 @@ public class LocalTransaction implements ServerTransaction public void enqueue(List<? extends BaseQueue> queues, EnqueableMessage message, Action postTransactionAction, long currentTime) { + sync(); _postTransactionActions.add(postTransactionAction); if (_txnStartTime == 0L) @@ -239,11 +243,13 @@ public class LocalTransaction implements ServerTransaction public void commit() { + sync(); commit(null); } public void commit(Runnable immediateAction) { + sync(); try { if(_transaction != null) @@ -256,29 +262,137 @@ public class LocalTransaction implements ServerTransaction immediateAction.run(); } - for(int i = 0; i < _postTransactionActions.size(); i++) + doPostTransactionActions(); + } + catch (Exception e) + { + _logger.error("Failed to commit transaction", e); + + doRollbackActions(); + throw new RuntimeException("Failed to commit transaction", e); + } + finally + { + resetDetails(); + } + } + + private void doRollbackActions() + { + for(Action action : _postTransactionActions) + { + action.onRollback(); + } + } + + public StoreFuture commitAsync(final Runnable deferred) + { + sync(); + try + { + StoreFuture future = StoreFuture.IMMEDIATE_FUTURE; + if(_transaction != null) { - _postTransactionActions.get(i).postCommit(); + future = new StoreFuture() + { + private volatile boolean _completed = false; + private StoreFuture _underlying = _transaction.commitTranAsync(); + + @Override + public boolean isComplete() + { + return _completed || checkUnderlyingCompletion(); + } + + @Override + public void waitForCompletion() + { + if(!_completed) + { + _underlying.waitForCompletion(); + checkUnderlyingCompletion(); + } + } + + private synchronized boolean checkUnderlyingCompletion() + { + if(!_completed && _underlying.isComplete()) + { + completeDeferredWork(); + _completed = true; + } + return _completed; + + } + + private void completeDeferredWork() + { + try + { + doPostTransactionActions(); + deferred.run(); + + } + catch (Exception e) + { + _logger.error("Failed to commit transaction", e); + + doRollbackActions(); + throw new RuntimeException("Failed to commit transaction", e); + } + finally + { + resetDetails(); + } + } + + }; + _asyncTran = future; } + else + { + try + { + doPostTransactionActions(); + + deferred.run(); + } + finally + { + resetDetails(); + } + } + + return future; } catch (Exception e) { _logger.error("Failed to commit transaction", e); - - for(Action action : _postTransactionActions) + try { - action.onRollback(); + doRollbackActions(); + } + finally + { + resetDetails(); } throw new RuntimeException("Failed to commit transaction", e); } - finally + + + } + + private void doPostTransactionActions() + { + for(int i = 0; i < _postTransactionActions.size(); i++) { - resetDetails(); + _postTransactionActions.get(i).postCommit(); } } public void rollback() { + sync(); try { if(_transaction != null) @@ -295,10 +409,7 @@ public class LocalTransaction implements ServerTransaction { try { - for(Action action : _postTransactionActions) - { - action.onRollback(); - } + doRollbackActions(); } finally { @@ -306,9 +417,19 @@ public class LocalTransaction implements ServerTransaction } } } - + + public void sync() + { + if(_asyncTran != null) + { + _asyncTran.waitForCompletion(); + _asyncTran = null; + } + } + private void resetDetails() { + _asyncTran = null; _transaction = null; _postTransactionActions.clear(); _txnStartTime = 0L; diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java index 523bafb8e1..1b0e50fd34 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java @@ -44,9 +44,9 @@ public abstract class HouseKeepingTask implements Runnable final public void run() { - // Don't need to undo this as this is a thread pool thread so will - // always go through here before we do any real work. + String originalThreadName = Thread.currentThread().getName(); Thread.currentThread().setName(_name); + CurrentActor.set(new AbstractActor(_rootLogger) { @Override @@ -67,6 +67,9 @@ public abstract class HouseKeepingTask implements Runnable finally { CurrentActor.remove(); + + // eagerly revert the thread name to make thread dumps more meaningful if captured after task has finished + Thread.currentThread().setName(originalThreadName); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java index fb50b3e289..55e2539dcf 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/State.java @@ -25,5 +25,7 @@ public enum State INITIALISING, ACTIVE, PASSIVE, - STOPPED + STOPPED, + /** Terminal state that signifies the virtual host has experienced an unexpected condition. */ + ERRORED } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java index 489b985222..f810360662 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java +++ b/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,10 +61,10 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo void close(); - ManagedObject getManagedObject(); - UUID getBrokerId(); + UUID getId(); + void scheduleHouseKeepingTask(long period, HouseKeepingTask task); long getHouseKeepingTaskCount(); @@ -74,7 +73,7 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo int getHouseKeepingPoolSize(); - void setHouseKeepingPoolSize(int newSize); + void setHouseKeepingPoolSize(int newSize); int getHouseKeepingActiveCount(); @@ -102,4 +101,8 @@ public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHo ScheduledFuture<?> scheduleTask(long delay, Runnable timeoutTask); State getState(); + + public void block(); + + public void unblock(); } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java index e956806823..ea2f0f15e4 100755 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java @@ -76,15 +76,12 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa private final VirtualHost _virtualHost; - private MessageStoreLogSubject _logSubject; - - private MessageStore _store; - private final Map<String, Integer> _queueRecoveries = new TreeMap<String, Integer>(); - private Map<Long, AbstractServerMessageImpl> _recoveredMessages = new HashMap<Long, AbstractServerMessageImpl>(); - private Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>(); - + private final Map<Long, AbstractServerMessageImpl> _recoveredMessages = new HashMap<Long, AbstractServerMessageImpl>(); + private final Map<Long, StoredMessage> _unusedMessages = new HashMap<Long, StoredMessage>(); + private MessageStoreLogSubject _logSubject; + private MessageStore _store; public VirtualHostConfigRecoveryHandler(VirtualHost virtualHost) { @@ -100,7 +97,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 +108,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)); @@ -120,12 +128,12 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa } catch (AMQException e) { - // TODO - throw new RuntimeException(e); + throw new RuntimeException("Error recovering queue uuid " + id + " name " + queueName, e); } } - public ExchangeRecoveryHandler completeQueueRecovery() + @Override + public BindingRecoveryHandler completeQueueRecovery() { return this; } @@ -145,19 +153,17 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa } catch (AMQException e) { - // TODO - throw new RuntimeException(e); + throw new RuntimeException("Error recovering exchange uuid " + id + " name " + exchangeName, e); } } - public BindingRecoveryHandler completeExchangeRecovery() + public QueueRecoveryHandler completeExchangeRecovery() { return this; } public StoredMessageRecoveryHandler begin() { - // TODO - log begin return this; } @@ -182,7 +188,6 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa public void completeMessageRecovery() { - //TODO - log end } public BridgeRecoveryHandler brokerLink(final UUID id, diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java index 9b113525d4..d9dc0aa64e 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java +++ b/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,10 @@ 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.model.UUIDGenerator; 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; @@ -59,37 +66,25 @@ import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.stats.StatisticsCounter; import org.apache.qpid.server.store.Event; import org.apache.qpid.server.store.EventListener; +import org.apache.qpid.server.store.HAMessageStore; import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.MessageStoreFactory; import org.apache.qpid.server.store.OperationalLoggingListener; 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 +public class VirtualHostImpl implements VirtualHost, IConnectionRegistry.RegistryChangeListener, EventListener { private static final Logger _logger = Logger.getLogger(VirtualHostImpl.class); private static final int HOUSEKEEPING_SHUTDOWN_TIMEOUT = 5; - private final UUID _id; + private final UUID _qmfId; private final String _name; + private final UUID _id; + private final long _createTime = System.currentTimeMillis(); private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>(); @@ -104,10 +99,6 @@ public class VirtualHostImpl implements VirtualHost private final VirtualHostConfiguration _vhostConfig; - private final VirtualHostMBean _virtualHostMBean; - - private final AMQBrokerManagerMBean _brokerMBean; - private final QueueRegistry _queueRegistry; private final ExchangeRegistry _exchangeRegistry; @@ -122,13 +113,12 @@ public class VirtualHostImpl implements VirtualHost private final MessageStore _messageStore; - private State _state = State.INITIALISING; - - private boolean _statisticsEnabled = false; + private volatile State _state = State.INITIALISING; private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived; private final Map<String, LinkRegistry> _linkRegistry = new HashMap<String, LinkRegistry>(); + private boolean _blocked; public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig) throws Exception { @@ -143,20 +133,21 @@ public class VirtualHostImpl implements VirtualHost } _appRegistry = appRegistry; - _brokerConfig = _appRegistry.getBroker(); + _brokerConfig = _appRegistry.getBrokerConfig(); _vhostConfig = hostConfig; _name = _vhostConfig.getName(); _dtxRegistry = new DtxRegistry(); - _id = _appRegistry.getConfigStore().createId(); + _qmfId = _appRegistry.getConfigStore().createId(); + _id = UUIDGenerator.generateVhostUUID(_name); CurrentActor.get().message(VirtualHostMessages.CREATED(_name)); - _virtualHostMBean = new VirtualHostMBean(); _securityManager = new SecurityManager(_appRegistry.getSecurityManager()); _securityManager.configureHostPlugins(_vhostConfig); _connectionRegistry = new ConnectionRegistry(); + _connectionRegistry.addRegistryChangeListener(this); _houseKeepingTasks = new ScheduledThreadPoolExecutor(_vhostConfig.getHouseKeepingThreadCount()); @@ -169,15 +160,16 @@ public class VirtualHostImpl implements VirtualHost _bindingFactory = new BindingFactory(this); - _brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean); - - _messageStore = initialiseMessageStore(hostConfig.getMessageStoreFactoryClass()); + _messageStore = initialiseMessageStore(hostConfig.getMessageStoreClass()); configureMessageStore(hostConfig); activateNonHAMessageStore(); initialiseStatistics(); + + _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); + _messageStore.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); } public IConnectionRegistry getConnectionRegistry() @@ -195,6 +187,12 @@ public class VirtualHostImpl implements VirtualHost return _id; } + @Override + public UUID getQMFId() + { + return _qmfId; + } + public VirtualHostConfigType getConfigType() { return VirtualHostConfigType.getInstance(); @@ -324,20 +322,19 @@ public class VirtualHostImpl implements VirtualHost } - private MessageStore initialiseMessageStore(final String messageStoreFactoryClass) throws Exception + private MessageStore initialiseMessageStore(final String messageStoreClass) throws Exception { - final Class<?> clazz = Class.forName(messageStoreFactoryClass); + final Class<?> clazz = Class.forName(messageStoreClass); final Object o = clazz.newInstance(); - if (!(o instanceof MessageStoreFactory)) + if (!(o instanceof MessageStore)) { - throw new ClassCastException("Message store factory class must implement " + MessageStoreFactory.class + + throw new ClassCastException("Message store factory class must implement " + MessageStore.class + ". Class " + clazz + " does not."); } - final MessageStoreFactory messageStoreFactory = (MessageStoreFactory) o; - final MessageStore messageStore = messageStoreFactory.createMessageStore(); - final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, messageStoreFactory.getStoreClassName()); + final MessageStore messageStore = (MessageStore) o; + final MessageStoreLogSubject storeLogSubject = new MessageStoreLogSubject(this, clazz.getSimpleName()); OperationalLoggingListener.listen(messageStore, storeLogSubject); messageStore.addEventListener(new BeforeActivationListener(), Event.BEFORE_ACTIVATE); @@ -361,7 +358,10 @@ public class VirtualHostImpl implements VirtualHost private void activateNonHAMessageStore() throws Exception { - _messageStore.activate(); + if (!(_messageStore instanceof HAMessageStore)) + { + _messageStore.activate(); + } } private void initialiseModel(VirtualHostConfiguration config) throws ConfigurationException, AMQException @@ -534,16 +534,6 @@ public class VirtualHostImpl implements VirtualHost CurrentActor.get().message(VirtualHostMessages.CLOSED()); } - public ManagedObject getBrokerMBean() - { - return _brokerMBean; - } - - public ManagedObject getManagedObject() - { - return _virtualHostMBean; - } - public UUID getBrokerId() { return _appRegistry.getBrokerId(); @@ -558,54 +548,48 @@ public class VirtualHostImpl implements VirtualHost { return _bindingFactory; } - + 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); } - + 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 (AMQConnectionModel connection : _connectionRegistry.getConnections()) { connection.resetStatistics(); @@ -614,25 +598,12 @@ public class VirtualHostImpl implements VirtualHost 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); @@ -699,107 +670,155 @@ public class VirtualHostImpl implements VirtualHost return _dtxRegistry; } - @Override public String toString() { return _name; } - @Override public State getState() { return _state; } - - /** - * 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 void block() { - public VirtualHostMBean() throws NotCompliantMBeanException + synchronized (_connectionRegistry) { - super(ManagedVirtualHost.class, ManagedVirtualHost.TYPE); + if(!_blocked) + { + _blocked = true; + for(AMQConnectionModel conn : _connectionRegistry.getConnections()) + { + conn.block(); + } + } } + } - public String getObjectInstanceName() - { - return ObjectName.quote(_name); - } - public String getName() + public void unblock() + { + synchronized (_connectionRegistry) { - return _name; + if(_blocked) + { + _blocked = false; + for(AMQConnectionModel conn : _connectionRegistry.getConnections()) + { + conn.unblock(); + } + } } + } - public VirtualHostImpl getVirtualHost() + public void connectionRegistered(final AMQConnectionModel connection) + { + if(_blocked) { - return VirtualHostImpl.this; + connection.block(); } } - private final class BeforeActivationListener implements EventListener + public void connectionUnregistered(final AMQConnectionModel connection) { - @Override - public void event(Event event) + } + + public void event(final Event event) + { + switch(event) { - try - { - _exchangeRegistry.initialise(); - initialiseModel(_vhostConfig); - } catch (Exception e) - { - throw new RuntimeException("Failed to initialise virtual host after state change", e); - } + case PERSISTENT_MESSAGE_SIZE_OVERFULL: + block(); + break; + case PERSISTENT_MESSAGE_SIZE_UNDERFULL: + unblock(); + break; } } - private final class AfterActivationListener implements EventListener + private final class BeforeActivationListener implements EventListener + { + @Override + public void event(Event event) + { + try + { + _exchangeRegistry.initialise(); + initialiseModel(_vhostConfig); + } + catch (Exception e) + { + throw new RuntimeException("Failed to initialise virtual host after state change", e); + } + } + } + + private final class AfterActivationListener implements EventListener + { + @Override + public void event(Event event) + { + State finalState = State.ERRORED; + + try + { + initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod()); + finalState = State.ACTIVE; + } + finally + { + _state = finalState; + reportIfError(_state); + } + } + } + + private final class BeforePassivationListener implements EventListener { - @Override public void event(Event event) { - initialiseHouseKeeping(_vhostConfig.getHousekeepingCheckPeriod()); + State finalState = State.ERRORED; + try { - _brokerMBean.register(); - } catch (JMException e) + /* the approach here is not ideal as there is a race condition where a + * queue etc could be created while the virtual host is on the way to + * the passivated state. However the store state change from MASTER to UNKNOWN + * is documented as exceptionally rare.. + */ + + _connectionRegistry.close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT); + removeHouseKeepingTasks(); + + _queueRegistry.stopAllAndUnregisterMBeans(); + _exchangeRegistry.clearAndUnregisterMbeans(); + _dtxRegistry.close(); + + finalState = State.PASSIVE; + } + finally { - throw new RuntimeException("Failed to register virtual host mbean for virtual host " + getName(), e); + _state = finalState; + reportIfError(_state); } - - _state = State.ACTIVE; } + } - public class BeforePassivationListener implements EventListener + private final class BeforeCloseListener implements EventListener { - @Override public void event(Event event) { - _connectionRegistry.close(IConnectionRegistry.VHOST_PASSIVATE_REPLY_TEXT); - _brokerMBean.unregister(); - removeHouseKeepingTasks(); - - _queueRegistry.stopAllAndUnregisterMBeans(); - _exchangeRegistry.clearAndUnregisterMbeans(); - _dtxRegistry.close(); - - _state = State.PASSIVE; + shutdownHouseKeeping(); } } - private final class BeforeCloseListener implements EventListener + private void reportIfError(State state) { - @Override - public void event(Event event) + if (state == State.ERRORED) { - _brokerMBean.unregister(); - shutdownHouseKeeping(); + CurrentActor.get().message(VirtualHostMessages.ERRORED()); } } diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java index ef621a166a..1be472844a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostRegistry.java +++ b/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); + } + }
diff --git a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java index 2c6705bb3b..bd2e30449a 100644 --- a/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java +++ b/java/broker/src/main/java/org/apache/qpid/server/virtualhost/plugins/SlowConsumerDetection.java @@ -1,5 +1,6 @@ /* * + * 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 diff --git a/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java b/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java deleted file mode 100644 index c06ce5e31a..0000000000 --- a/java/broker/src/test/java/org/apache/log4j/xml/QpidLog4JConfiguratorTest.java +++ /dev/null @@ -1,395 +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.log4j.xml; - - -import junit.framework.TestCase; -import org.apache.log4j.xml.QpidLog4JConfigurator.IllegalLoggerLevelException; - -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -public class QpidLog4JConfiguratorTest extends TestCase -{ - private static final String NEWLINE = System.getProperty("line.separator"); - - private File _testConfigFile; - - private File createTempTestLog4JConfig(String loggerLevel,String rootLoggerLevel, boolean missingTagClose, boolean incorrectAttribute) - { - File tmpFile = null; - try - { - tmpFile = File.createTempFile("QpidLog4JConfiguratorTestLog4jConfig", ".tmp"); - tmpFile.deleteOnExit(); - - FileWriter fstream = new FileWriter(tmpFile); - BufferedWriter writer = new BufferedWriter(fstream); - - writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+NEWLINE); - writer.write("<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"+NEWLINE); - - writer.write("<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"null\" " + - "threshold=\"null\">"+NEWLINE); - - writer.write(" <appender class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE); - writer.write(" <layout class=\"org.apache.log4j.PatternLayout\">"+NEWLINE); - writer.write(" <param name=\"ConversionPattern\" value=\"%d %-5p [%t] %C{2} (%F:%L) - %m%n\"/>"+NEWLINE); - writer.write(" </layout>"+NEWLINE); - writer.write(" </appender>"+NEWLINE); - - String closeTag="/"; - if(missingTagClose) - { - closeTag=""; - } - - //Example of a 'category' with a 'priority' - writer.write(" <category additivity=\"true\" name=\"logger1\">"+NEWLINE); - writer.write(" <priority value=\"" + loggerLevel+ "\"" + closeTag + ">"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </category>"+NEWLINE); - - String attributeName="value"; - if(incorrectAttribute) - { - attributeName="values"; - } - - //Example of a 'category' with a 'level' - writer.write(" <category additivity=\"true\" name=\"logger2\">"+NEWLINE); - writer.write(" <level " + attributeName + "=\"" + loggerLevel+ "\"/>"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </category>"+NEWLINE); - - //Example of a 'logger' with a 'level' - writer.write(" <logger additivity=\"true\" name=\"logger3\">"+NEWLINE); - writer.write(" <level value=\"" + loggerLevel+ "\"/>"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </logger>"+NEWLINE); - - //'root' logger - writer.write(" <root>"+NEWLINE); - writer.write(" <priority value=\"" + rootLoggerLevel+ "\"/>"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </root>"+NEWLINE); - - writer.write("</log4j:configuration>"+NEWLINE); - - writer.flush(); - writer.close(); - } - catch (IOException e) - { - fail("Unable to create temporary test log4j configuration"); - } - - return tmpFile; - } - - - - //******* Test Methods ******* // - - public void testCheckLevelsAndStrictParser() - { - //try the valid logger levels - _testConfigFile = createTempTestLog4JConfig("all", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("trace", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("debug", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("warn", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("error", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("fatal", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("off", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("null", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("inherited", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - //now try an invalid logger level - _testConfigFile = createTempTestLog4JConfig("madeup", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - fail("IllegalLoggerLevelException expected, invalid levels used"); - } - catch (IllegalLoggerLevelException e) - { - //expected, ignore - } - catch (IOException e) - { - fail("Incorrect Exception, expected an IllegalLoggerLevelException"); - } - - - - //now try the valid rootLogger levels - _testConfigFile = createTempTestLog4JConfig("info", "all", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "trace", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "debug", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "info", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "warn", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "error", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "fatal", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "off", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "null", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "inherited", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - _testConfigFile = createTempTestLog4JConfig("info", "debug", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - } - catch (Exception e) - { - fail("No exception expected, valid levels and xml were used"); - } - - //now try an invalid logger level - _testConfigFile = createTempTestLog4JConfig("info", "madeup", false, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - fail("IllegalLoggerLevelException expected, invalid levels used"); - } - catch (IllegalLoggerLevelException e) - { - //expected, ignore - } - catch (IOException e) - { - fail("Incorrect Exception, expected an IllegalLoggerLevelException"); - } - - - - //now try invalid xml - _testConfigFile = createTempTestLog4JConfig("info", "info", true, false); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - fail("IOException expected, malformed XML used"); - } - catch (IllegalLoggerLevelException e) - { - fail("Incorrect Exception, expected an IOException"); - } - catch (IOException e) - { - //expected, ignore - } - - _testConfigFile = createTempTestLog4JConfig("info", "info", false, true); - try - { - QpidLog4JConfigurator.checkLoggerLevels(_testConfigFile.getAbsolutePath()); - fail("IOException expected, malformed XML used"); - } - catch (IllegalLoggerLevelException e) - { - //expected, ignore - } - catch (IOException e) - { - fail("Incorrect Exception, expected an IllegalLoggerLevelException"); - } - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java deleted file mode 100644 index 5c500771c2..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/AMQBrokerManagerMBeanTest.java +++ /dev/null @@ -1,195 +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.commons.configuration.XMLConfiguration; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.ManagedBroker; -import org.apache.qpid.server.configuration.ServerConfiguration; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.exchange.ExchangeRegistry; -import org.apache.qpid.server.logging.SystemOutMessageLogger; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.TestLogActor; -import org.apache.qpid.server.queue.AMQPriorityQueue; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.queue.QueueRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory; -import org.apache.qpid.server.util.TestApplicationRegistry; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.server.virtualhost.VirtualHostImpl; -import org.apache.qpid.test.utils.QpidTestCase; - -import java.util.HashMap; -import java.util.Map; - -public class AMQBrokerManagerMBeanTest extends QpidTestCase -{ - private QueueRegistry _queueRegistry; - private ExchangeRegistry _exchangeRegistry; - private VirtualHost _vHost; - - public void testExchangeOperations() throws Exception - { - String exchange1 = "testExchange1_" + System.currentTimeMillis(); - String exchange2 = "testExchange2_" + System.currentTimeMillis(); - String exchange3 = "testExchange3_" + System.currentTimeMillis(); - - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) == null); - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) == null); - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null); - - - ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject()); - mbean.createNewExchange(exchange1, "direct", false); - mbean.createNewExchange(exchange2, "topic", false); - mbean.createNewExchange(exchange3, "headers", false); - - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) != null); - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) != null); - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) != null); - - mbean.unregisterExchange(exchange1); - mbean.unregisterExchange(exchange2); - mbean.unregisterExchange(exchange3); - - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange1)) == null); - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange2)) == null); - assertTrue(_exchangeRegistry.getExchange(new AMQShortString(exchange3)) == null); - } - - public void testQueueOperations() throws Exception - { - String queueName = "testQueue_" + System.currentTimeMillis(); - - ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject()); - - assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null); - - mbean.createNewQueue(queueName, "test", false); - assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) != null); - - mbean.deleteQueue(queueName); - assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) == null); - } - - public void testCreateNewQueueBindsToDefaultExchange() throws Exception - { - String queueName = "testQueue_" + System.currentTimeMillis(); - - ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject()); - ExchangeRegistry exReg = _vHost.getExchangeRegistry(); - Exchange defaultExchange = exReg.getDefaultExchange(); - - mbean.createNewQueue(queueName, "test", false); - assertTrue(_queueRegistry.getQueue(new AMQShortString(queueName)) != null); - - assertTrue("New queue should be bound to default exchange", defaultExchange.isBound(new AMQShortString(queueName))); - } - - /** - * Tests that setting the {@link AMQQueueFactory#X_QPID_MAXIMUM_DELIVERY_COUNT} argument does cause the - * maximum delivery count to be set on the Queue. - */ - public void testCreateNewQueueWithMaximumDeliveryCount() throws Exception - { - final Map<String,Object> args = new HashMap<String, Object>(); - args.put(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, 5); - - final AMQShortString queueName = new AMQShortString("testCreateNewQueueWithMaximumDeliveryCount"); - - final QueueRegistry qReg = _vHost.getQueueRegistry(); - - assertNull("The queue should not yet exist", qReg.getQueue(queueName)); - - final ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject()); - mbean.createNewQueue(queueName.asString(), "test", false, args); - - final AMQQueue createdQueue = qReg.getQueue(queueName); - assertNotNull("The queue was not registered as expected", createdQueue); - assertEquals("Unexpected maximum delivery count", 5, createdQueue.getMaximumDeliveryCount()); - } - - /** - * Tests that setting the {@link AMQQueueFactory#X_QPID_PRIORITIES} argument prompts creation of - * a Priority Queue. - */ - public void testCreatePriorityQueue() throws Exception - { - int numPriorities = 7; - Map<String,Object> args = new HashMap<String, Object>(); - args.put(AMQQueueFactory.X_QPID_PRIORITIES, numPriorities); - - AMQShortString queueName = new AMQShortString("testCreatePriorityQueue"); - - QueueRegistry qReg = _vHost.getQueueRegistry(); - - assertNull("The queue should not yet exist", qReg.getQueue(queueName)); - - ManagedBroker mbean = new AMQBrokerManagerMBean((VirtualHostImpl.VirtualHostMBean) _vHost.getManagedObject()); - mbean.createNewQueue(queueName.asString(), "test", false, args); - - AMQQueue queue = qReg.getQueue(queueName); - assertEquals("Queue is not a priorty queue", AMQPriorityQueue.class, queue.getClass()); - assertEquals("Number of priorities supported was not as expected", numPriorities, ((AMQPriorityQueue)queue).getPriorities()); - } - - @Override - public void setUp() throws Exception - { - super.setUp(); - - CurrentActor.set(new TestLogActor(new SystemOutMessageLogger())); - - XMLConfiguration configXml = new XMLConfiguration(); - configXml.addProperty("virtualhosts.virtualhost(-1).name", "test"); - configXml.addProperty("virtualhosts.virtualhost(-1).test.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName()); - - ServerConfiguration configuration = new ServerConfiguration(configXml); - - ApplicationRegistry registry = new TestApplicationRegistry(configuration); - ApplicationRegistry.initialise(registry); - registry.getVirtualHostRegistry().setDefaultVirtualHostName("test"); - - IApplicationRegistry appRegistry = ApplicationRegistry.getInstance(); - _vHost = appRegistry.getVirtualHostRegistry().getVirtualHost("test"); - _queueRegistry = _vHost.getQueueRegistry(); - _exchangeRegistry = _vHost.getExchangeRegistry(); - } - - @Override - public void tearDown() throws Exception - { - try - { - super.tearDown(); - } - finally - { - ApplicationRegistry.remove(); - } - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java b/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java index bb20e0200b..43824e713f 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/BrokerOptionsTest.java @@ -199,4 +199,31 @@ public class BrokerOptionsTest extends QpidTestCase _options.setLogWatchFrequency(myFreq); assertEquals(myFreq, _options.getLogWatchFrequency()); } + + public void testDefaultIncludesPortFor0_10() + { + assertEquals(Collections.EMPTY_SET, _options.getIncludedPorts(ProtocolInclusion.v0_10)); + } + + public void testOverriddenIncludesPortFor0_10() + { + _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1); + assertEquals(Collections.singleton(TEST_PORT1), _options.getIncludedPorts(ProtocolInclusion.v0_10)); + } + + public void testManyOverriddenIncludedPortFor0_10() + { + _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1); + _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT2); + final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); + assertEquals(expectedPorts, _options.getIncludedPorts(ProtocolInclusion.v0_10)); + } + + public void testDuplicatedOverriddenIncludedPortFor0_10AreSilentlyIgnored() + { + _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT1); + _options.addIncludedPort(ProtocolInclusion.v0_10, TEST_PORT2); + final Set<Integer> expectedPorts = new HashSet<Integer>(Arrays.asList(new Integer[] {TEST_PORT1, TEST_PORT2})); + assertEquals(expectedPorts, _options.getIncludedPorts(ProtocolInclusion.v0_10)); + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/MainTest.java b/java/broker/src/test/java/org/apache/qpid/server/MainTest.java index 31d5028536..ffd607574e 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/MainTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/MainTest.java @@ -47,6 +47,11 @@ public class MainTest extends QpidTestCase { assertEquals(0, options.getExcludedPorts(pe).size()); } + + for(ProtocolInclusion pe : EnumSet.allOf(ProtocolInclusion.class)) + { + assertEquals(0, options.getIncludedPorts(pe).size()); + } } public void testPortOverriddenSingle() @@ -162,6 +167,20 @@ public class MainTest extends QpidTestCase assertTrue("Parsed command line didnt pick up help option", main.getCommandLine().hasOption("h")); } + public void testInclude010() + { + BrokerOptions options = startDummyMain("-p 5678 --include-0-10 5678"); + + assertTrue(options.getPorts().contains(5678)); + assertEquals(1, options.getPorts().size()); + assertTrue(options.getIncludedPorts(ProtocolInclusion.v0_10).contains(5678)); + assertEquals(1, options.getIncludedPorts(ProtocolInclusion.v0_10).size()); + assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_9_1).size()); + assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_9).size()); + assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v0_8).size()); + assertEquals(0, options.getIncludedPorts(ProtocolInclusion.v1_0).size()); + } + private BrokerOptions startDummyMain(String commandLine) { return (new TestMain(commandLine.split("\\s"))).getOptions(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java b/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java new file mode 100644 index 0000000000..9081dc49d6 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/TransactionTimeoutHelperTest.java @@ -0,0 +1,101 @@ +/* + * 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 static org.mockito.Matchers.any; +import static org.mockito.Matchers.same; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogMessage; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.logging.RootMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.test.utils.QpidTestCase; + +public class TransactionTimeoutHelperTest extends QpidTestCase +{ + private final LogMessage _logMessage = mock(LogMessage.class); + private final LogActor _logActor = mock(LogActor.class); + private final LogSubject _logSubject = mock(LogSubject.class); + private TransactionTimeoutHelper _transactionTimeoutHelper; + private RootMessageLogger _rootMessageLogger; + + public void testLogIfNecessary() + { + _transactionTimeoutHelper.logIfNecessary(99, 100, _logMessage, ""); + verifyZeroInteractions(_logActor, _logMessage); + + _transactionTimeoutHelper.logIfNecessary(101, 100, _logMessage, ""); + verify(_logActor).message(_logSubject, _logMessage); + } + + public void testLogIfNecessaryWhenOperationalLoggingDisabled() + { + //disable the operational logging + when(_rootMessageLogger.isMessageEnabled( + same(_logActor), any(LogSubject.class), any(String.class))) + .thenReturn(false); + + //verify the actor is never asked to log a message + _transactionTimeoutHelper.logIfNecessary(101, 100, _logMessage, ""); + verify(_logActor, never()).message(any(LogMessage.class)); + verify(_logActor, never()).message(any(LogSubject.class), any(LogMessage.class)); + } + + public void testIsTimedOut() + { + assertFalse("Shouldn't have timed out", _transactionTimeoutHelper.isTimedOut(199,200)); + assertTrue("Should have timed out", _transactionTimeoutHelper.isTimedOut(201,200)); + } + + /** + * If TransactionTimeout is disabled, the timeout will be 0. This test verifies + * that the helper methods respond negatively in this scenario. + */ + public void testTransactionTimeoutDisabled() + { + assertFalse("Shouldn't have timed out", _transactionTimeoutHelper.isTimedOut(201,0)); + + _transactionTimeoutHelper.logIfNecessary(99, 0, _logMessage, ""); + verifyZeroInteractions(_logActor, _logMessage); + } + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + CurrentActor.set(_logActor); + + _rootMessageLogger = mock(RootMessageLogger.class); + when(_logActor.getRootMessageLogger()).thenReturn(_rootMessageLogger); + + when(_rootMessageLogger.isMessageEnabled( + same(_logActor), any(LogSubject.class), any(String.class))) + .thenReturn(true); + + _transactionTimeoutHelper = new TransactionTimeoutHelper(_logSubject); + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java index c0777d2f8f..00e5cd1222 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/MockConnectionConfig.java @@ -25,14 +25,14 @@ import java.util.UUID; public class MockConnectionConfig implements ConnectionConfig { - public MockConnectionConfig(UUID _id, ConnectionConfigType _configType, + public MockConnectionConfig(UUID _qmfId, ConnectionConfigType _configType, ConfiguredObject<ConnectionConfigType, ConnectionConfig> _parent, boolean _durable, long _createTime, VirtualHostConfig _virtualHost, String _address, Boolean _incoming, Boolean _systemConnection, Boolean _federationLink, String _authId, String _remoteProcessName, Integer _remotePID, Integer _remoteParentPID, ConfigStore _configStore, Boolean _shadow) { super(); - this._id = _id; + this._qmfId = _qmfId; this._configType = _configType; this._parent = _parent; this._durable = _durable; @@ -50,7 +50,7 @@ public class MockConnectionConfig implements ConnectionConfig this._shadow = _shadow; } - private UUID _id; + private UUID _qmfId; private ConnectionConfigType _configType; private ConfiguredObject<ConnectionConfigType, ConnectionConfig> _parent; private boolean _durable; @@ -68,9 +68,9 @@ public class MockConnectionConfig implements ConnectionConfig private Boolean _shadow; @Override - public UUID getId() + public UUID getQMFId() { - return _id; + return _qmfId; } @Override diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java index 36f131a30f..3c5b85cd90 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/QueueConfigurationTest.java @@ -176,20 +176,29 @@ public class QueueConfigurationTest extends TestCase assertEquals(1, qConf.getMaximumMessageCount()); } - public void testGetMinimumAlertRepeatGap() throws ConfigurationException + public void testGetMinimumAlertRepeatGap() throws Exception { - // Check default value - QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); - assertEquals(0, qConf.getMinimumAlertRepeatGap()); + try + { + ApplicationRegistry registry = new TestApplicationRegistry(new ServerConfiguration(_env)); + ApplicationRegistry.initialise(registry); + // Check default value + QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); + assertEquals(ServerConfiguration.DEFAULT_MINIMUM_ALERT_REPEAT_GAP, qConf.getMinimumAlertRepeatGap()); - // Check explicit value - VirtualHostConfiguration vhostConfig = overrideConfiguration("minimumAlertRepeatGap", 2); - qConf = new QueueConfiguration("test", vhostConfig); - assertEquals(2, qConf.getMinimumAlertRepeatGap()); + // Check explicit value + VirtualHostConfiguration vhostConfig = overrideConfiguration("minimumAlertRepeatGap", 2); + qConf = new QueueConfiguration("test", vhostConfig); + assertEquals(2, qConf.getMinimumAlertRepeatGap()); - // Check inherited value - qConf = new QueueConfiguration("test", _fullHostConf); - assertEquals(1, qConf.getMinimumAlertRepeatGap()); + // Check inherited value + qConf = new QueueConfiguration("test", _fullHostConf); + assertEquals(1, qConf.getMinimumAlertRepeatGap()); + } + finally + { + ApplicationRegistry.remove(); + } } public void testSortQueueConfiguration() throws ConfigurationException @@ -204,6 +213,18 @@ public class QueueConfigurationTest extends TestCase assertEquals("test-sort-key", qConf.getQueueSortKey()); } + public void testQueueDescription() throws ConfigurationException + { + //Check default value + QueueConfiguration qConf = new QueueConfiguration("test", _emptyConf); + assertNull(qConf.getDescription()); + + // Check explicit value + final VirtualHostConfiguration vhostConfig = overrideConfiguration("description", "mydescription"); + qConf = new QueueConfiguration("test", vhostConfig); + assertEquals("mydescription", qConf.getDescription()); + } + private VirtualHostConfiguration overrideConfiguration(String property, Object value) throws ConfigurationException { diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java index 4caefc2f18..660ff5e7d4 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/ServerConfigurationTest.java @@ -25,6 +25,7 @@ import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry; import org.apache.qpid.server.util.TestApplicationRegistry; @@ -251,13 +252,13 @@ public class ServerConfigurationTest extends QpidTestCase { // Check default _serverConfig.initialise(); - assertEquals(true, _serverConfig.getManagementSSLEnabled()); + assertEquals(false, _serverConfig.getManagementSSLEnabled()); // Check value we set - _config.setProperty("management.ssl.enabled", false); + _config.setProperty("management.ssl.enabled", true); _serverConfig = new ServerConfiguration(_config); _serverConfig.initialise(); - assertEquals(false, _serverConfig.getManagementSSLEnabled()); + assertEquals(true, _serverConfig.getManagementSSLEnabled()); } public void testGetManagementKeystorePassword() throws ConfigurationException @@ -286,25 +287,17 @@ public class ServerConfigurationTest extends QpidTestCase assertEquals(false, _serverConfig.getQueueAutoRegister()); } - public void testGetManagementEnabled() throws ConfigurationException + public void testGetJMXManagementEnabled() throws ConfigurationException { // Check default _serverConfig.initialise(); - assertEquals(true, _serverConfig.getManagementEnabled()); + assertEquals(true, _serverConfig.getJMXManagementEnabled()); // Check value we set _config.setProperty("management.enabled", false); _serverConfig = new ServerConfiguration(_config); _serverConfig.initialise(); - assertEquals(false, _serverConfig.getManagementEnabled()); - } - - public void testSetManagementEnabled() throws ConfigurationException - { - // Check value we set - _serverConfig.initialise(); - _serverConfig.setManagementEnabled(false); - assertEquals(false, _serverConfig.getManagementEnabled()); + assertEquals(false, _serverConfig.getJMXManagementEnabled()); } public void testGetManagementRightsInferAllAccess() throws Exception @@ -401,7 +394,7 @@ public class ServerConfigurationTest extends QpidTestCase { // Check default _serverConfig.initialise(); - assertEquals(0, _serverConfig.getMinimumAlertRepeatGap()); + assertEquals(30000l, _serverConfig.getMinimumAlertRepeatGap()); // Check value we set _config.setProperty("minimumAlertRepeatGap", 10L); @@ -1588,6 +1581,168 @@ public class ServerConfigurationTest extends QpidTestCase assertEquals(false, _serverConfig.isAmqp08enabled()); } + public void testPortInclude08() throws ConfigurationException + { + // Check default + _serverConfig.initialise(); + assertEquals(true, _serverConfig.getPortInclude08().isEmpty()); + + // Check values we set + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_08, "1"); + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_08, "2"); + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals(2, _serverConfig.getPortInclude08().size()); + assertTrue(_serverConfig.getPortInclude08().contains("1")); + assertTrue(_serverConfig.getPortInclude08().contains("2")); + } + + public void testPortInclude09() throws ConfigurationException + { + // Check default + _serverConfig.initialise(); + assertEquals(true, _serverConfig.getPortInclude09().isEmpty()); + + // Check values we set + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_09, "3"); + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_09, "4"); + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals(2, _serverConfig.getPortInclude09().size()); + assertTrue(_serverConfig.getPortInclude09().contains("3")); + assertTrue(_serverConfig.getPortInclude09().contains("4")); + } + + public void testPortInclude091() throws ConfigurationException + { + // Check default + _serverConfig.initialise(); + assertEquals(true, _serverConfig.getPortInclude091().isEmpty()); + + // Check values we set + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_091, "5"); + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_091, "6"); + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals(2, _serverConfig.getPortInclude091().size()); + assertTrue(_serverConfig.getPortInclude091().contains("5")); + assertTrue(_serverConfig.getPortInclude091().contains("6")); + } + + public void testPortInclude010() throws ConfigurationException + { + // Check default + _serverConfig.initialise(); + assertEquals(true, _serverConfig.getPortInclude010().isEmpty()); + + // Check values we set + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, "7"); + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_010, "8"); + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals(2, _serverConfig.getPortInclude010().size()); + assertTrue(_serverConfig.getPortInclude010().contains("7")); + assertTrue(_serverConfig.getPortInclude010().contains("8")); + } + + public void testPortInclude10() throws ConfigurationException + { + // Check default + _serverConfig.initialise(); + assertEquals(true, _serverConfig.getPortInclude10().isEmpty()); + + // Check values we set + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_10, "9"); + _config.addProperty(ServerConfiguration.CONNECTOR_INCLUDE_10, "10"); + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals(2, _serverConfig.getPortInclude10().size()); + assertTrue(_serverConfig.getPortInclude10().contains("9")); + assertTrue(_serverConfig.getPortInclude10().contains("10")); + } + + public void testGetDefaultSupportedProtocolReply() throws Exception + { + // Check default + _serverConfig.initialise(); + assertNull("unexpected default value", _serverConfig.getDefaultSupportedProtocolReply()); + + // Check values we set + _config.addProperty(ServerConfiguration.CONNECTOR_AMQP_SUPPORTED_REPLY, "v0_10"); + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals(AmqpProtocolVersion.v0_10, _serverConfig.getDefaultSupportedProtocolReply()); + } + + public void testDefaultAuthenticationManager() throws Exception + { + // Check default + _serverConfig.initialise(); + assertNull("unexpected default value", _serverConfig.getDefaultAuthenticationManager()); + + // Check values we set + String testAuthManager = "myauthmanager"; + _config.addProperty("security.default-auth-manager", testAuthManager); + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals(testAuthManager, _serverConfig.getDefaultAuthenticationManager()); + } + + public void testPortAuthenticationMappingsDefault() throws Exception + { + _serverConfig.initialise(); + assertEquals("unexpected default number of port/authmanager mappings", 0, _serverConfig.getPortAuthenticationMappings().size()); + } + + public void testPortAuthenticationMappingsWithSingleMapping() throws Exception + { + String testAuthManager = "myauthmanager"; + _config.addProperty("security.port-mappings.port-mapping.port", 1234); + _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager); + + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + assertEquals("unexpected number of port/authmanager mappings", 1, _serverConfig.getPortAuthenticationMappings().size()); + assertEquals("unexpected mapping for port", testAuthManager, _serverConfig.getPortAuthenticationMappings().get(1234)); + } + + public void testPortAuthenticationMappingsWithManyMapping() throws Exception + { + String testAuthManager1 = "myauthmanager1"; + String testAuthManager2 = "myauthmanager2"; + _config.addProperty("security.port-mappings.port-mapping(-1).port", 1234); + _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager1); + + _config.addProperty("security.port-mappings.port-mapping(-1).port", 2345); + _config.addProperty("security.port-mappings.port-mapping.auth-manager", testAuthManager2); + + _serverConfig = new ServerConfiguration(_config); + _serverConfig.initialise(); + + assertEquals("unexpected number of port/authmanager mappings", 2, _serverConfig.getPortAuthenticationMappings().size()); + assertEquals("unexpected mapping for port", testAuthManager1, _serverConfig.getPortAuthenticationMappings().get(1234)); + assertEquals("unexpected mapping for port", testAuthManager2, _serverConfig.getPortAuthenticationMappings().get(2345)); + } + + public void testPortAuthenticationMappingWithMissingAuthManager() throws Exception + { + _config.addProperty("security.port-mappings.port-mapping(-1).port", 1234); + // no auth manager defined for port + _serverConfig = new ServerConfiguration(_config); + try + { + _serverConfig.initialise(); + fail("Exception not thrown"); + } + catch(ConfigurationException ce) + { + // PASS + assertEquals("Incorrect error message", + "Validation error: Each port-mapping must have exactly one port and exactly one auth-manager.", + ce.getMessage()); + } + } + /** * Convenience method to output required security preamble for broker config */ @@ -1605,7 +1760,6 @@ public class ServerConfigurationTest extends QpidTestCase out.write("\t\t\t\t\t</attribute>\n"); out.write("\t\t\t\t</attributes>\n"); out.write("\t\t\t</principal-database>\n"); - out.write("\t\t\t<jmx-access>/dev/null</jmx-access>\n"); out.write("\t\t</pd-auth-manager>\n"); out.write("\t</security>\n"); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java index 59cd0cf1db..caf74a89ec 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/TopicConfigurationTest.java @@ -26,8 +26,8 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; +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.util.InternalBrokerBaseCase; @@ -77,7 +77,7 @@ public class TopicConfigurationTest extends InternalBrokerBaseCase public void testSubscriptionWithTopicCreation() throws ConfigurationException, AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()+":stockSubscription"), false, new AMQShortString("testowner"), + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), getName()+":stockSubscription", false, "testowner", false, false, getVirtualHost(), null); getVirtualHost().getQueueRegistry().registerQueue(queue); @@ -107,7 +107,7 @@ public class TopicConfigurationTest extends InternalBrokerBaseCase public void testSubscriptionCreation() throws ConfigurationException, AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()+":stockSubscription"), false, new AMQShortString("testowner"), + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID() ,getName()+":stockSubscription", false, "testowner", false, false, getVirtualHost(), null); getVirtualHost().getQueueRegistry().registerQueue(queue); diff --git a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java index c4c93acfb6..50e7f0588b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java @@ -27,7 +27,6 @@ import org.apache.qpid.server.queue.AMQPriorityQueue; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory; import org.apache.qpid.server.util.InternalBrokerBaseCase; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -162,7 +161,7 @@ public class VirtualHostConfigurationTest extends InternalBrokerBaseCase getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "r2d2"); getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues.queue.r2d2.deadLetterQueues", "true"); getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.queues(-1).queue(-1).name", "c3p0"); - getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName()); + getConfigXml().addProperty("virtualhosts.virtualhost." + getName() + "Extra.store.class", TestableMemoryMessageStore.class.getName()); // Start the broker now. super.createBroker(); diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java index afd8fd9ed2..4befd26ece 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTestBase.java @@ -83,7 +83,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase protected void unbind(TestQueue queue, String... bindings) throws AMQException { String queueName = queue.getName(); - exchange.onUnbind(new Binding(null,queueName, queue, exchange, getHeadersMap(bindings))); + exchange.onUnbind(new Binding(null, null, queueName, queue, exchange, getHeadersMap(bindings))); } protected int getCount() @@ -95,7 +95,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase { TestQueue queue = new TestQueue(new AMQShortString(queueName)); queues.add(queue); - exchange.onBind(new Binding(null,key, queue, exchange, args)); + exchange.onBind(new Binding(null, null, key, queue, exchange, args)); return queue; } @@ -276,7 +276,7 @@ public class AbstractHeadersExchangeTestBase extends InternalBrokerBaseCase public TestQueue(AMQShortString name) throws AMQException { - super(UUIDGenerator.generateUUID(), name, false, new AMQShortString("test"), true, false,ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), Collections.EMPTY_MAP); + super(UUIDGenerator.generateRandomUUID(), name, false, new AMQShortString("test"), true, false,ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"), Collections.EMPTY_MAP); ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test").getQueueRegistry().registerQueue(this); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java deleted file mode 100644 index 9034bf9c3a..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/ExchangeMBeanTest.java +++ /dev/null @@ -1,235 +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.commons.lang.ArrayUtils; - -import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.ManagedExchange; -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.QueueRegistry; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.registry.IApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import javax.management.JMException; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.TabularData; -import java.util.ArrayList; -import java.util.Iterator; - -/** - * Unit test class for testing different Exchange MBean operations - */ -public class ExchangeMBeanTest extends InternalBrokerBaseCase -{ - private AMQQueue _queue; - private QueueRegistry _queueRegistry; - private VirtualHost _virtualHost; - - public void testGeneralProperties() throws Exception - { - DirectExchange exchange = new DirectExchange(); - exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true); - ManagedObject managedObj = exchange.getManagedObject(); - ManagedExchange mbean = (ManagedExchange)managedObj; - - // test general exchange properties - assertEquals("Unexpected exchange name", "amq.direct", mbean.getName()); - assertEquals("Unexpected exchange type", "direct", mbean.getExchangeType()); - assertEquals("Unexpected ticket number", Integer.valueOf(0), mbean.getTicketNo()); - assertFalse("Unexpected durable flag", mbean.isDurable()); - assertTrue("Unexpected auto delete flag", mbean.isAutoDelete()); - } - - public void testDirectExchangeMBean() throws Exception - { - DirectExchange exchange = new DirectExchange(); - exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost, ExchangeDefaults.DIRECT_EXCHANGE_NAME, false, 0, true); - ManagedObject managedObj = exchange.getManagedObject(); - ManagedExchange mbean = (ManagedExchange)managedObj; - - mbean.createNewBinding(_queue.getNameShortString().toString(), "binding1"); - mbean.createNewBinding(_queue.getNameShortString().toString(), "binding2"); - - TabularData data = mbean.bindings(); - ArrayList<Object> list = new ArrayList<Object>(data.values()); - assertTrue(list.size() == 2); - } - - public void testTopicExchangeMBean() throws Exception - { - TopicExchange exchange = new TopicExchange(); - exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.TOPIC_EXCHANGE_NAME, false, 0, true); - ManagedObject managedObj = exchange.getManagedObject(); - ManagedExchange mbean = (ManagedExchange)managedObj; - - mbean.createNewBinding(_queue.getNameShortString().toString(), "binding1"); - mbean.createNewBinding(_queue.getNameShortString().toString(), "binding2"); - - TabularData data = mbean.bindings(); - ArrayList<Object> list = new ArrayList<Object>(data.values()); - assertTrue(list.size() == 2); - } - - public void testHeadersExchangeMBean() throws Exception - { - HeadersExchange exchange = new HeadersExchange(); - exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true); - ManagedObject managedObj = exchange.getManagedObject(); - ManagedExchange mbean = (ManagedExchange)managedObj; - - mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,key1=binding1,key2=binding2"); - - TabularData data = mbean.bindings(); - ArrayList<Object> list = new ArrayList<Object>(data.values()); - assertEquals("Unexpected number of bindings", 1, list.size()); - - final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) data.values().iterator(); - CompositeDataSupport row = rowItr.next(); - assertBinding(1, _queue.getName(), new String[]{"x-match=any","key1=binding1","key2=binding2"}, row); - } - - /** - * Included to ensure 0-10 Specification compliance: - * 2.3.1.4 "the field in the bind arguments has no value and a field of the same name is present in the message headers - */ - public void testHeadersExchangeMBeanMatchPropertyNoValue() throws Exception - { - HeadersExchange exchange = new HeadersExchange(); - exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true); - ManagedObject managedObj = exchange.getManagedObject(); - ManagedExchange mbean = (ManagedExchange)managedObj; - - mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,key4,key5="); - - TabularData data = mbean.bindings(); - ArrayList<Object> list = new ArrayList<Object>(data.values()); - assertEquals("Unexpected number of bindings", 1, list.size()); - - final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) data.values().iterator(); - CompositeDataSupport row = rowItr.next(); - assertBinding(1, _queue.getName(), new String[]{"x-match=any","key4=","key5="}, row); - } - - public void testInvalidHeaderBindingMalformed() throws Exception - { - HeadersExchange exchange = new HeadersExchange(); - exchange.initialise(UUIDGenerator.generateUUID(), _virtualHost,ExchangeDefaults.HEADERS_EXCHANGE_NAME, false, 0, true); - ManagedObject managedObj = exchange.getManagedObject(); - ManagedExchange mbean = (ManagedExchange)managedObj; - - try - { - mbean.createNewBinding(_queue.getNameShortString().toString(), "x-match=any,=value4"); - fail("Exception not thrown"); - } - catch (JMException jme) - { - //pass - } - } - - private void assertBinding(final int expectedBindingNo, final String expectedQueueName, final String[] expectedBindingArray, - final CompositeDataSupport row) - { - final Number bindingNumber = (Number) row.get(ManagedExchange.HDR_BINDING_NUMBER); - final String queueName = (String) row.get(ManagedExchange.HDR_QUEUE_NAME); - final String[] bindings = (String[]) row.get(ManagedExchange.HDR_QUEUE_BINDINGS); - assertEquals("Unexpected binding number", expectedBindingNo, bindingNumber); - assertEquals("Unexpected queue name", expectedQueueName, queueName); - assertEquals("Unexpected no of bindings", expectedBindingArray.length, bindings.length); - for(String binding : bindings) - { - assertTrue("Expected binding not found: " + binding, ArrayUtils.contains(expectedBindingArray, binding)); - } - } - - /** - * Test adding bindings and removing them from the default exchange via JMX. - * <p> - * QPID-2700 - */ - public void testDefaultBindings() throws Exception - { - int bindings = _queue.getBindingCount(); - - Exchange exchange = _queue.getVirtualHost().getExchangeRegistry().getDefaultExchange(); - ManagedExchange mbean = (ManagedExchange) ((AbstractExchange) exchange).getManagedObject(); - - mbean.createNewBinding(_queue.getName(), "robot"); - mbean.createNewBinding(_queue.getName(), "kitten"); - - assertEquals("Should have added two bindings", bindings + 2, _queue.getBindingCount()); - - mbean.removeBinding(_queue.getName(), "robot"); - - assertEquals("Should have one extra binding", bindings + 1, _queue.getBindingCount()); - - mbean.removeBinding(_queue.getName(), "kitten"); - - assertEquals("Should have original number of binding", bindings, _queue.getBindingCount()); - } - - /** - * Test adding bindings and removing them from the topic exchange via JMX. - * <p> - * QPID-2700 - */ - public void testTopicBindings() throws Exception - { - int bindings = _queue.getBindingCount(); - - Exchange exchange = _queue.getVirtualHost().getExchangeRegistry().getExchange(new AMQShortString("amq.topic")); - ManagedExchange mbean = (ManagedExchange) ((AbstractExchange) exchange).getManagedObject(); - - mbean.createNewBinding(_queue.getName(), "robot.#"); - mbean.createNewBinding(_queue.getName(), "#.kitten"); - - assertEquals("Should have added two bindings", bindings + 2, _queue.getBindingCount()); - - mbean.removeBinding(_queue.getName(), "robot.#"); - - assertEquals("Should have one extra binding", bindings + 1, _queue.getBindingCount()); - - mbean.removeBinding(_queue.getName(), "#.kitten"); - - assertEquals("Should have original number of binding", bindings, _queue.getBindingCount()); - } - - @Override - public void setUp() throws Exception - { - super.setUp(); - - IApplicationRegistry applicationRegistry = ApplicationRegistry.getInstance(); - _virtualHost = applicationRegistry.getVirtualHostRegistry().getVirtualHost("test"); - _queueRegistry = _virtualHost.getQueueRegistry(); - _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue"), false, new AMQShortString("ExchangeMBeanTest"), false, false, - _virtualHost, null); - _queueRegistry.registerQueue(_queue); - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java index 4305cdadc6..3988edcb3c 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/HeadersBindingTest.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 @@ -20,6 +20,7 @@ */ package org.apache.qpid.server.exchange; +import java.util.Collection; import junit.framework.TestCase; import org.apache.qpid.server.binding.Binding; @@ -50,6 +51,16 @@ public class HeadersBindingTest extends TestCase return 0; } + public String getUserId() + { + return null; + } + + public String getAppId() + { + return null; + } + public String getMessageId() { return null; @@ -57,7 +68,7 @@ public class HeadersBindingTest extends TestCase public String getMimeType() { - return null; //To change body of implemented methods use File | Settings | File Templates. + return null; } public String getEncoding() @@ -105,6 +116,12 @@ public class HeadersBindingTest extends TestCase return _headers.keySet().containsAll(names); } + @Override + public Collection<String> getHeaderNames() + { + return _headers.keySet(); + } + public boolean containsHeader(String name) { return _headers.containsKey(name); @@ -125,13 +142,13 @@ public class HeadersBindingTest extends TestCase private MockHeader matchHeaders = new MockHeader(); private int _count = 0; private MockAMQQueue _queue; - + protected void setUp() { _count++; _queue = new MockAMQQueue(getQueueName()); } - + protected String getQueueName() { return "Queue" + _count; @@ -143,7 +160,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -154,7 +171,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); matchHeaders.setString("B", "Value of B"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -164,7 +181,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Altered value of A"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } @@ -175,7 +192,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -187,7 +204,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } @@ -200,7 +217,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); matchHeaders.setString("B", "Value of B"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -214,7 +231,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -228,7 +245,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Altered value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } @@ -239,7 +256,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -251,7 +268,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -264,7 +281,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("A", "Value of A"); matchHeaders.setString("B", "Value of B"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -278,7 +295,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -292,7 +309,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Altered value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertTrue(new HeadersBinding(b).matches(matchHeaders)); } @@ -306,7 +323,7 @@ public class HeadersBindingTest extends TestCase matchHeaders.setString("B", "Altered value of B"); matchHeaders.setString("C", "Value of C"); - Binding b = new Binding(null, getQueueName(), _queue, null, bindHeaders); + Binding b = new Binding(null, null, getQueueName(), _queue, null, bindHeaders); assertFalse(new HeadersBinding(b).matches(matchHeaders)); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java index 00c8a18d9f..92274afece 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java @@ -30,6 +30,7 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; @@ -64,8 +65,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testNoRoute() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*#b"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.*.#.b", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*#b", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.*.#.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.b"); @@ -76,8 +77,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testDirectMatch() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("ab"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.b", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "ab", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.b"); @@ -103,8 +104,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testStarMatch() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a*"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.*", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a*", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.*",queue, _exchange, null)); IncomingMessage message = createMessage("a.b"); @@ -142,8 +143,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testHashMatch() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.#", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.#",queue, _exchange, null)); IncomingMessage message = createMessage("a.b.c"); @@ -205,8 +206,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMidHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.*.#.b", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.*.#.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.d.b"); @@ -235,8 +236,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMatchafterHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.*.#.b.c", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.*.#.b.c",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.b.b"); @@ -281,8 +282,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testHashAfterHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.*.#.b.c.#.d", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.*.#.b.c.#.d",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.b.b.c"); @@ -308,8 +309,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testHashHash() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a#"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.#.*.#.d", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a#", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.#.*.#.d",queue, _exchange, null)); IncomingMessage message = createMessage("a.c.b.b.c"); @@ -334,8 +335,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testSubMatchFails() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.b.c.d", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.b.c.d",queue, _exchange, null)); IncomingMessage message = createMessage("a.b.c"); @@ -364,8 +365,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMoreRouting() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.b", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null)); IncomingMessage message = createMessage("a.b.c"); @@ -379,8 +380,8 @@ public class TopicExchangeTest extends InternalBrokerBaseCase public void testMoreQueue() throws AMQException { - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("a"), false, null, false, false, _vhost, null); - _exchange.registerQueue(new Binding(null,"a.b", queue,_exchange, null)); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "a", false, null, false, false, _vhost, null); + _exchange.registerQueue(new Binding(null, null, "a.b",queue, _exchange, null)); IncomingMessage message = createMessage("a"); diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java new file mode 100644 index 0000000000..f871baffe6 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.java @@ -0,0 +1,245 @@ +/* + * 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.log4j; + +import java.io.File; +import java.util.List; +import java.util.Map; + +import org.apache.log4j.Level; +import org.apache.qpid.util.FileUtils; + +import junit.framework.TestCase; + +public class LoggingFacadeTest extends TestCase +{ + private LoggingFacade _loggingFacade; + private String _log4jXmlFile; + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _log4jXmlFile = createTestLog4jXml(); + _loggingFacade = LoggingFacade.configure(_log4jXmlFile); + } + + public void testGetAvailableLoggerLevels() throws Exception + { + List<String> levels = _loggingFacade.getAvailableLoggerLevels(); + assertTrue(levels.contains("ALL")); + assertTrue(levels.contains("TRACE")); + assertTrue(levels.contains("DEBUG")); + assertTrue(levels.contains("INFO")); + assertTrue(levels.contains("WARN")); + assertTrue(levels.contains("ERROR")); + assertTrue(levels.contains("FATAL")); + assertTrue(levels.contains("OFF")); + assertEquals(8, levels.size()); + } + + public void testRetrieveConfigFileRootLoggerLevel() throws Exception + { + String level = _loggingFacade.retrieveConfigFileRootLoggerLevel(); + assertEquals(Level.WARN.toString(), level); + } + + public void testSetConfigFileRootLoggerLevel() throws Exception + { + String oldLevel = _loggingFacade.retrieveConfigFileRootLoggerLevel(); + assertEquals("WARN", oldLevel); + + _loggingFacade.setConfigFileRootLoggerLevel("INFO"); + + String level = _loggingFacade.retrieveConfigFileRootLoggerLevel(); + assertEquals("INFO", level); + } + + public void testRetrieveConfigFileLoggerLevels() throws Exception + { + Map<String, String> levels = _loggingFacade.retrieveConfigFileLoggersLevels(); + assertEquals(3, levels.size()); + String abcLevel = levels.get("a.b.c"); + String abc1Level = levels.get("a.b.c.1"); + String abc2Level = levels.get("a.b.c.2"); + assertEquals("INFO", abcLevel); + assertEquals("DEBUG", abc1Level); + assertEquals("TRACE", abc2Level); + } + + public void testSetConfigFileLoggerLevels() throws Exception + { + final String loggerName = "a.b.c"; + + assertConfigFileLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN"); + + Map<String, String> levels = _loggingFacade.retrieveConfigFileLoggersLevels(); + String abcLevel = levels.get(loggerName); + assertEquals("WARN", abcLevel); + } + + public void testSetConfigFileLoggerLevelsWhereLoggerDoesNotExist() throws Exception + { + try + { + _loggingFacade.setConfigFileLoggerLevel("does.not.exist", "WARN"); + fail("Exception not thrown"); + } + catch (LoggingFacadeException lfe) + { + // PASS + assertEquals("Can't find logger does.not.exist", lfe.getMessage()); + } + } + + public void testRetrieveRuntimeRootLoggerLevel() throws Exception + { + String level = _loggingFacade.retrieveRuntimeRootLoggerLevel(); + assertEquals(Level.WARN.toString(), level); + } + + public void testSetRuntimeRootLoggerLevel() throws Exception + { + String oldLevel = _loggingFacade.retrieveRuntimeRootLoggerLevel(); + assertEquals("WARN", oldLevel); + + _loggingFacade.setRuntimeRootLoggerLevel("INFO"); + + String level = _loggingFacade.retrieveRuntimeRootLoggerLevel(); + assertEquals("INFO", level); + } + + public void testRetrieveRuntimeLoggersLevels() throws Exception + { + Map<String, String> levels = _loggingFacade.retrieveRuntimeLoggersLevels(); + // Don't assert size as implementation itself uses logging and we'd count its loggers too + String abcLevel = levels.get("a.b.c"); + String abc1Level = levels.get("a.b.c.1"); + String abc2Level = levels.get("a.b.c.2"); + assertEquals("INFO", abcLevel); + assertEquals("DEBUG", abc1Level); + assertEquals("TRACE", abc2Level); + } + + public void testSetRuntimeLoggerLevel() throws Exception + { + final String loggerName = "a.b.c"; + + assertRuntimeLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); + + assertRuntimeLoggingLevel(loggerName, "WARN"); + } + + public void testSetRuntimeLoggerToInheritFromParent() throws Exception + { + final String parentLoggerName = "a.b.c"; + final String childLoggerName = "a.b.c.1"; + + assertRuntimeLoggingLevel(parentLoggerName, "INFO"); + assertRuntimeLoggingLevel(childLoggerName, "DEBUG"); + + _loggingFacade.setRuntimeLoggerLevel(childLoggerName, null); + + assertRuntimeLoggingLevel(parentLoggerName, "INFO"); + assertRuntimeLoggingLevel(childLoggerName, "INFO"); + } + + public void testSetRuntimeLoggerLevelsWhereLoggerDoesNotExist() throws Exception + { + final String loggerName = "does.not.exist2"; + + Map<String, String> oldLevels = _loggingFacade.retrieveRuntimeLoggersLevels(); + assertFalse(oldLevels.containsKey(loggerName)); + + try + { + _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); + fail("Exception not thrown"); + } + catch (LoggingFacadeException lfe) + { + // PASS + assertEquals("Can't find logger " + loggerName, lfe.getMessage()); + } + + Map<String, String> levels = _loggingFacade.retrieveRuntimeLoggersLevels(); + assertFalse(levels.containsKey(loggerName)); + } + + public void testReloadOfChangedLog4JFileUpdatesRuntimeLogLevel() throws Exception + { + final String loggerName = "a.b.c"; + + assertRuntimeLoggingLevel(loggerName, "INFO"); + assertConfigFileLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setConfigFileLoggerLevel(loggerName, "WARN"); + + assertRuntimeLoggingLevel(loggerName, "INFO"); + + _loggingFacade.reload(); + + assertRuntimeLoggingLevel(loggerName, "WARN"); + } + + + public void testReloadOfLog4JFileRevertsRuntimeChanges() throws Exception + { + final String loggerName = "a.b.c"; + + assertRuntimeLoggingLevel(loggerName, "INFO"); + assertConfigFileLoggingLevel(loggerName, "INFO"); + + _loggingFacade.setRuntimeLoggerLevel(loggerName, "WARN"); + + assertRuntimeLoggingLevel(loggerName, "WARN"); + + _loggingFacade.reload(); + + assertRuntimeLoggingLevel(loggerName, "INFO"); + } + + private void assertConfigFileLoggingLevel(final String loggerName, String expectedLevel) throws Exception + { + Map<String, String> levels = _loggingFacade.retrieveConfigFileLoggersLevels(); + String actualLevel = levels.get(loggerName); + assertEquals(expectedLevel, actualLevel); + } + + private void assertRuntimeLoggingLevel(final String loggerName, String expectedLevel) throws Exception + { + Map<String, String> levels = _loggingFacade.retrieveRuntimeLoggersLevels(); + String actualLevel = levels.get(loggerName); + assertEquals(expectedLevel, actualLevel); + } + + private String createTestLog4jXml() throws Exception + { + File dst = File.createTempFile("log4j." + getName(), "xml"); + File filename = new File(getClass().getResource("LoggingFacadeTest.log4j.xml").toURI()); + FileUtils.copy(filename, dst); + dst.deleteOnExit(); + return dst.getAbsolutePath(); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.log4j.xml b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.log4j.xml new file mode 100644 index 0000000000..62ec877d3d --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/log4j/LoggingFacadeTest.log4j.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - 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. + - + --><!DOCTYPE log4j:configuration SYSTEM "log4j.dtd"> + +<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="null" threshold="null"> + + <category additivity="true" name="a.b.c"> + <priority value="INFO"/> + </category> + + <logger additivity="true" name="a.b.c.1"> + <level value="DEBUG"/> + </logger> + + <logger additivity="true" name="a.b.c.2"> + <level value="TRACE"/> + </logger> + + <root> + <priority value="WARN"/> + </root> + +</log4j:configuration> diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java deleted file mode 100644 index f9ad81ae74..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/management/LoggingManagementMBeanTest.java +++ /dev/null @@ -1,428 +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.Logger; - -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL; -import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularDataSupport; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public class LoggingManagementMBeanTest extends InternalBrokerBaseCase -{ - private static final String TEST_LOGGER = "LoggingManagementMBeanTestLogger"; - private static final String TEST_LOGGER_CHILD1 = "LoggingManagementMBeanTestLogger.child1"; - private static final String TEST_LOGGER_CHILD2 = "LoggingManagementMBeanTestLogger.child2"; - - private static final String TEST_CATEGORY_PRIORITY = "LogManMBeanTest.category.priority"; - private static final String TEST_CATEGORY_LEVEL = "LogManMBeanTest.category.level"; - private static final String TEST_LOGGER_LEVEL = "LogManMBeanTest.logger.level"; - - private static final String NEWLINE = System.getProperty("line.separator"); - - private File _testConfigFile; - - @Override - public void setUp() throws Exception - { - super.setUp(); - _testConfigFile = createTempTestLog4JConfig(); - } - - @Override - public void tearDown() throws Exception - { - File oldTestConfigFile = new File(_testConfigFile.getAbsolutePath() + ".old"); - if(oldTestConfigFile.exists()) - { - oldTestConfigFile.delete(); - } - - _testConfigFile.delete(); - - super.tearDown(); - } - - private File createTempTestLog4JConfig() - { - File tmpFile = null; - try - { - tmpFile = File.createTempFile("LogManMBeanTestLog4jConfig", ".tmp"); - tmpFile.deleteOnExit(); - - FileWriter fstream = new FileWriter(tmpFile); - BufferedWriter writer = new BufferedWriter(fstream); - - writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"+NEWLINE); - writer.write("<!DOCTYPE log4j:configuration SYSTEM \"log4j.dtd\">"+NEWLINE); - - writer.write("<log4j:configuration xmlns:log4j=\"http://jakarta.apache.org/log4j/\" debug=\"null\" " + - "threshold=\"null\">"+NEWLINE); - - writer.write(" <appender class=\"org.apache.log4j.ConsoleAppender\" name=\"STDOUT\">"+NEWLINE); - writer.write(" <layout class=\"org.apache.log4j.PatternLayout\">"+NEWLINE); - writer.write(" <param name=\"ConversionPattern\" value=\"%d %-5p [%t] %C{2} (%F:%L) - %m%n\"/>"+NEWLINE); - writer.write(" </layout>"+NEWLINE); - writer.write(" </appender>"+NEWLINE); - - //Example of a 'category' with a 'priority' - writer.write(" <category additivity=\"true\" name=\"" + TEST_CATEGORY_PRIORITY +"\">"+NEWLINE); - writer.write(" <priority value=\"info\"/>"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </category>"+NEWLINE); - - //Example of a 'category' with a 'level' - writer.write(" <category additivity=\"true\" name=\"" + TEST_CATEGORY_LEVEL +"\">"+NEWLINE); - writer.write(" <level value=\"warn\"/>"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </category>"+NEWLINE); - - //Example of a 'logger' with a 'level' - writer.write(" <logger additivity=\"true\" name=\"" + TEST_LOGGER_LEVEL + "\">"+NEWLINE); - writer.write(" <level value=\"error\"/>"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </logger>"+NEWLINE); - - //'root' logger - writer.write(" <root>"+NEWLINE); - writer.write(" <priority value=\"info\"/>"+NEWLINE); - writer.write(" <appender-ref ref=\"STDOUT\"/>"+NEWLINE); - writer.write(" </root>"+NEWLINE); - - writer.write("</log4j:configuration>"+NEWLINE); - - writer.flush(); - writer.close(); - } - catch (IOException e) - { - fail("Unable to create temporary test log4j configuration"); - } - - return tmpFile; - } - - - - //******* Test Methods ******* // - - public void testSetRuntimeLoggerLevel() - { - LoggingManagementMBean lm = null; - try - { - lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0); - } - catch (JMException e) - { - fail("Could not create test LoggingManagementMBean"); - } - - //create a parent test logger, set its level explicitly - Logger log = Logger.getLogger(TEST_LOGGER); - log.setLevel(Level.toLevel("info")); - - //create child1 test logger, check its *effective* level is the same as the parent, "info" - Logger log1 = Logger.getLogger(TEST_LOGGER_CHILD1); - assertTrue("Test logger's level was not the expected value", - log1.getEffectiveLevel().toString().equalsIgnoreCase("info")); - - //now change its level to "warn" - assertTrue("Failed to set logger level", lm.setRuntimeLoggerLevel(TEST_LOGGER_CHILD1, "warn")); - - //check the change, see its actual level is "warn - assertTrue("Test logger's level was not the expected value", - log1.getLevel().toString().equalsIgnoreCase("warn")); - - //try an invalid level - assertFalse("Trying to set an invalid level succeded", lm.setRuntimeLoggerLevel(TEST_LOGGER_CHILD1, "made.up.level")); - } - - public void testSetRuntimeRootLoggerLevel() - { - LoggingManagementMBean lm = null; - try - { - lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0); - } - catch (JMException e) - { - fail("Could not create test LoggingManagementMBean"); - } - - Logger log = Logger.getRootLogger(); - - //get current root logger level - Level origLevel = log.getLevel(); - - //change level twice to ensure a new level is actually selected - - //set root loggers level to info - assertTrue("Failed to set root logger level", lm.setRuntimeRootLoggerLevel("debug")); - //check it is now actually info - Level currentLevel = log.getLevel(); - assertTrue("Logger level was not expected value", currentLevel.equals(Level.toLevel("debug"))); - - //try an invalid level - assertFalse("Trying to set an invalid level succeded", lm.setRuntimeRootLoggerLevel("made.up.level")); - - //set root loggers level to warn - assertTrue("Failed to set logger level", lm.setRuntimeRootLoggerLevel("info")); - //check it is now actually warn - currentLevel = log.getLevel(); - assertTrue("Logger level was not expected value", currentLevel.equals(Level.toLevel("info"))); - - //restore original level - log.setLevel(origLevel); - } - - public void testGetRuntimeRootLoggerLevel() - { - LoggingManagementMBean lm = null; - try - { - lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0); - } - catch (JMException e) - { - fail("Could not create test LoggingManagementMBean"); - } - - Logger log = Logger.getRootLogger(); - - //get current root logger level - Level origLevel = log.getLevel(); - - //change level twice to ensure a new level is actually selected - - //set root loggers level to debug - log.setLevel(Level.toLevel("debug")); - //check it is now actually debug - assertTrue("Logger level was not expected value", lm.getRuntimeRootLoggerLevel().equalsIgnoreCase("debug")); - - - //set root loggers level to warn - log.setLevel(Level.toLevel("info")); - //check it is now actually warn - assertTrue("Logger level was not expected value", lm.getRuntimeRootLoggerLevel().equalsIgnoreCase("info")); - - //restore original level - log.setLevel(origLevel); - } - - public void testViewEffectiveRuntimeLoggerLevels() - { - LoggingManagementMBean lm = null; - try - { - lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0); - } - catch (JMException e) - { - fail("Could not create test LoggingManagementMBean"); - } - - //(re)create a parent test logger, set its level explicitly - Logger log = Logger.getLogger(TEST_LOGGER); - log.setLevel(Level.toLevel("info")); - - //retrieve the current effective runtime logger level values - TabularDataSupport levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels(); - Collection<Object> records = levels.values(); - Map<String,String> list = new HashMap<String,String>(); - for (Object o : records) - { - CompositeData data = (CompositeData) o; - list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString()); - } - - //check child2 does not exist already - assertFalse("Did not expect this logger to exist already", list.containsKey(TEST_LOGGER_CHILD2)); - - //create child2 test logger - Logger log2 = Logger.getLogger(TEST_LOGGER_CHILD2); - - //retrieve the current effective runtime logger level values - levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels(); - records = levels.values(); - list = new HashMap<String,String>(); - for (Object o : records) - { - CompositeData data = (CompositeData) o; - list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString()); - } - - //verify the parent and child2 loggers are present in returned values - assertTrue(TEST_LOGGER + " logger was not in the returned list", list.containsKey(TEST_LOGGER)); - assertTrue(TEST_LOGGER_CHILD2 + " logger was not in the returned list", list.containsKey(TEST_LOGGER_CHILD2)); - - //check child2's effective level is the same as the parent, "info" - assertTrue("Test logger's level was not the expected value", - list.get(TEST_LOGGER_CHILD2).equalsIgnoreCase("info")); - - //now change its level explicitly to "warn" - log2.setLevel(Level.toLevel("warn")); - - //retrieve the current effective runtime logger level values - levels = (TabularDataSupport) lm.viewEffectiveRuntimeLoggerLevels(); - records = levels.values(); - list = new HashMap<String,String>(); - for (Object o : records) - { - CompositeData data = (CompositeData) o; - list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString()); - } - - //check child2's effective level is now "warn" - assertTrue("Test logger's level was not the expected value", - list.get(TEST_LOGGER_CHILD2).equalsIgnoreCase("warn")); - } - - public void testViewAndSetConfigFileLoggerLevel() throws Exception - { - LoggingManagementMBean lm =null; - try - { - lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0); - } - catch (JMException e) - { - fail("Could not create test LoggingManagementMBean"); - } - - //retrieve the current values - TabularDataSupport levels = (TabularDataSupport) lm.viewConfigFileLoggerLevels(); - Collection<Object> records = levels.values(); - Map<String,String> list = new HashMap<String,String>(); - for (Object o : records) - { - CompositeData data = (CompositeData) o; - list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString()); - } - - //check the 3 different types of logger definition are successfully retrieved before update - assertTrue("Wrong number of items in returned list", list.size() == 3); - assertTrue(TEST_CATEGORY_PRIORITY + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_PRIORITY)); - assertTrue(TEST_CATEGORY_LEVEL + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_LEVEL)); - assertTrue(TEST_LOGGER_LEVEL + " logger was not in the returned list", list.containsKey(TEST_LOGGER_LEVEL)); - - //check that their level is as expected - assertTrue(TEST_CATEGORY_PRIORITY + " logger's level was incorrect", list.get(TEST_CATEGORY_PRIORITY).equalsIgnoreCase("info")); - assertTrue(TEST_CATEGORY_LEVEL + " logger's level was incorrect", list.get(TEST_CATEGORY_LEVEL).equalsIgnoreCase("warn")); - assertTrue(TEST_LOGGER_LEVEL + " logger's level was incorrect", list.get(TEST_LOGGER_LEVEL).equalsIgnoreCase("error")); - - //increase their levels a notch to test the 3 different types of logger definition are successfully updated - //change the category+priority to warn - assertTrue("failed to set new level", lm.setConfigFileLoggerLevel(TEST_CATEGORY_PRIORITY, "warn")); - //change the category+level to error - assertTrue("failed to set new level", lm.setConfigFileLoggerLevel(TEST_CATEGORY_LEVEL, "error")); - //change the logger+level to trace - assertTrue("failed to set new level", lm.setConfigFileLoggerLevel(TEST_LOGGER_LEVEL, "trace")); - - //try an invalid level - assertFalse("Use of an invalid logger level was successfull", lm.setConfigFileLoggerLevel(TEST_LOGGER_LEVEL, "made.up.level")); - - //try an invalid logger name - assertFalse("Use of an invalid logger name was successfull", lm.setConfigFileLoggerLevel("made.up.logger.name", "info")); - - //retrieve the new values from the file and check them - levels = (TabularDataSupport) lm.viewConfigFileLoggerLevels(); - records = levels.values(); - list = new HashMap<String,String>(); - for (Object o : records) - { - CompositeData data = (CompositeData) o; - list.put(data.get(LOGGER_NAME).toString(), data.get(LOGGER_LEVEL).toString()); - } - - //check the 3 different types of logger definition are successfully retrieved after update - assertTrue("Wrong number of items in returned list", list.size() == 3); - assertTrue(TEST_CATEGORY_PRIORITY + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_PRIORITY)); - assertTrue(TEST_CATEGORY_LEVEL + " logger was not in the returned list", list.containsKey(TEST_CATEGORY_LEVEL)); - assertTrue(TEST_LOGGER_LEVEL + " logger was not in the returned list", list.containsKey(TEST_LOGGER_LEVEL)); - - //check that their level is as expected after the changes - assertTrue(TEST_CATEGORY_PRIORITY + " logger's level was incorrect", list.get(TEST_CATEGORY_PRIORITY).equalsIgnoreCase("warn")); - assertTrue(TEST_CATEGORY_LEVEL + " logger's level was incorrect", list.get(TEST_CATEGORY_LEVEL).equalsIgnoreCase("error")); - assertTrue(TEST_LOGGER_LEVEL + " logger's level was incorrect", list.get(TEST_LOGGER_LEVEL).equalsIgnoreCase("trace")); - } - - public void testGetAndSetConfigFileRootLoggerLevel() throws Exception - { - LoggingManagementMBean lm =null; - try - { - lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 0); - } - catch (JMException e) - { - fail("Could not create test LoggingManagementMBean"); - } - - //retrieve the current value - String level = lm.getConfigFileRootLoggerLevel(); - - //check the value was successfully retrieved before update - assertTrue("Retrieved RootLogger level was incorrect", level.equalsIgnoreCase("info")); - - //try an invalid level - assertFalse("Use of an invalid RootLogger level was successfull", lm.setConfigFileRootLoggerLevel("made.up.level")); - - //change the level to warn - assertTrue("Failed to set new RootLogger level", lm.setConfigFileRootLoggerLevel("warn")); - - //retrieve the current value - level = lm.getConfigFileRootLoggerLevel(); - - //check the value was successfully retrieved after update - assertTrue("Retrieved RootLogger level was incorrect", level.equalsIgnoreCase("warn")); - } - - public void testGetLog4jLogWatchInterval() - { - LoggingManagementMBean lm =null; - try - { - lm = new LoggingManagementMBean(_testConfigFile.getAbsolutePath(), 5000); - } - catch (JMException e) - { - fail("Could not create test LoggingManagementMBean"); - } - - assertTrue("Wrong value returned for logWatch period", lm.getLog4jLogWatchInterval() == 5000); - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java index e87d292471..6571d20711 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BrokerMessagesTest.java @@ -20,10 +20,9 @@ */ package org.apache.qpid.server.logging.messages; +import java.text.NumberFormat; import java.util.List; -import org.apache.derby.iapi.services.io.FileUtil; - /** * Test BRK log Messages */ @@ -139,7 +138,7 @@ public class BrokerMessagesTest extends AbstractTestMessages _logMessage = BrokerMessages.MAX_MEMORY(oneGiga); List<Object> log = performLog(); - String[] expected = {"Maximum Memory :", "1,073,741,824", "bytes"}; + String[] expected = {"Maximum Memory :", NumberFormat.getNumberInstance().format(oneGiga), "bytes"}; validateLogMessage(log, "BRK-1011", expected); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java deleted file mode 100644 index f7d85c11a8..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/management/AMQUserManagementMBeanTest.java +++ /dev/null @@ -1,153 +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.UserManagement; -import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; -import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; - -/** - * - * Tests the AMQUserManagementMBean and its interaction with the PrincipalDatabase. - * - */ -public class AMQUserManagementMBeanTest extends InternalBrokerBaseCase -{ - private PlainPasswordFilePrincipalDatabase _database; - private AMQUserManagementMBean _amqumMBean; - - private File _passwordFile; - - private static final String TEST_USERNAME = "testuser"; - private static final String TEST_PASSWORD = "password"; - - @Override - public void setUp() throws Exception - { - super.setUp(); - - _database = new PlainPasswordFilePrincipalDatabase(); - _amqumMBean = new AMQUserManagementMBean(); - loadFreshTestPasswordFile(); - } - - @Override - public void tearDown() throws Exception - { - //clean up test password/access files - File _oldPasswordFile = new File(_passwordFile.getAbsolutePath() + ".old"); - _oldPasswordFile.delete(); - _passwordFile.delete(); - - super.tearDown(); - } - - public void testDeleteUser() - { - assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size()); - assertTrue("Delete should return true to flag successful delete", _amqumMBean.deleteUser(TEST_USERNAME)); - assertEquals("Unexpected number of users after test", 0,_amqumMBean.viewUsers().size()); - } - - public void testDeleteUserWhereUserDoesNotExist() - { - assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size()); - assertFalse("Delete should return false to flag unsuccessful delete", _amqumMBean.deleteUser("made.up.username")); - assertEquals("Unexpected number of users after test", 1,_amqumMBean.viewUsers().size()); - - } - - public void testCreateUser() - { - assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size()); - assertTrue("Create should return true to flag successful create", _amqumMBean.createUser("newuser", "mypass")); - assertEquals("Unexpected number of users before test", 2,_amqumMBean.viewUsers().size()); - } - - public void testCreateUserWhereUserAlreadyExists() - { - assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size()); - assertFalse("Create should return false to flag unsuccessful create", _amqumMBean.createUser(TEST_USERNAME, "mypass")); - assertEquals("Unexpected number of users before test", 1,_amqumMBean.viewUsers().size()); - } - - public void testSetPassword() - { - assertTrue("Set password should return true to flag successful change", _amqumMBean.setPassword(TEST_USERNAME, "newpassword")); - } - - public void testSetPasswordWhereUserDoesNotExist() - { - assertFalse("Set password should return false to flag successful change", _amqumMBean.setPassword("made.up.username", "newpassword")); - } - - public void testViewUsers() - { - TabularData userList = _amqumMBean.viewUsers(); - - assertNotNull(userList); - assertEquals("Unexpected number of users in user list", 1, userList.size()); - assertTrue(userList.containsKey(new Object[]{TEST_USERNAME})); - - // Check the deprecated read, write and admin items continue to exist but return false. - CompositeData userRec = userList.get(new Object[]{TEST_USERNAME}); - assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_ONLY)); - assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_ONLY)); - assertEquals(false, userRec.get(UserManagement.RIGHTS_READ_WRITE)); - assertTrue(userRec.containsKey(UserManagement.RIGHTS_READ_WRITE)); - assertTrue(userRec.containsKey(UserManagement.RIGHTS_ADMIN)); - assertEquals(false, userRec.get(UserManagement.RIGHTS_ADMIN)); - } - - // ============================ Utility methods ========================= - - private void loadFreshTestPasswordFile() - { - try - { - if(_passwordFile == null) - { - _passwordFile = File.createTempFile(this.getClass().getName(),".password"); - } - - BufferedWriter passwordWriter = new BufferedWriter(new FileWriter(_passwordFile, false)); - passwordWriter.write(TEST_USERNAME + ":" + TEST_PASSWORD); - passwordWriter.newLine(); - passwordWriter.flush(); - passwordWriter.close(); - _database.setPasswordFile(_passwordFile.toString()); - _amqumMBean.setPrincipalDatabase(_database); - } - catch (IOException e) - { - fail("Unable to create test password file: " + e.getMessage()); - } - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java b/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java new file mode 100644 index 0000000000..643132d371 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/model/UUIDGeneratorTest.java @@ -0,0 +1,213 @@ +/* + * + * 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.HashSet; +import java.util.Set; +import java.util.UUID; + +import org.apache.qpid.test.utils.QpidTestCase; + +public class UUIDGeneratorTest extends QpidTestCase +{ + private static final String VIRTUAL_HOST_NAME_1 = "virtualHost1"; + private static final String VIRTUAL_HOST_NAME_2 = "virtualHost2"; + private static final String VHOST_ALIAS_1 = "alias1"; + private static final String VHOST_ALIAS_2 = "alias2"; + private static final String QUEUE_NAME_1 = "queue1"; + private static final String QUEUE_NAME_2 = "queue2"; + private static final String EXCHANGE_NAME_1 = "exchange1"; + private static final String EXCHANGE_NAME_2 = "exchange2"; + private static final String BINDING_KEY_1 = "bindingKey1"; + private static final String BINDING_KEY_2 = "bindingKey2"; + private static final String PORT_1 = "port1"; + private static final String PORT_2 = "port2"; + private static final String CONN_REMOTE_ADDR_1 = "localhost:1234"; + private static final String CONN_REMOTE_ADDR_2 = "localhost:5678"; + private static final String CHANNEL_NUMBER_1 = "1"; + private static final String CHANNEL_NUMBER_2 = "2"; + private static final String CONSUMER_NAME_1 = "consumer1"; + private static final String CONSUMER_NAME_2 = "consumer2"; + private static final String PROVIDER_1 = "provider1"; + private static final String PROVIDER_2 = "provider2"; + private static final String USER_1 = "user1"; + private static final String USER_2 = "user2"; + + public void testDifferentObjectTypeReturnDifferentIdFromSameValues() throws Exception + { + String value = "name"; + Set<UUID> idSet = new HashSet<UUID>(); + + UUID id1 = UUIDGenerator.generateQueueUUID(value, value); + idSet.add(id1); + UUID id2 = UUIDGenerator.generateExchangeUUID(value, value); + idSet.add(id2); + UUID id3 = UUIDGenerator.generateBindingUUID(value, value, value, value); + idSet.add(id3); + UUID id4 = UUIDGenerator.generateConsumerUUID(value, value, value, value, value); + idSet.add(id4); + UUID id5 = UUIDGenerator.generateUserUUID(value, value); + idSet.add(id5); + UUID id6 = UUIDGenerator.generateVhostUUID(value); + idSet.add(id6); + UUID id7 = UUIDGenerator.generateVhostAliasUUID(value, value); + idSet.add(id7); + + assertEquals("The produced UUIDs were not all unique", 7, idSet.size()); + } + + public void testQueueIdGeneration() throws Exception + { + //check repeated generation is deterministic + UUID queue1 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1); + UUID queue2 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1); + assertEquals("Queue IDs should be equal", queue1, queue2); + + //check different name gives different ID + queue1 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1); + queue2 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_2, VIRTUAL_HOST_NAME_1); + assertFalse("Queue IDs should not be equal", queue1.equals(queue2)); + + //check different vhost name gives different ID + queue1 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_1); + queue2 = UUIDGenerator.generateQueueUUID(QUEUE_NAME_1, VIRTUAL_HOST_NAME_2); + assertFalse("Queue IDs should not be equal", queue1.equals(queue2)); + } + + public void testExchangeIdGeneration() throws Exception + { + //check repeated generation is deterministic + UUID exchange1 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1); + UUID exchange2 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1); + assertEquals("Exchange IDs should be equal", exchange1, exchange2); + + //check different name gives different ID + exchange1 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1); + exchange2 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_2, VIRTUAL_HOST_NAME_1); + assertFalse("Exchange IDs should not be equal", exchange1.equals(exchange2)); + + //check different vhost name gives different ID + exchange1 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_1); + exchange2 = UUIDGenerator.generateExchangeUUID(EXCHANGE_NAME_1, VIRTUAL_HOST_NAME_2); + assertFalse("Exchange IDs should not be equal", exchange1.equals(exchange2)); + } + + public void testBindingIdGeneration() throws Exception + { + //check repeated generation is deterministic + UUID binding1 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1); + UUID binding2 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1); + assertEquals("Binding IDs should be equal", binding1, binding2); + + //check different name gives different ID + binding1 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1); + binding2 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_2, VIRTUAL_HOST_NAME_1); + assertFalse("Binding IDs should not be equal", binding1.equals(binding2)); + + //check different vhost name gives different ID + binding1 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_1); + binding2 = UUIDGenerator.generateBindingUUID(EXCHANGE_NAME_1, QUEUE_NAME_1, BINDING_KEY_1, VIRTUAL_HOST_NAME_2); + assertFalse("Binding IDs should not be equal", binding1.equals(binding2)); + } + + public void testVhostIdGeneration() throws Exception + { + //check repeated generation is deterministic + UUID vhost1 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_1); + UUID vhost2 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_1); + assertTrue("Virtualhost IDs should be equal", vhost1.equals(vhost2)); + + //check different vhost name gives different ID + vhost1 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_1); + vhost2 = UUIDGenerator.generateVhostUUID(VIRTUAL_HOST_NAME_2); + assertFalse("Virtualhost IDs should not be equal", vhost1.equals(vhost2)); + } + + public void testVhostAliasIdGeneration() throws Exception + { + //check repeated generation is deterministic + UUID alias1 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1); + UUID alias2 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1); + assertTrue("Virtualhost Alias IDs should be equal", alias1.equals(alias2)); + + //check different port name gives different ID + alias1 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1); + alias2 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_2, PORT_1); + assertFalse("Virtualhost Alias IDs should not be equal", alias1.equals(alias2)); + + //check different alias name gives different ID + alias1 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_1); + alias2 = UUIDGenerator.generateVhostAliasUUID(VHOST_ALIAS_1, PORT_2); + assertFalse("Virtualhost Alias IDs should not be equal", alias1.equals(alias2)); + } + + public void testConsumerIdGeneration() throws Exception + { + //check repeated generation is deterministic + UUID consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + UUID consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + assertTrue("Consumer IDs should be equal", consumer1.equals(consumer2)); + + //check different name gives different ID + consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_2); + assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2)); + + //check different vhost name gives different ID + consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_2, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2)); + + //check different consumer name gives different ID + consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_2, CONSUMER_NAME_1); + assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2)); + + //check different address name gives different ID + consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_2, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2)); + + //check different queue name gives different ID + consumer1 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_1, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + consumer2 = UUIDGenerator.generateConsumerUUID(VIRTUAL_HOST_NAME_1, QUEUE_NAME_2, CONN_REMOTE_ADDR_1, CHANNEL_NUMBER_1, CONSUMER_NAME_1); + assertFalse("Consumer IDs should not be equal", consumer1.equals(consumer2)); + } + + public void testUserIdGeneration() throws Exception + { + //check repeated generation is deterministic + UUID user1 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1); + UUID user2 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1); + assertTrue("User IDs should be equal", user1.equals(user2)); + + //check different name gives different ID + user1 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1); + user2 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_2); + assertFalse("User IDs should not be equal", user1.equals(user2)); + + //check different provider gives different ID + user1 = UUIDGenerator.generateUserUUID(PROVIDER_1, USER_1); + user2 = UUIDGenerator.generateUserUUID(PROVIDER_2, USER_1); + assertFalse("User IDs should not be equal", user1.equals(user2)); + } + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java b/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java index 267545c656..20abdd48cd 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtilTest.java @@ -73,11 +73,11 @@ public class OsgiSystemPackageUtilTest extends QpidTestCase _map.put("org.apache.qpid.xyz", "1.0.0"); _map.put("org.abc", "1.2.3"); - _util = new OsgiSystemPackageUtil(new Version("0.17"), _map); + _util = new OsgiSystemPackageUtil(new Version("0.19"), _map); final String systemPackageString = _util.getFormattedSystemPackageString(); - assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.17.0", systemPackageString); + assertEquals("org.abc; version=1.2.3, org.apache.qpid.xyz; version=0.19.0", systemPackageString); } public void testWithQpidPackageWithoutQpidReleaseNumberSet() throws Exception diff --git a/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java deleted file mode 100644 index fe9bcc57a6..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBeanTest.java +++ /dev/null @@ -1,146 +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.protocol; - -import org.apache.log4j.Logger; - -import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.management.common.mbeans.ManagedConnection; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.store.MessageStore; -import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.util.InternalBrokerBaseCase; -import org.apache.qpid.server.virtualhost.VirtualHost; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; - - -/** Test class to test MBean operations for AMQMinaProtocolSession. */ -public class AMQProtocolSessionMBeanTest extends InternalBrokerBaseCase -{ - /** Used for debugging. */ - private static final Logger log = Logger.getLogger(AMQProtocolSessionMBeanTest.class); - - private MessageStore _messageStore = new TestableMemoryMessageStore(); - private AMQProtocolEngine _protocolSession; - private AMQChannel _channel; - private AMQProtocolSessionMBean _mbean; - - public void testChannels() throws Exception - { - // check the channel count is correct - int channelCount = _mbean.channels().size(); - assertTrue(channelCount == 1); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue_" + System.currentTimeMillis()), - false, - new AMQShortString("test"), - true, - false, _protocolSession.getVirtualHost(), null); - AMQChannel channel = new AMQChannel(_protocolSession, 2, _messageStore); - channel.setDefaultQueue(queue); - _protocolSession.addChannel(channel); - channelCount = _mbean.channels().size(); - assertTrue(channelCount == 2); - - // general properties test - _protocolSession.setMaximumNumberOfChannels(1000L); - assertTrue(_mbean.getMaximumNumberOfChannels() == 1000L); - - // check APIs - AMQChannel channel3 = new AMQChannel(_protocolSession, 3, _messageStore); - channel3.setLocalTransactional(); - _protocolSession.addChannel(channel3); - _mbean.rollbackTransactions(2); - _mbean.rollbackTransactions(3); - _mbean.commitTransactions(2); - _mbean.commitTransactions(3); - - // This should throw exception, because the channel does't exist - try - { - _mbean.commitTransactions(4); - fail(); - } - catch (JMException ex) - { - log.debug("expected exception is thrown :" + ex.getMessage()); - } - - // check channels() return type conveys flow control blocking status correctly - AMQChannel channel4 = new AMQChannel(_protocolSession, 4, _messageStore); - _protocolSession.addChannel(channel4); - channel4.setDefaultQueue(queue); - - final String blocking = ManagedConnection.FLOW_BLOCKED; - TabularData channels = _mbean.channels(); - CompositeData chan4result = channels.get(new Integer[]{4}); - assertNotNull(chan4result); - assertEquals("Flow should not have been blocked", false, chan4result.get(blocking)); - - channel4.block(queue); - channels = _mbean.channels(); - chan4result = channels.get(new Integer[]{4}); - assertNotNull(chan4result); - assertEquals("Flow should have been blocked", true, chan4result.get(blocking)); - - channel4.unblock(queue); - channels = _mbean.channels(); - chan4result = channels.get(new Integer[]{4}); - assertNotNull(chan4result); - assertEquals("Flow should have been unblocked", false, chan4result.get(blocking)); - - // check if closing of session works - _protocolSession.addChannel(new AMQChannel(_protocolSession, 5, _messageStore)); - _mbean.closeConnection(); - try - { - channelCount = _mbean.channels().size(); - assertTrue(channelCount == 0); - // session is now closed so adding another channel should throw an exception - _protocolSession.addChannel(new AMQChannel(_protocolSession, 6, _messageStore)); - fail(); - } - catch (AMQException ex) - { - log.debug("expected exception is thrown :" + ex.getMessage()); - } - } - - @Override - public void setUp() throws Exception - { - super.setUp(); - - VirtualHost vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"); - _protocolSession = new InternalTestProtocolSession(vhost); - - _channel = new AMQChannel(_protocolSession, 1, _messageStore); - _protocolSession.addChannel(_channel); - _mbean = (AMQProtocolSessionMBean) _protocolSession.getManagedObject(); - } - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java index 01a2178911..c3d58f3bdc 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQPriorityQueueTest.java @@ -1,4 +1,3 @@ -package org.apache.qpid.server.queue; /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -19,6 +18,7 @@ package org.apache.qpid.server.queue; * under the License. * */ +package org.apache.qpid.server.queue; import junit.framework.AssertionFailedError; diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java deleted file mode 100644 index 25d35aab16..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueAlertTest.java +++ /dev/null @@ -1,348 +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.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import javax.management.Notification; - -import java.nio.ByteBuffer; -import java.util.ArrayList; - -/** This class tests all the alerts an AMQQueue can throw based on threshold values of different parameters */ -public class AMQQueueAlertTest extends InternalBrokerBaseCase -{ - private final static long MAX_MESSAGE_COUNT = 50; - private final static long MAX_MESSAGE_AGE = 250; // 0.25 sec - private final static long MAX_MESSAGE_SIZE = 2000; // 2 KB - private final static long MAX_QUEUE_DEPTH = 10000; // 10 KB - private AMQQueueMBean _queueMBean; - private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE; - - /** - * Tests if the alert gets thrown when message count increases the threshold limit - * - * @throws Exception - */ - public void testMessageCountAlert() throws Exception - { - setSession(new InternalTestProtocolSession(getVirtualHost())); - AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore()); - getSession().addChannel(channel); - - setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue1"), false, new AMQShortString("AMQueueAlertTest"), - false, false, - getVirtualHost(), null)); - _queueMBean = (AMQQueueMBean) getQueue().getManagedObject(); - - _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT); - - sendMessages(channel, MAX_MESSAGE_COUNT, 256l); - assertTrue(_queueMBean.getMessageCount() == MAX_MESSAGE_COUNT); - - Notification lastNotification = _queueMBean.getLastNotification(); - assertNotNull(lastNotification); - - String notificationMsg = lastNotification.getMessage(); - assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_COUNT_ALERT.name())); - } - - /** - * Tests if the Message Size alert gets thrown when message of higher than threshold limit is sent - * - * @throws Exception - */ - public void testMessageSizeAlert() throws Exception - { - setSession(new InternalTestProtocolSession(getVirtualHost())); - AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore()); - getSession().addChannel(channel); - - setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue2"), false, new AMQShortString("AMQueueAlertTest"), - false, false, - getVirtualHost(), null)); - _queueMBean = (AMQQueueMBean) getQueue().getManagedObject(); - _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT); - _queueMBean.setMaximumMessageSize(MAX_MESSAGE_SIZE); - - sendMessages(channel, 1, MAX_MESSAGE_SIZE * 2); - assertTrue(_queueMBean.getMessageCount() == 1); - - Notification lastNotification = _queueMBean.getLastNotification(); - assertNotNull(lastNotification); - - String notificationMsg = lastNotification.getMessage(); - assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_SIZE_ALERT.name())); - } - - /** - * Tests if Queue Depth alert is thrown when queue depth reaches the threshold value - * - * Based on FT-402 subbmitted by client - * - * @throws Exception - */ - public void testQueueDepthAlertNoSubscriber() throws Exception - { - setSession(new InternalTestProtocolSession(getVirtualHost())); - AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore()); - getSession().addChannel(channel); - - setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue3"), false, new AMQShortString("AMQueueAlertTest"), - false, false, - getVirtualHost(), null)); - _queueMBean = (AMQQueueMBean) getQueue().getManagedObject(); - _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT); - _queueMBean.setMaximumQueueDepth(MAX_QUEUE_DEPTH); - - while (getQueue().getQueueDepth() < MAX_QUEUE_DEPTH) - { - sendMessages(channel, 1, MAX_MESSAGE_SIZE); - } - - Notification lastNotification = _queueMBean.getLastNotification(); - assertNotNull(lastNotification); - - String notificationMsg = lastNotification.getMessage(); - assertTrue(notificationMsg.startsWith(NotificationCheck.QUEUE_DEPTH_ALERT.name())); - } - - /** - * Tests if MESSAGE AGE alert is thrown, when a message is in the queue for time higher than threshold value of - * message age - * - * Alternative test to FT-401 provided by client - * - * @throws Exception - */ - public void testMessageAgeAlert() throws Exception - { - setSession(new InternalTestProtocolSession(getVirtualHost())); - AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore()); - getSession().addChannel(channel); - - setQueue(AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue4"), false, new AMQShortString("AMQueueAlertTest"), - false, false, - getVirtualHost(), null)); - _queueMBean = (AMQQueueMBean) getQueue().getManagedObject(); - _queueMBean.setMaximumMessageCount(MAX_MESSAGE_COUNT); - _queueMBean.setMaximumMessageAge(MAX_MESSAGE_AGE); - - sendMessages(channel, 1, MAX_MESSAGE_SIZE); - - // Ensure message sits on queue long enough to age. - Thread.sleep(MAX_MESSAGE_AGE * 2); - - Notification lastNotification = _queueMBean.getLastNotification(); - assertNotNull("Last notification was null", lastNotification); - - String notificationMsg = lastNotification.getMessage(); - assertTrue(notificationMsg.startsWith(NotificationCheck.MESSAGE_AGE_ALERT.name())); - } - - /* - This test sends some messages to the queue with subscribers needing message to be acknowledged. - The messages will not be acknowledged and will be required twice. Why we are checking this is because - the bug reported said that the queueDepth keeps increasing when messages are requeued. - // TODO - queue depth now includes unacknowledged messages so does not go down when messages are delivered - - The QueueDepth should decrease when messages are delivered from the queue (QPID-408) - */ - public void testQueueDepthAlertWithSubscribers() throws Exception - { - AMQChannel channel = new AMQChannel(getSession(), 2, getMessageStore()); - getSession().addChannel(channel); - - // Create queue - setQueue(getNewQueue()); - Subscription subscription = - SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), getSession(), new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager()); - - getQueue().registerSubscription( - subscription, false); - - _queueMBean = (AMQQueueMBean) getQueue().getManagedObject(); - _queueMBean.setMaximumMessageCount(9999l); // Set a high value, because this is not being tested - _queueMBean.setMaximumQueueDepth(MAX_QUEUE_DEPTH); - - // Send messages(no of message to be little more than what can cause a Queue_Depth alert) - int messageCount = Math.round(MAX_QUEUE_DEPTH / MAX_MESSAGE_SIZE) + 10; - long totalSize = (messageCount * MAX_MESSAGE_SIZE); - sendMessages(channel, messageCount, MAX_MESSAGE_SIZE); - - // Check queueDepth. There should be no messages on the queue and as the subscriber is listening - // so there should be no Queue_Deoth alert raised - assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth())); - Notification lastNotification = _queueMBean.getLastNotification(); -// assertNull(lastNotification); - - // Kill the subscriber and check for the queue depth values. - // Messages are unacknowledged, so those should get requeued. All messages should be on the Queue - getQueue().unregisterSubscription(subscription); - channel.requeue(); - - assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth())); - - lastNotification = _queueMBean.getLastNotification(); - assertNotNull(lastNotification); - String notificationMsg = lastNotification.getMessage(); - assertTrue(notificationMsg.startsWith(NotificationCheck.QUEUE_DEPTH_ALERT.name())); - - // Connect a consumer again and check QueueDepth values. The queue should get emptied. - // Messages will get delivered but still are unacknowledged. - Subscription subscription2 = - SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), getSession(), new AMQShortString("consumer_tag"), true, null, false, channel.getCreditManager()); - - getQueue().registerSubscription( - subscription2, false); - - while (getQueue().getUndeliveredMessageCount()!= 0) - { - Thread.sleep(100); - } -// assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth())); - - // Kill the subscriber again. Now those messages should get requeued again. Check if the queue depth - // value is correct. - getQueue().unregisterSubscription(subscription2); - channel.requeue(); - - assertEquals(new Long(totalSize), new Long(_queueMBean.getQueueDepth())); - getSession().closeSession(); - - // Check the clear queue - _queueMBean.clearQueue(); - assertEquals(new Long(0), new Long(_queueMBean.getQueueDepth())); - } - - protected IncomingMessage message(final boolean immediate, long size) throws AMQException - { - MessagePublishInfo publish = new MessagePublishInfo() - { - - public AMQShortString getExchange() - { - return null; - } - - public void setExchange(AMQShortString exchange) - { - //To change body of implemented methods use File | Settings | File Templates. - } - - public boolean isImmediate() - { - return immediate; - } - - public boolean isMandatory() - { - return false; - } - - public AMQShortString getRoutingKey() - { - return null; - } - }; - - ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); - BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - contentHeaderBody.setProperties(props); - contentHeaderBody.setBodySize(size); // in bytes - IncomingMessage message = new IncomingMessage(publish); - message.setContentHeaderBody(contentHeaderBody); - - return message; - } - - @Override - protected void configure() - { - // Increase Alert Check period - getConfiguration().setHousekeepingCheckPeriod(200); - } - - private void sendMessages(AMQChannel channel, long messageCount, final long size) throws AMQException - { - IncomingMessage[] messages = new IncomingMessage[(int) messageCount]; - MessageMetaData[] metaData = new MessageMetaData[(int) messageCount]; - for (int i = 0; i < messages.length; i++) - { - messages[i] = message(false, size); - ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); - qs.add(getQueue()); - metaData[i] = messages[i].headersReceived(System.currentTimeMillis()); - messages[i].setStoredMessage(getMessageStore().addMessage(metaData[i])); - - messages[i].enqueue(qs); - - } - - for (int i = 0; i < messageCount; i++) - { - ContentChunk contentChunk = new ContentChunk() - { - private byte[] _data = new byte[(int)size]; - - public int getSize() - { - return (int) size; - } - - public byte[] getData() - { - return _data; - } - - public void reduceToFit() - { - } - }; - - messages[i].addContentBodyFrame(contentChunk); - messages[i].getStoredMessage().addContent(0, ByteBuffer.wrap(contentChunk.getData())); - - getQueue().enqueue(new AMQMessage(messages[i].getStoredMessage())); - } - } - - private AMQQueue getNewQueue() throws AMQException - { - return AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testQueue" + Math.random()), - false, - new AMQShortString("AMQueueAlertTest"), - false, - false, getVirtualHost(), null); - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java index e123a968a4..186be4dff7 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueFactoryTest.java @@ -20,8 +20,6 @@ */ package org.apache.qpid.server.queue; -import java.util.UUID; - import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.AMQException; @@ -35,9 +33,9 @@ import org.apache.qpid.server.exchange.ExchangeRegistry; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory; import org.apache.qpid.server.util.TestApplicationRegistry; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -56,7 +54,7 @@ public class AMQQueueFactoryTest extends QpidTestCase XMLConfiguration configXml = new XMLConfiguration(); configXml.addProperty("virtualhosts.virtualhost(-1).name", getName()); - configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.factoryclass", TestableMemoryMessageStoreFactory.class.getName()); + configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName()); ServerConfiguration configuration = new ServerConfiguration(configXml); @@ -100,8 +98,8 @@ public class AMQQueueFactoryTest extends QpidTestCase fieldTable.put(new AMQShortString(AMQQueueFactory.X_QPID_PRIORITIES), 5); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("testPriorityQueue"), false, new AMQShortString("owner"), false, - false, _virtualHost, fieldTable); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testPriorityQueue", false, "owner", false, + false, _virtualHost, FieldTable.convertToMap(fieldTable)); assertEquals("Queue not a priorty queue", AMQPriorityQueue.class, queue.getClass()); verifyQueueRegistered("testPriorityQueue"); @@ -111,13 +109,13 @@ public class AMQQueueFactoryTest extends QpidTestCase public void testSimpleQueueRegistration() throws Exception { - AMQShortString queueName = new AMQShortString("testSimpleQueueRegistration"); + String queueName = getName(); AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false, _virtualHost, null); assertEquals("Queue not a simple queue", SimpleAMQQueue.class, queue.getClass()); - verifyQueueRegistered("testSimpleQueueRegistration"); + verifyQueueRegistered(queueName); //verify that no alternate exchange or DLQ were produced QueueRegistry qReg = _virtualHost.getQueueRegistry(); @@ -138,7 +136,7 @@ public class AMQQueueFactoryTest extends QpidTestCase FieldTable fieldTable = new FieldTable(); fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); - AMQShortString queueName = new AMQShortString("testDeadLetterQueueEnabled"); + String queueName = "testDeadLetterQueueEnabled"; AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); @@ -148,8 +146,8 @@ public class AMQQueueFactoryTest extends QpidTestCase assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName)); assertNull("The alternate exchange should not yet exist", exReg.getExchange(dlExchangeName)); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false, - _virtualHost, fieldTable); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false, + _virtualHost, FieldTable.convertToMap(fieldTable)); Exchange altExchange = queue.getAlternateExchange(); assertNotNull("Queue should have an alternate exchange as DLQ is enabled", altExchange); @@ -179,7 +177,7 @@ public class AMQQueueFactoryTest extends QpidTestCase ApplicationRegistry.getInstance().getConfiguration().getConfig().addProperty("deadLetterQueues","true"); ApplicationRegistry.getInstance().getConfiguration().getConfig().addProperty("maximumDeliveryCount","5"); - AMQShortString queueName = new AMQShortString("testDeadLetterQueueEnabled"); + String queueName = "testDeadLetterQueueEnabled"; AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); @@ -189,7 +187,7 @@ public class AMQQueueFactoryTest extends QpidTestCase assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName)); assertNull("The alternate exchange should not yet exist", exReg.getExchange(dlExchangeName)); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false, + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false, _virtualHost, null); assertEquals("Unexpected maximum delivery count", 5, queue.getMaximumDeliveryCount()); @@ -221,7 +219,7 @@ public class AMQQueueFactoryTest extends QpidTestCase FieldTable fieldTable = new FieldTable(); fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, false); - AMQShortString queueName = new AMQShortString("testDeadLetterQueueDisabled"); + String queueName = "testDeadLetterQueueDisabled"; AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); @@ -231,8 +229,8 @@ public class AMQQueueFactoryTest extends QpidTestCase assertNull("The DLQ should not yet exist", qReg.getQueue(dlQueueName)); assertNull("The alternate exchange should not exist", exReg.getExchange(dlExchangeName)); - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false, - _virtualHost, fieldTable); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", false, false, + _virtualHost, FieldTable.convertToMap(fieldTable)); assertNull("Queue should not have an alternate exchange as DLQ is disabled", queue.getAlternateExchange()); assertNull("The alternate exchange should still not exist", exReg.getExchange(dlExchangeName)); @@ -254,7 +252,7 @@ public class AMQQueueFactoryTest extends QpidTestCase FieldTable fieldTable = new FieldTable(); fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); - AMQShortString queueName = new AMQShortString("testDeadLetterQueueNotCreatedForAutodeleteQueues"); + String queueName = "testDeadLetterQueueNotCreatedForAutodeleteQueues"; AMQShortString dlExchangeName = new AMQShortString(queueName + DefaultExchangeFactory.DEFAULT_DLE_NAME_SUFFIX); AMQShortString dlQueueName = new AMQShortString(queueName + AMQQueueFactory.DEFAULT_DLQ_NAME_SUFFIX); @@ -265,8 +263,8 @@ public class AMQQueueFactoryTest extends QpidTestCase assertNull("The alternate exchange should not exist", exReg.getExchange(dlExchangeName)); //create an autodelete queue - AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), true, false, - _virtualHost, fieldTable); + AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", true, false, + _virtualHost, FieldTable.convertToMap(fieldTable)); assertTrue("Queue should be autodelete", queue.isAutoDelete()); //ensure that the autodelete property overrides the request to enable DLQ @@ -287,10 +285,8 @@ public class AMQQueueFactoryTest extends QpidTestCase final FieldTable fieldTable = new FieldTable(); fieldTable.setInteger(AMQQueueFactory.X_QPID_MAXIMUM_DELIVERY_COUNT, 5); - final AMQShortString queueName = new AMQShortString("testMaximumDeliveryCount"); - - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false, - _virtualHost, fieldTable); + final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testMaximumDeliveryCount", false, "owner", false, false, + _virtualHost, FieldTable.convertToMap(fieldTable)); assertNotNull("The queue was not registered as expected ", queue); assertEquals("Maximum delivery count not as expected", 5, queue.getMaximumDeliveryCount()); @@ -304,10 +300,7 @@ public class AMQQueueFactoryTest extends QpidTestCase */ public void testMaximumDeliveryCountDefault() throws Exception { - - final AMQShortString queueName = new AMQShortString("testMaximumDeliveryCount"); - - final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueName, false, new AMQShortString("owner"), false, false, + final AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "testMaximumDeliveryCount", false, "owner", false, false, _virtualHost, null); assertNotNull("The queue was not registered as expected ", queue); @@ -323,7 +316,7 @@ public class AMQQueueFactoryTest extends QpidTestCase { try { - AMQQueueFactory.createAMQQueueImpl(null, false, new AMQShortString("owner"), true, false, _virtualHost, null); + AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), null, false, "owner", true, false, _virtualHost, null); fail("queue with null name can not be created!"); } catch (Exception e) @@ -350,8 +343,8 @@ public class AMQQueueFactoryTest extends QpidTestCase FieldTable fieldTable = new FieldTable(); fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); - AMQQueueFactory.createAMQQueueImpl(new AMQShortString(queueName), false, new AMQShortString("owner"), - false, false, _virtualHost, fieldTable); + AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", + false, false, _virtualHost, FieldTable.convertToMap(fieldTable)); fail("queue with DLQ name having more than 255 characters can not be created!"); } catch (Exception e) @@ -386,8 +379,8 @@ public class AMQQueueFactoryTest extends QpidTestCase FieldTable fieldTable = new FieldTable(); fieldTable.setBoolean(AMQQueueFactory.X_QPID_DLQ_ENABLED, true); - AMQQueueFactory.createAMQQueueImpl(new AMQShortString(queueName), false, new AMQShortString("owner"), - false, false, _virtualHost, fieldTable); + AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName, false, "owner", + false, false, _virtualHost, FieldTable.convertToMap(fieldTable)); fail("queue with DLE name having more than 255 characters can not be created!"); } catch (Exception e) diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java deleted file mode 100644 index 45933e7064..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AMQQueueMBeanTest.java +++ /dev/null @@ -1,553 +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.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.BasicContentHeaderProperties; -import org.apache.qpid.framing.ContentBody; -import org.apache.qpid.framing.ContentHeaderBody; -import org.apache.qpid.framing.abstraction.ContentChunk; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; -import org.apache.qpid.management.common.mbeans.ManagedQueue; -import org.apache.qpid.server.AMQChannel; -import org.apache.qpid.server.message.AMQMessage; -import org.apache.qpid.server.message.MessageMetaData; -import org.apache.qpid.server.protocol.InternalTestProtocolSession; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.subscription.Subscription; -import org.apache.qpid.server.subscription.SubscriptionFactory; -import org.apache.qpid.server.subscription.SubscriptionFactoryImpl; -import org.apache.qpid.server.util.InternalBrokerBaseCase; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.TabularData; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -/** - * Test class to test AMQQueueMBean attributes and operations - */ -public class AMQQueueMBeanTest extends InternalBrokerBaseCase -{ - private static long MESSAGE_SIZE = 1000; - private AMQQueueMBean _queueMBean; - private static final SubscriptionFactoryImpl SUBSCRIPTION_FACTORY = SubscriptionFactoryImpl.INSTANCE; - - public void testMessageCountTransient() throws Exception - { - int messageCount = 10; - sendMessages(messageCount, false); - assertTrue(_queueMBean.getMessageCount() == messageCount); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - long queueDepth = (messageCount * MESSAGE_SIZE); - assertTrue(_queueMBean.getQueueDepth() == queueDepth); - - _queueMBean.deleteMessageFromTop(); - assertTrue(_queueMBean.getMessageCount() == (messageCount - 1)); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - - _queueMBean.clearQueue(); - assertEquals(0,(int)_queueMBean.getMessageCount()); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - - //Ensure that the data has been removed from the Store - verifyBrokerState(); - } - - public void testMessageCountPersistent() throws Exception - { - int messageCount = 10; - sendMessages(messageCount, true); - assertEquals("", messageCount, _queueMBean.getMessageCount().intValue()); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - long queueDepth = (messageCount * MESSAGE_SIZE); - assertTrue(_queueMBean.getQueueDepth() == queueDepth); - - _queueMBean.deleteMessageFromTop(); - assertTrue(_queueMBean.getMessageCount() == (messageCount - 1)); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - - _queueMBean.clearQueue(); - assertTrue(_queueMBean.getMessageCount() == 0); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - - //Ensure that the data has been removed from the Store - verifyBrokerState(); - } - - public void testDeleteMessages() throws Exception - { - int messageCount = 10; - sendMessages(messageCount, true); - assertEquals("", messageCount, _queueMBean.getMessageCount().intValue()); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - long queueDepth = (messageCount * MESSAGE_SIZE); - assertTrue(_queueMBean.getQueueDepth() == queueDepth); - - //delete first message - _queueMBean.deleteMessages(1L,1L); - assertTrue(_queueMBean.getMessageCount() == (messageCount - 1)); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - try - { - _queueMBean.viewMessageContent(1L); - fail("Message should no longer be on the queue"); - } - catch(Exception e) - { - - } - - //delete last message, leaving 2nd to 9th - _queueMBean.deleteMessages(10L,10L); - assertTrue(_queueMBean.getMessageCount() == (messageCount - 2)); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - try - { - _queueMBean.viewMessageContent(10L); - fail("Message should no longer be on the queue"); - } - catch(Exception e) - { - - } - - //delete remaining messages, leaving none - _queueMBean.deleteMessages(2L,9L); - assertTrue(_queueMBean.getMessageCount() == (0)); - assertTrue(_queueMBean.getReceivedMessageCount() == messageCount); - - //Ensure that the data has been removed from the Store - verifyBrokerState(); - } - - - // todo: collect to a general testing class -duplicated from Systest/MessageReturntest - private void verifyBrokerState() - { - - TestableMemoryMessageStore store = (TestableMemoryMessageStore) getVirtualHost().getMessageStore(); - - // Unlike MessageReturnTest there is no need for a delay as there this thread does the clean up. - - assertEquals("Store should have no messages:" + store.getMessageCount(), 0, store.getMessageCount()); - } - - public void testConsumerCount() throws AMQException - { - - assertTrue(getQueue().getActiveConsumerCount() == 0); - assertTrue(_queueMBean.getActiveConsumerCount() == 0); - - - InternalTestProtocolSession protocolSession = new InternalTestProtocolSession(getVirtualHost()); - - AMQChannel channel = new AMQChannel(protocolSession, 1, getMessageStore()); - protocolSession.addChannel(channel); - - Subscription subscription = - SUBSCRIPTION_FACTORY.createSubscription(channel.getChannelId(), protocolSession, new AMQShortString("test"), false, null, false, channel.getCreditManager()); - - getQueue().registerSubscription(subscription, false); - assertEquals(1,(int)_queueMBean.getActiveConsumerCount()); - - - SubscriptionFactory subscriptionFactory = SUBSCRIPTION_FACTORY; - Subscription s1 = subscriptionFactory.createSubscription(channel.getChannelId(), - protocolSession, - new AMQShortString("S1"), - false, - null, - true, - channel.getCreditManager()); - - Subscription s2 = subscriptionFactory.createSubscription(channel.getChannelId(), - protocolSession, - new AMQShortString("S2"), - false, - null, - true, - channel.getCreditManager()); - getQueue().registerSubscription(s1,false); - getQueue().registerSubscription(s2,false); - assertTrue(_queueMBean.getActiveConsumerCount() == 3); - assertTrue(_queueMBean.getConsumerCount() == 3); - - s1.close(); - assertEquals(2, (int) _queueMBean.getActiveConsumerCount()); - assertTrue(_queueMBean.getConsumerCount() == 3); - } - - public void testGeneralProperties() throws Exception - { - long maxQueueDepth = 1000; // in bytes - _queueMBean.setMaximumMessageCount(50000l); - _queueMBean.setMaximumMessageSize(2000l); - _queueMBean.setMaximumQueueDepth(maxQueueDepth); - - assertEquals("Max MessageCount not set",50000,_queueMBean.getMaximumMessageCount().longValue()); - assertEquals("Max MessageSize not set",2000, _queueMBean.getMaximumMessageSize().longValue()); - assertEquals("Max QueueDepth not set",maxQueueDepth, _queueMBean.getMaximumQueueDepth().longValue()); - - assertEquals("Queue Name does not match", new AMQShortString(getName()), _queueMBean.getName()); - assertFalse("AutoDelete should not be set.",_queueMBean.isAutoDelete()); - assertFalse("Queue should not be durable.",_queueMBean.isDurable()); - - //set+get exclusivity using the mbean, and also verify it is actually updated in the queue - _queueMBean.setExclusive(true); - assertTrue("Exclusive property should be true.",_queueMBean.isExclusive()); - assertTrue("Exclusive property should be true.", getQueue().isExclusive()); - _queueMBean.setExclusive(false); - assertFalse("Exclusive property should be false.",_queueMBean.isExclusive()); - assertFalse("Exclusive property should be false.", getQueue().isExclusive()); - } - - /** - * Tests view messages with two test messages. The first message is non-persistent, the second persistent - * and has timestamp/expiration. - * - */ - public void testViewMessages() throws Exception - { - sendMessages(1, false); - final Date msg2Timestamp = new Date(); - final Date msg2Expiration = new Date(msg2Timestamp.getTime() + 1000); - sendMessages(1, true, msg2Timestamp.getTime(), msg2Expiration.getTime()); - - final TabularData tab = _queueMBean.viewMessages(1l, 2l); - assertEquals("Unexpected number of rows in table", 2, tab.size()); - final Iterator<CompositeDataSupport> rowItr = (Iterator<CompositeDataSupport>) tab.values().iterator(); - - // Check row1 - final CompositeDataSupport row1 = rowItr.next(); - assertEquals("Message should have AMQ message id", 1l, row1.get(ManagedQueue.MSG_AMQ_ID)); - assertNotNull("Expected message header array", row1.get(ManagedQueue.MSG_HEADER)); - final Map<String, String> row1Headers = headerArrayToMap((String[])row1.get(ManagedQueue.MSG_HEADER)); - assertEquals("Unexpected JMSPriority within header", "Non_Persistent", row1Headers.get("JMSDeliveryMode")); - assertEquals("Unexpected JMSTimestamp within header", "null", row1Headers.get("JMSTimestamp")); - assertEquals("Unexpected JMSExpiration within header", "null", row1Headers.get("JMSExpiration")); - - final CompositeDataSupport row2 = rowItr.next(); - assertEquals("Message should have AMQ message id", 2l, row2.get(ManagedQueue.MSG_AMQ_ID)); - assertNotNull("Expected message header array", row2.get(ManagedQueue.MSG_HEADER)); - final Map<String, String> row2Headers = headerArrayToMap((String[])row2.get(ManagedQueue.MSG_HEADER)); - assertEquals("Unexpected JMSPriority within header", "Persistent", row2Headers.get("JMSDeliveryMode")); - assertEquals("Unexpected JMSTimestamp within header", FastDateFormat.getInstance(AMQQueueMBean.JMSTIMESTAMP_DATETIME_FORMAT).format(msg2Timestamp), - row2Headers.get("JMSTimestamp")); - assertEquals("Unexpected JMSExpiration within header", FastDateFormat.getInstance(AMQQueueMBean.JMSTIMESTAMP_DATETIME_FORMAT).format(msg2Expiration), - row2Headers.get("JMSExpiration")); - } - - public void testViewMessageWithIllegalStartEndRanges() throws Exception - { - try - { - _queueMBean.viewMessages(0L, 3L); - fail(); - } - catch (JMException ex) - { - // PASS - } - - try - { - _queueMBean.viewMessages(2L, 1L); - fail(); - } - catch (JMException ex) - { - // PASS - } - - try - { - _queueMBean.viewMessages(-1L, 1L); - fail(); - } - catch (JMException ex) - { - // PASS - } - - try - { - long end = Integer.MAX_VALUE; - end+=2; - _queueMBean.viewMessages(1L, end); - fail("Expected Exception due to oversized(> 2^31) message range"); - } - catch (JMException ex) - { - // PASS - } - } - - public void testViewMessageContent() throws Exception - { - final List<AMQMessage> sentMessages = sendMessages(1, true); - final Long id = sentMessages.get(0).getMessageId(); - - final CompositeData messageData = _queueMBean.viewMessageContent(id); - assertNotNull(messageData); - } - - public void testViewMessageContentWithUnknownMessageId() throws Exception - { - final List<AMQMessage> sentMessages = sendMessages(1, true); - final Long id = sentMessages.get(0).getMessageId(); - - try - { - _queueMBean.viewMessageContent(id + 1); - fail(); - } - catch (JMException ex) - { - // PASS - } - } - - public void testFlowControlProperties() throws Exception - { - assertTrue(_queueMBean.getCapacity() == 0); - assertTrue(_queueMBean.getFlowResumeCapacity() == 0); - assertFalse(_queueMBean.isFlowOverfull()); - - //capacity currently 0, try setting FlowResumeCapacity above this - try - { - _queueMBean.setFlowResumeCapacity(1L); - fail("Should have failed to allow setting FlowResumeCapacity above Capacity"); - } - catch (IllegalArgumentException ex) - { - //expected exception - assertTrue(_queueMBean.getFlowResumeCapacity() == 0); - } - - //add a message to the queue - sendMessages(1, true); - - //(FlowResume)Capacity currently 0, set both to 2 - _queueMBean.setCapacity(2L); - assertTrue(_queueMBean.getCapacity() == 2L); - _queueMBean.setFlowResumeCapacity(2L); - assertTrue(_queueMBean.getFlowResumeCapacity() == 2L); - - //Try setting Capacity below FlowResumeCapacity - try - { - _queueMBean.setCapacity(1L); - fail("Should have failed to allow setting Capacity below FlowResumeCapacity"); - } - catch (IllegalArgumentException ex) - { - //expected exception - assertTrue(_queueMBean.getCapacity() == 2); - } - - //create a channel and use it to exercise the capacity check mechanism - AMQChannel channel = new AMQChannel(getSession(), 1, getMessageStore()); - getQueue().checkCapacity(channel); - - assertTrue(_queueMBean.isFlowOverfull()); - assertTrue(channel.getBlocking()); - - //set FlowResumeCapacity to MESSAGE_SIZE and check queue is now underfull and channel unblocked - _queueMBean.setCapacity(MESSAGE_SIZE);//must increase capacity too - _queueMBean.setFlowResumeCapacity(MESSAGE_SIZE); - - assertFalse(_queueMBean.isFlowOverfull()); - assertFalse(channel.getBlocking()); - } - - public void testMaximumDeliveryCount() throws IOException - { - assertEquals("Unexpected default maximum delivery count", Integer.valueOf(0), _queueMBean.getMaximumDeliveryCount()); - } - - public void testViewAllMessages() throws Exception - { - final int messageCount = 5; - sendPersistentMessages(messageCount); - - - final TabularData messageTable = _queueMBean.viewMessages(1L, 5L); - assertNotNull("Message table should not be null", messageTable); - assertEquals("Unexpected number of rows", messageCount, messageTable.size()); - - - final Iterator rowIterator = messageTable.values().iterator(); - // Get its message ID - final CompositeDataSupport row1 = (CompositeDataSupport) rowIterator.next(); - final Long msgId = (Long) row1.get("AMQ MessageId"); - final Long queuePosition = (Long) row1.get("Queue Position"); - final Integer deliveryCount = (Integer) row1.get("Delivery Count"); - - assertNotNull("Row should have value for queue position", queuePosition); - assertNotNull("Row should have value for msgid", msgId); - assertNotNull("Row should have value for deliveryCount", deliveryCount); - } - - - @Override - public void setUp() throws Exception - { - super.setUp(); - - _queueMBean = new AMQQueueMBean(getQueue()); - } - - public void tearDown() - { - ApplicationRegistry.remove(); - } - - private void sendPersistentMessages(int messageCount) throws AMQException - { - sendMessages(messageCount, true); - assertEquals("Expected " + messageCount + " messages in the queue", messageCount, _queueMBean - .getMessageCount().intValue()); - } - - private List<AMQMessage> sendMessages(int messageCount, boolean persistent) throws AMQException - { - return sendMessages(messageCount, persistent, 0l, 0l); - } - - private List<AMQMessage> sendMessages(int messageCount, boolean persistent, long timestamp, long expiration) throws AMQException - { - final List<AMQMessage> sentMessages = new ArrayList<AMQMessage>(); - - for (int i = 0; i < messageCount; i++) - { - IncomingMessage currentMessage = createIncomingMessage(false, persistent, timestamp, expiration); - ArrayList<AMQQueue> qs = new ArrayList<AMQQueue>(); - qs.add(getQueue()); - currentMessage.enqueue(qs); - - // route header - MessageMetaData mmd = currentMessage.headersReceived(System.currentTimeMillis()); - - // Add the message to the store so we have something to test later - currentMessage.setStoredMessage(getMessageStore().addMessage(mmd)); - ContentChunk chunk = getSession().getMethodRegistry() - .getProtocolVersionMethodConverter() - .convertToContentChunk( - new ContentBody(new byte[(int) MESSAGE_SIZE])); - currentMessage.addContentBodyFrame(chunk); - currentMessage.getStoredMessage().addContent(0, ByteBuffer.wrap(chunk.getData())); - - AMQMessage m = new AMQMessage(currentMessage.getStoredMessage()); - for(BaseQueue q : currentMessage.getDestinationQueues()) - { - q.enqueue(m); - } - - sentMessages.add(m); - } - - return sentMessages; - } - - private IncomingMessage createIncomingMessage(final boolean immediate, boolean persistent, long timestamp, long expiration) throws AMQException - { - MessagePublishInfo publish = new MessagePublishInfo() - { - - public AMQShortString getExchange() - { - return null; - } - - public void setExchange(AMQShortString exchange) - { - } - - public boolean isImmediate() - { - return immediate; - } - - public boolean isMandatory() - { - return false; - } - - public AMQShortString getRoutingKey() - { - return null; - } - }; - - ContentHeaderBody contentHeaderBody = new ContentHeaderBody(); - contentHeaderBody.setBodySize(MESSAGE_SIZE); // in bytes - final BasicContentHeaderProperties props = new BasicContentHeaderProperties(); - contentHeaderBody.setProperties(props); - props.setDeliveryMode((byte) (persistent ? 2 : 1)); - if (timestamp > 0) - { - props.setTimestamp(timestamp); - } - if (expiration > 0) - { - props.setExpiration(expiration); - } - IncomingMessage msg = new IncomingMessage(publish); - msg.setContentHeaderBody(contentHeaderBody); - return msg; - } - - /** - * - * Utility method to convert array of Strings in the form x = y into a - * map with key/value x => y. - * - */ - private Map<String,String> headerArrayToMap(final String[] headerArray) - { - final Map<String, String> headerMap = new HashMap<String, String>(); - final List<String> headerList = Arrays.asList(headerArray); - for (Iterator<String> iterator = headerList.iterator(); iterator.hasNext();) - { - final String nameValuePair = iterator.next(); - final String[] nameValue = nameValuePair.split(" *= *", 2); - headerMap.put(nameValue[0], nameValue[1]); - } - return headerMap; - } - - -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java index 409b9fd92e..190d5c777b 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/AckTest.java @@ -32,6 +32,7 @@ import org.apache.qpid.server.flow.LimitlessCreditManager; import org.apache.qpid.server.flow.Pre0_10CreditManager; import org.apache.qpid.server.message.AMQMessage; import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.protocol.AMQProtocolSession; import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.registry.ApplicationRegistry; @@ -76,7 +77,7 @@ public class AckTest extends InternalBrokerBaseCase _protocolSession.addChannel(_channel); - _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString("myQ"), false, new AMQShortString("guest"), true, false, + _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "myQ", false, "guest", true, false, _virtualHost, null); } diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java new file mode 100644 index 0000000000..a94548f1c3 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/ConflationQueueListTest.java @@ -0,0 +1,211 @@ +/* + * 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 static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import junit.framework.TestCase; + +import org.apache.qpid.server.message.AMQMessage; +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.AMQMessageReference; +import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.virtualhost.VirtualHost; + +public class ConflationQueueListTest extends TestCase +{ + private static final String CONFLATION_KEY = "CONFLATION_KEY"; + + private static final String TEST_KEY_VALUE = "testKeyValue"; + private static final String TEST_KEY_VALUE1 = "testKeyValue1"; + private static final String TEST_KEY_VALUE2 = "testKeyValue2"; + + private ConflationQueueList _list; + private AMQQueue _queue = createTestQueue(); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + _list = new ConflationQueueList(_queue, CONFLATION_KEY); + } + + public void testListHasNoEntries() + { + int numberOfEntries = countEntries(_list); + assertEquals(0, numberOfEntries); + } + + public void testAddMessageWithoutConflationKeyValue() + { + ServerMessage<MessageMetaData> message = createTestServerMessage(null); + + _list.add(message); + int numberOfEntries = countEntries(_list); + assertEquals(1, numberOfEntries); + } + + public void testAddAndDiscardMessageWithoutConflationKeyValue() + { + ServerMessage<MessageMetaData> message = createTestServerMessage(null); + + QueueEntry addedEntry = _list.add(message); + addedEntry.discard(); + + int numberOfEntries = countEntries(_list); + assertEquals(0, numberOfEntries); + } + + public void testAddMessageWithConflationKeyValue() + { + ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE); + + _list.add(message); + int numberOfEntries = countEntries(_list); + assertEquals(1, numberOfEntries); + } + + public void testAddAndRemoveMessageWithConflationKeyValue() + { + ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE); + + QueueEntry addedEntry = _list.add(message); + addedEntry.discard(); + + int numberOfEntries = countEntries(_list); + assertEquals(0, numberOfEntries); + } + + public void testAddTwoMessagesWithDifferentConflationKeyValue() + { + ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE1); + ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE2); + + _list.add(message1); + _list.add(message2); + + int numberOfEntries = countEntries(_list); + assertEquals(2, numberOfEntries); + } + + public void testAddTwoMessagesWithSameConflationKeyValue() + { + ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE); + + _list.add(message1); + _list.add(message2); + + int numberOfEntries = countEntries(_list); + assertEquals(1, numberOfEntries); + } + + public void testSupersededEntryIsDiscardedOnRelease() + { + ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE); + ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE); + + QueueEntry entry1 = _list.add(message1); + entry1.acquire(); // simulate an in-progress delivery to consumer + + _list.add(message2); + assertFalse(entry1.isDeleted()); + + assertEquals(2, countEntries(_list)); + + entry1.release(); // simulate consumer rollback/recover + + assertEquals(1, countEntries(_list)); + assertTrue(entry1.isDeleted()); + } + + public void testConflationMapMaintained() + { + assertEquals(0, _list.getLatestValuesMap().size()); + + ServerMessage<MessageMetaData> message = createTestServerMessage(TEST_KEY_VALUE); + + QueueEntry addedEntry = _list.add(message); + + assertEquals(1, countEntries(_list)); + assertEquals(1, _list.getLatestValuesMap().size()); + + addedEntry.discard(); + + assertEquals(0, countEntries(_list)); + assertEquals(0, _list.getLatestValuesMap().size()); + } + + public void testConflationMapMaintainedWithDifferentConflationKeyValue() + { + + assertEquals(0, _list.getLatestValuesMap().size()); + + ServerMessage<MessageMetaData> message1 = createTestServerMessage(TEST_KEY_VALUE1); + ServerMessage<MessageMetaData> message2 = createTestServerMessage(TEST_KEY_VALUE2); + + QueueEntry addedEntry1 = _list.add(message1); + QueueEntry addedEntry2 = _list.add(message2); + + assertEquals(2, countEntries(_list)); + assertEquals(2, _list.getLatestValuesMap().size()); + + addedEntry1.discard(); + addedEntry2.discard(); + + assertEquals(0, countEntries(_list)); + assertEquals(0, _list.getLatestValuesMap().size()); + } + + private int countEntries(ConflationQueueList list) + { + QueueEntryIterator<SimpleQueueEntryImpl> iterator = list.iterator(); + int count = 0; + while(iterator.advance()) + { + count++; + } + return count; + } + + private ServerMessage<MessageMetaData> createTestServerMessage(String conflationKeyValue) + { + AMQMessage mockMessage = mock(AMQMessage.class); + + AMQMessageHeader messageHeader = mock(AMQMessageHeader.class); + when(messageHeader.getHeader(CONFLATION_KEY)).thenReturn(conflationKeyValue); + when(mockMessage.getMessageHeader()).thenReturn(messageHeader); + + AMQMessageReference messageReference = new AMQMessageReference(mockMessage); + when(mockMessage.newReference()).thenReturn(messageReference); + + return mockMessage; + } + + private AMQQueue createTestQueue() + { + AMQQueue queue = mock(AMQQueue.class); + VirtualHost virtualHost = mock(VirtualHost.class); + when(queue.getVirtualHost()).thenReturn(virtualHost); + + return queue; + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index afaa417415..bcb8d54636 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -29,13 +29,14 @@ import org.apache.qpid.server.configuration.QueueConfigType; import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.LogSubject; -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.security.AuthorizationHolder; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.virtualhost.VirtualHost; +import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -51,7 +52,6 @@ public class MockAMQQueue implements AMQQueue private AuthorizationHolder _authorizationHolder; private AMQSessionModel _exclusiveOwner; - private AMQShortString _owner; private List<Binding> _bindings = new CopyOnWriteArrayList<Binding>(); private boolean _autoDelete; @@ -98,7 +98,12 @@ public class MockAMQQueue implements AMQQueue return "[MockAMQQueue]"; } - }; + }; + } + + public long getUnackedMessageBytes() + { + return 0; } public ConfigStore getConfigStore() @@ -121,6 +126,16 @@ public class MockAMQQueue implements AMQQueue return 0; } + public long getTotalDequeueCount() + { + return 0; + } + + public long getTotalEnqueueCount() + { + return 0; + } + public int getBindingCountHigh() { return 0; @@ -171,6 +186,12 @@ public class MockAMQQueue implements AMQQueue return null; } + @Override + public UUID getQMFId() + { + return null; + } + public QueueConfigType getConfigType() { return null; @@ -219,12 +240,27 @@ public class MockAMQQueue implements AMQQueue public void registerSubscription(Subscription subscription, boolean exclusive) throws AMQException { - + } public void unregisterSubscription(Subscription subscription) throws AMQException { - + + } + + public Collection<Subscription> getConsumers() + { + return Collections.emptyList(); + } + + public void addSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener) + { + + } + + public void removeSubscriptionRegistrationListener(final SubscriptionRegistrationListener listener) + { + } public int getConsumerCount() @@ -283,7 +319,7 @@ public class MockAMQQueue implements AMQQueue } public int delete() throws AMQException - { + { _deleted = true; return getMessageCount(); } @@ -356,21 +392,6 @@ public class MockAMQQueue implements AMQQueue return null; } - public void moveMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName) - { - - } - - public void copyMessagesToAnotherQueue(long fromMessageId, long toMessageId, String queueName) - { - - } - - public void removeMessagesFromQueue(long fromMessageId, long toMessageId) - { - - } - public long getMaximumMessageSize() { return 0; @@ -378,7 +399,7 @@ public class MockAMQQueue implements AMQQueue public void setMaximumMessageSize(long value) { - + } public long getMaximumMessageCount() @@ -388,7 +409,7 @@ public class MockAMQQueue implements AMQQueue public void setMaximumMessageCount(long value) { - + } public long getMaximumQueueDepth() @@ -398,7 +419,7 @@ public class MockAMQQueue implements AMQQueue public void setMaximumQueueDepth(long value) { - + } public long getMaximumMessageAge() @@ -408,7 +429,7 @@ public class MockAMQQueue implements AMQQueue public void setMaximumMessageAge(long maximumMessageAge) { - + } public long getMinimumAlertRepeatGap() @@ -418,7 +439,7 @@ public class MockAMQQueue implements AMQQueue public void deleteMessageFromTop() { - + } public long clearQueue() @@ -429,7 +450,7 @@ public class MockAMQQueue implements AMQQueue public void checkMessageStatus() throws AMQException { - + } public Set<NotificationCheck> getNotificationChecks() @@ -439,22 +460,22 @@ public class MockAMQQueue implements AMQQueue public void flushSubscription(Subscription sub) throws AMQException { - + } public void deliverAsync(Subscription sub) { - + } public void deliverAsync() { - + } public void stop() { - + } public boolean isExclusive() @@ -469,7 +490,7 @@ public class MockAMQQueue implements AMQQueue public void setAlternateExchange(Exchange exchange) { - + } public Map<String, Object> getArguments() @@ -481,11 +502,6 @@ public class MockAMQQueue implements AMQQueue { } - public ManagedObject getManagedObject() - { - return null; - } - public int compareTo(AMQQueue o) { return 0; @@ -503,7 +519,7 @@ public class MockAMQQueue implements AMQQueue public void setCapacity(long capacity) { - + } public long getFlowResumeCapacity() @@ -513,7 +529,7 @@ public class MockAMQQueue implements AMQQueue public void setFlowResumeCapacity(long flowResumeCapacity) { - + } public void configure(ConfigurationPlugin config) @@ -546,12 +562,6 @@ public class MockAMQQueue implements AMQQueue _exclusiveOwner = exclusiveOwner; } - - public String getResourceName() - { - return _name.toString(); - } - public boolean isOverfull() { return false; @@ -582,7 +592,7 @@ public class MockAMQQueue implements AMQQueue return 0; } - public void decrementUnackedMsgCount() + public void decrementUnackedMsgCount(QueueEntry queueEntry) { } @@ -599,7 +609,6 @@ public class MockAMQQueue implements AMQQueue public void setExclusive(boolean exclusive) { - } public int getMaximumDeliveryCount() @@ -611,11 +620,23 @@ public class MockAMQQueue implements AMQQueue { } - public void setAlternateExchange(String exchangeName) + public void visit(final QueueEntryVisitor visitor) + { + } + + @Override + public void setNotificationListener(NotificationListener listener) { } - public void visit(final Visitor visitor) + @Override + public void setDescription(String description) { } + + @Override + public String getDescription() + { + return null; + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java new file mode 100644 index 0000000000..df2de7f0e0 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/NotificationCheckTest.java @@ -0,0 +1,106 @@ +/* + * + * 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 static org.mockito.Matchers.contains; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_AGE_ALERT; +import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_COUNT_ALERT; +import static org.apache.qpid.server.queue.NotificationCheck.MESSAGE_SIZE_ALERT; +import static org.apache.qpid.server.queue.NotificationCheck.QUEUE_DEPTH_ALERT; + + +import junit.framework.TestCase; + +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.queue.AMQQueue.NotificationListener; + +public class NotificationCheckTest extends TestCase +{ + + private ServerMessage<?> _message = mock(ServerMessage.class); + private AMQQueue _queue = mock(AMQQueue.class); + private NotificationListener _listener = mock(NotificationListener.class); + + public void testMessageCountAlertFires() throws Exception + { + when(_queue.getMaximumMessageCount()).thenReturn(1000l); + when(_queue.getMessageCount()).thenReturn(999, 1000, 1001); + + MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener); + verifyZeroInteractions(_listener); + + MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener); + verify(_listener).notifyClients(eq(MESSAGE_COUNT_ALERT), eq(_queue), eq("1000: Maximum count on queue threshold (1000) breached.")); + + MESSAGE_COUNT_ALERT.notifyIfNecessary(_message, _queue, _listener); + verify(_listener).notifyClients(eq(MESSAGE_COUNT_ALERT), eq(_queue), eq("1001: Maximum count on queue threshold (1000) breached.")); + } + + public void testMessageSizeAlertFires() throws Exception + { + when(_queue.getMaximumMessageSize()).thenReturn(1024l); + when(_message.getSize()).thenReturn(1023l, 1024l, 1025l); + + MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener); + verifyZeroInteractions(_listener); + + MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener); + verify(_listener).notifyClients(eq(MESSAGE_SIZE_ALERT), eq(_queue), contains("1024b : Maximum message size threshold (1024) breached.")); + + MESSAGE_SIZE_ALERT.notifyIfNecessary(_message, _queue, _listener); + verify(_listener).notifyClients(eq(MESSAGE_SIZE_ALERT), eq(_queue), contains("1025b : Maximum message size threshold (1024) breached.")); + } + + public void testMessageAgeAlertFires() throws Exception + { + long now = System.currentTimeMillis(); + when(_queue.getMaximumMessageAge()).thenReturn(1000l); + when(_queue.getOldestMessageArrivalTime()).thenReturn(now, now - 15000); + + MESSAGE_AGE_ALERT.notifyIfNecessary(_message, _queue, _listener); + verifyZeroInteractions(_listener); + + MESSAGE_AGE_ALERT.notifyIfNecessary(_message, _queue, _listener); + // Uses contains as first part of message is nondeterministic + verify(_listener).notifyClients(eq(MESSAGE_AGE_ALERT), eq(_queue), contains("s : Maximum age on queue threshold (1s) breached.")); + } + + public void testQueueDepthAlertFires() throws Exception + { + when(_queue.getMaximumQueueDepth()).thenReturn(1024l); + when(_queue.getQueueDepth()).thenReturn(1023l, 1024l, 2048l); + + QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener); + verifyZeroInteractions(_listener); + + QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener); + verify(_listener).notifyClients(eq(QUEUE_DEPTH_ALERT), eq(_queue), eq("1Kb : Maximum queue depth threshold (1Kb) breached.")); + + QUEUE_DEPTH_ALERT.notifyIfNecessary(_message, _queue, _listener); + verify(_listener).notifyClients(eq(QUEUE_DEPTH_ALERT), eq(_queue), eq("2Kb : Maximum queue depth threshold (1Kb) breached.")); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java index 52ad4a7c5b..2cd423d4c9 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java @@ -21,6 +21,13 @@ package org.apache.qpid.server.queue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Matchers.contains; +import static org.mockito.Matchers.eq; + import org.apache.commons.configuration.PropertiesConfiguration; import org.apache.qpid.AMQException; @@ -43,7 +50,6 @@ import org.apache.qpid.server.queue.SimpleAMQQueue.QueueEntryFilter; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.store.StoredMessage; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory; import org.apache.qpid.server.subscription.MockSubscription; import org.apache.qpid.server.subscription.Subscription; import org.apache.qpid.server.txn.AutoCommitTransaction; @@ -80,7 +86,6 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase public void setExchange(AMQShortString exchange) { - //To change body of implemented methods use File | Settings | File Templates. } public boolean isImmediate() @@ -108,11 +113,11 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase PropertiesConfiguration env = new PropertiesConfiguration(); final VirtualHostConfiguration vhostConfig = new VirtualHostConfiguration(getClass().getName(), env); - vhostConfig.setMessageStoreFactoryClass(TestableMemoryMessageStoreFactory.class.getName()); + vhostConfig.setMessageStoreClass(TestableMemoryMessageStore.class.getName()); _virtualHost = new VirtualHostImpl(ApplicationRegistry.getInstance(), vhostConfig); applicationRegistry.getVirtualHostRegistry().registerVirtualHost(_virtualHost); - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, false, _virtualHost, _arguments); + _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), false, false, _virtualHost, FieldTable.convertToMap(_arguments)); _exchange = (DirectExchange)_virtualHost.getExchangeRegistry().getExchange(ExchangeDefaults.DIRECT_EXCHANGE_NAME); } @@ -128,7 +133,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase { _queue.stop(); try { - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(null, false, _owner, false, false, _virtualHost, _arguments ); + _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), null, false, _owner.asString(), false, false, _virtualHost, FieldTable.convertToMap(_arguments)); assertNull("Queue was created", _queue); } catch (IllegalArgumentException e) @@ -138,7 +143,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase } try { - _queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP); + _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, _owner, false,false, null, Collections.EMPTY_MAP); assertNull("Queue was created", _queue); } catch (IllegalArgumentException e) @@ -147,8 +152,8 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase e.getMessage().contains("Host")); } - _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(_qname, false, _owner, false, - false, _virtualHost, _arguments); + _queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), _qname.asString(), false, _owner.asString(), false, + false, _virtualHost, FieldTable.convertToMap(_arguments)); assertNotNull("Queue was not created", _queue); } @@ -480,7 +485,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase public void testAutoDeleteQueue() throws Exception { _queue.stop(); - _queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP); + _queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), _qname, false, null, true, false, _virtualHost, Collections.EMPTY_MAP); _queue.setDeleteOnNoConsumers(true); _queue.registerSubscription(_subscription, false); AMQMessage message = createMessage(new Long(25)); @@ -692,7 +697,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase public void testProcessQueueWithUniqueSelectors() throws Exception { TestSimpleQueueEntryListFactory factory = new TestSimpleQueueEntryListFactory(); - SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), "testQueue", false,"testOwner", + SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), "testQueue", false,"testOwner", false, false, _virtualHost, factory, null) { @Override @@ -840,120 +845,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase } } - /** - * Tests that dequeued message is not copied as part of invocation of - * {@link SimpleAMQQueue#copyMessagesToAnotherQueue(long, long, String)} - */ - public void testCopyMessagesWithDequeuedEntry() - { - int messageNumber = 4; - int dequeueMessageIndex = 1; - String anotherQueueName = "testQueue2"; - - // put test messages into a test queue - enqueueGivenNumberOfMessages(_queue, messageNumber); - - // dequeue message - dequeueMessage(_queue, dequeueMessageIndex); - - // create another queue - SimpleAMQQueue queue = createQueue(anotherQueueName); - - // copy messages into another queue - _queue.copyMessagesToAnotherQueue(0, messageNumber, anotherQueueName); - // get messages on another queue - List<QueueEntry> entries = queue.getMessagesOnTheQueue(); - - // assert another queue entries - assertEquals(messageNumber - 1, entries.size()); - int expectedId = 0; - for (int i = 0; i < messageNumber - 1; i++) - { - Long id = ((AMQMessage)entries.get(i).getMessage()).getMessageId(); - if (i == dequeueMessageIndex) - { - assertFalse("Message with id " + dequeueMessageIndex - + " was dequeued and should not been copied into another queue!", - new Long(expectedId).equals(id)); - expectedId++; - } - assertEquals("Expected message with id " + expectedId + " but got message with id " + id, - new Long(expectedId), id); - expectedId++; - } - } - - /** - * Tests that dequeued message is not moved as part of invocation of - * {@link SimpleAMQQueue#moveMessagesToAnotherQueue(long, long, String)} - */ - public void testMovedMessagesWithDequeuedEntry() - { - int messageNumber = 4; - int dequeueMessageIndex = 1; - String anotherQueueName = "testQueue2"; - - // put messages into a test queue - enqueueGivenNumberOfMessages(_queue, messageNumber); - - // dequeue message - dequeueMessage(_queue, dequeueMessageIndex); - - // create another queue - SimpleAMQQueue queue = createQueue(anotherQueueName); - - // move messages into another queue - _queue.moveMessagesToAnotherQueue(0, messageNumber, anotherQueueName); - - // get messages on another queue - List<QueueEntry> entries = queue.getMessagesOnTheQueue(); - - // assert another queue entries - assertEquals(messageNumber - 1, entries.size()); - int expectedId = 0; - for (int i = 0; i < messageNumber - 1; i++) - { - Long id = ((AMQMessage)entries.get(i).getMessage()).getMessageId(); - if (i == dequeueMessageIndex) - { - assertFalse("Message with id " + dequeueMessageIndex - + " was dequeued and should not been copied into another queue!", - new Long(expectedId).equals(id)); - expectedId++; - } - assertEquals("Expected message with id " + expectedId + " but got message with id " + id, - new Long(expectedId), id); - expectedId++; - } - } - - /** - * Tests that messages in given range including dequeued one are deleted - * from the queue on invocation of - * {@link SimpleAMQQueue#removeMessagesFromQueue(long, long)} - */ - public void testRemoveMessagesFromQueueWithDequeuedEntry() - { - int messageNumber = 4; - int dequeueMessageIndex = 1; - - // put messages into a test queue - enqueueGivenNumberOfMessages(_queue, messageNumber); - - // dequeue message - dequeueMessage(_queue, dequeueMessageIndex); - - // remove messages - _queue.removeMessagesFromQueue(0, messageNumber); - - // get queue entries - List<QueueEntry> entries = _queue.getMessagesOnTheQueue(); - - // assert queue entries - assertNotNull("Null is returned from getMessagesOnTheQueue", entries); - assertEquals("Queue should be empty", 0, entries.size()); - } /** * Tests that dequeued message on the top is not accounted and next message @@ -1029,7 +921,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase int dequeueMessageIndex = 1; // create queue with overridden method deliverAsync - SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("test"), + SimpleAMQQueue testQueue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("test"), false, new AMQShortString("testOwner"), false, false, _virtualHost, null) { @Override @@ -1097,10 +989,10 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase /** * Tests that entry in dequeued state are not enqueued and not delivered to subscription */ - public void testEqueueDequeuedEntry() + public void testEnqueueDequeuedEntry() { // create a queue where each even entry is considered a dequeued - SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("test"), false, + SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("test"), false, new AMQShortString("testOwner"), false, false, _virtualHost, new QueueEntryListFactory() { public QueueEntryList createQueueEntryList(AMQQueue queue) @@ -1178,7 +1070,7 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase public void testActiveConsumerCount() throws Exception { - final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateUUID(), new AMQShortString("testActiveConsumerCount"), false, + final SimpleAMQQueue queue = new SimpleAMQQueue(UUIDGenerator.generateRandomUUID(), new AMQShortString("testActiveConsumerCount"), false, new AMQShortString("testOwner"), false, false, _virtualHost, new SimpleQueueEntryList.Factory(), null); //verify adding an active subscription increases the count @@ -1232,29 +1124,37 @@ public class SimpleAMQQueueTest extends InternalBrokerBaseCase assertEquals("Unexpected active consumer count", 1, queue.getActiveConsumerCount()); } - /** - * A helper method to create a queue with given name - * - * @param name - * queue name - * @return queue - */ - private SimpleAMQQueue createQueue(String name) + public void testNotificationFiredOnEnqueue() throws Exception { - SimpleAMQQueue queue = null; - try - { - AMQShortString queueName = new AMQShortString(name); - AMQShortString ownerName = new AMQShortString(name + "Owner"); - queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(queueName, false, ownerName, false, false, - _virtualHost, _arguments); - } - catch (AMQException e) - { - fail("Failure to create a queue:" + e.getMessage()); - } - assertNotNull("Queue was not created", queue); - return queue; + AMQQueue.NotificationListener listener = mock(AMQQueue.NotificationListener.class); + + _queue.setNotificationListener(listener); + _queue.setMaximumMessageCount(2); + + _queue.enqueue(createMessage(new Long(24))); + verifyZeroInteractions(listener); + + _queue.enqueue(createMessage(new Long(25))); + + verify(listener, atLeastOnce()).notifyClients(eq(NotificationCheck.MESSAGE_COUNT_ALERT), eq(_queue), contains("Maximum count on queue threshold")); + } + + public void testNotificationFiredAsync() throws Exception + { + AMQQueue.NotificationListener listener = mock(AMQQueue.NotificationListener.class); + + _queue.enqueue(createMessage(new Long(24))); + _queue.enqueue(createMessage(new Long(25))); + _queue.enqueue(createMessage(new Long(26))); + + _queue.setNotificationListener(listener); + _queue.setMaximumMessageCount(2); + + verifyZeroInteractions(listener); + + _queue.checkMessageStatus(); + + verify(listener, atLeastOnce()).notifyClients(eq(NotificationCheck.MESSAGE_COUNT_ALERT), eq(_queue), contains("Maximum count on queue threshold")); } /** diff --git a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java index 39ddd1d500..6b82cd361a 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueThreadPoolTest.java @@ -21,8 +21,8 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.pool.ReferenceCountingExecutorService; +import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.util.InternalBrokerBaseCase; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -37,9 +37,8 @@ public class SimpleAMQQueueThreadPoolTest extends InternalBrokerBaseCase try { - SimpleAMQQueue queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(new AMQShortString("test"), false, - new AMQShortString("owner"), - false, false, test, null); + SimpleAMQQueue queue = (SimpleAMQQueue) AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), "test", false, + "owner", false, false, test, null); assertFalse("Creation did not start Pool.", ReferenceCountingExecutorService.getInstance().getPool().isShutdown()); diff --git a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java index 9ff8f0a531..9af950d385 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/registry/ApplicationRegistryShutdownTest.java @@ -49,7 +49,7 @@ public class ApplicationRegistryShutdownTest extends InternalBrokerBaseCase /** - * QPID-1399 : Ensure that the Authentiction manager unregisters any SASL providers created during + * QPID-1399 : Ensure that the Authentication manager unregisters any SASL providers created during * ApplicationRegistry initialisation. * */ diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java new file mode 100644 index 0000000000..9dcd22c088 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AnonymousAuthenticationManagerTest.java @@ -0,0 +1,109 @@ +/* + * 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.manager; + +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.commons.configuration.CompositeConfiguration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; +import org.apache.qpid.server.util.InternalBrokerBaseCase; + +public class AnonymousAuthenticationManagerTest extends InternalBrokerBaseCase +{ + + private AuthenticationManager _manager = null; + + public void setUp() throws Exception + { + _manager = AnonymousAuthenticationManager.INSTANCE; + } + + + public void tearDown() throws Exception + { + if(_manager != null) + { + _manager = null; + } + } + + private ConfigurationPlugin getPlainDatabaseConfig() throws ConfigurationException + { + final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration(); + + XMLConfiguration xmlconfig = new XMLConfiguration(); + xmlconfig.addProperty("pd-auth-manager.principal-database.class", PlainPasswordFilePrincipalDatabase.class.getName()); + + // Create a CompositeConfiguration as this is what the broker uses + CompositeConfiguration composite = new CompositeConfiguration(); + composite.addConfiguration(xmlconfig); + config.setConfiguration("security", xmlconfig); + return config; + } + + + public void testConfiguration() throws Exception + { + AuthenticationManager authenticationManager = + AnonymousAuthenticationManager.FACTORY.newInstance(getPlainDatabaseConfig()); + + assertNull("AnonymousAuthenticationManager unexpectedly created when not in config", authenticationManager); + } + + public void testGetMechanisms() throws Exception + { + assertEquals("ANONYMOUS", _manager.getMechanisms()); + } + + public void testCreateSaslServer() throws Exception + { + SaslServer server = _manager.createSaslServer("ANONYMOUS", "example.example.com", null); + + assertEquals("Sasl Server mechanism name is not as expected", "ANONYMOUS", server.getMechanismName()); + + try + { + server = _manager.createSaslServer("PLAIN", "example.example.com", null); + fail("Expected creating SaslServer with incorrect mechanism to throw an exception"); + } + catch (SaslException e) + { + // pass + } + } + + public void testAuthenticate() throws Exception + { + SaslServer saslServer = _manager.createSaslServer("ANONYMOUS", "example.example.com", null); + AuthenticationResult result = _manager.authenticate(saslServer, new byte[0]); + assertNotNull(result); + assertEquals("Expected authentication to be successful", + AuthenticationResult.AuthenticationStatus.SUCCESS, + result.getStatus()); + assertNotNull("Subject should not be null", result.getSubject()); + } + + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java new file mode 100644 index 0000000000..efb8df3a38 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerRegistryTest.java @@ -0,0 +1,304 @@ +/* + * 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.manager; + +import static org.mockito.Mockito.*; + +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.util.ArrayList; +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; +import org.apache.qpid.server.configuration.ServerConfiguration; +import org.apache.qpid.server.plugins.Plugin; +import org.apache.qpid.server.plugins.PluginManager; +import org.apache.qpid.server.security.SecurityManager.SecurityConfiguration; +import org.mockito.Mockito; + +import junit.framework.TestCase; + +public class AuthenticationManagerRegistryTest extends TestCase +{ + private static final Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> EMPTY_PLUGINMAP = Collections.emptyMap(); + + private PluginManager _pluginManager = Mockito.mock(PluginManager.class); + private ServerConfiguration _serverConfiguration = Mockito.mock(ServerConfiguration.class); + private SecurityConfiguration _securityConfiguration = Mockito.mock(SecurityConfiguration.class); + + private List<AuthenticationManager> _allCreatedAuthManagers = new ArrayList<AuthenticationManager>(); + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + // Setup server configuration to return mock security config. + when(_serverConfiguration.getConfiguration(SecurityConfiguration.class.getName())).thenReturn(_securityConfiguration); + } + + @Override + protected void tearDown() throws Exception + { + try + { + verifyAllCreatedAuthManagersClosed(); + } + finally + { + super.tearDown(); + } + } + + public void testNoAuthenticationManagerFactoryPluginsFound() throws Exception + { + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(EMPTY_PLUGINMAP); + try + { + new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + fail("Exception not thrown"); + } + catch (ConfigurationException ce) + { + // PASS + assertEquals("No authentication manager factory plugins found. Check the desired authentication manager plugin has been placed in the plugins directory.", + ce.getMessage()); + } + } + + public void testSameAuthenticationManagerSpecifiedTwice() throws Exception + { + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory, myAuthManagerFactory); + + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + + try + { + new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + fail("Exception not thrown"); + } + catch (ConfigurationException ce) + { + // PASS + assertEquals("Cannot configure more than one authentication manager of type " + myAuthManagerFactory.getPluginClass().getSimpleName() + ". Remove configuration for one of the authentication managers.", + ce.getMessage()); + } + } + + public void testMultipleAuthenticationManagersSpecifiedButNoDefaultSpecified() throws Exception + { + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); + + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); + + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(null); + + try + { + new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + fail("Exception not thrown"); + } + catch (ConfigurationException ce) + { + // PASS + assertEquals("If more than one authentication manager is configured a default MUST be specified.", + ce.getMessage()); + } + } + + public void testDefaultAuthenticationManagerNotKnown() throws Exception + { + String myDefaultAuthManagerSimpleClassName = "UnknownAuthenticationManager"; + + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); + + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); + + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(myDefaultAuthManagerSimpleClassName); + + try + { + new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + fail("Exception not thrown"); + } + catch (ConfigurationException ce) + { + // PASS + assertTrue("Unexpected message " + ce.getMessage(), + ce.getMessage().startsWith("No authentication managers configured of type " + myDefaultAuthManagerSimpleClassName + " which is specified as the default")); + } + } + + public void testPortMappedToUnknownAuthenticationManager() throws Exception + { + String myDefaultAuthManagerSimpleClassName = "UnknownAuthenticationManager"; + int portNumber = 1234; + + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1); + + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + when(_serverConfiguration.getPortAuthenticationMappings()).thenReturn(Collections.singletonMap(portNumber, myDefaultAuthManagerSimpleClassName)); + + try + { + new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + fail("Exception not thrown"); + } + catch (ConfigurationException ce) + { + // PASS + assertEquals("Unknown authentication manager class " + myDefaultAuthManagerSimpleClassName + " configured for port " + portNumber, ce.getMessage()); + } + } + + public void testGetAuthenticationManagerForInetSocketAddress() throws Exception + { + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1); + + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + + AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + + AuthenticationManager authenticationManager = registry.getAuthenticationManager(new InetSocketAddress(1234)); + assertEquals("TestAuthenticationManager1", authenticationManager.getMechanisms()); + + registry.close(); + } + + public void testGetAuthenticationManagerForNonInetSocketAddress() throws Exception + { + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1); + + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + + AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + + AuthenticationManager authenticationManager = registry.getAuthenticationManager(mock(SocketAddress.class)); + assertEquals("TestAuthenticationManager1", authenticationManager.getMechanisms()); + + registry.close(); + } + + public void testGetAuthenticationManagerWithMultipleAuthenticationManager() throws Exception + { + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); + + String defaultAuthManger = myAuthManagerFactory1.getPluginName(); + int unmappedPortNumber = 1234; + int mappedPortNumber = 1235; + String mappedAuthManager = myAuthManagerFactory2.getPluginName(); + + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(defaultAuthManger); + when(_serverConfiguration.getPortAuthenticationMappings()).thenReturn(Collections.singletonMap(mappedPortNumber, mappedAuthManager)); + + AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + + AuthenticationManager authenticationManager1 = registry.getAuthenticationManager(new InetSocketAddress(unmappedPortNumber)); + assertEquals("TestAuthenticationManager1", authenticationManager1.getMechanisms()); + + AuthenticationManager authenticationManager2 = registry.getAuthenticationManager(new InetSocketAddress(mappedPortNumber)); + assertEquals("TestAuthenticationManager2", authenticationManager2.getMechanisms()); + + registry.close(); + } + + public void testAuthenticationManagersAreClosed() throws Exception + { + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory1 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager1.class); + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory2 = newMockFactoryProducingMockAuthManagerImplementing(TestAuthenticationManager2.class); + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = createPluginMap(myAuthManagerFactory1, myAuthManagerFactory2); + + String defaultAuthManger = myAuthManagerFactory1.getPluginName(); + when(_pluginManager.getAuthenticationManagerPlugins()).thenReturn(pluginMap); + when(_serverConfiguration.getDefaultAuthenticationManager()).thenReturn(defaultAuthManger); + + AuthenticationManagerRegistry registry = new AuthenticationManagerRegistry(_serverConfiguration, _pluginManager); + + registry.close(); + } + + private AuthenticationManagerPluginFactory<? extends Plugin> newMockFactoryProducingMockAuthManagerImplementing(Class<? extends AuthenticationManager> authManagerClazz) + throws ConfigurationException + { + AuthenticationManager myAuthManager = mock(authManagerClazz); + when(myAuthManager.getMechanisms()).thenReturn(authManagerClazz.getSimpleName()); // used to verify the getAuthenticationManagerFor returns expected impl. + + AuthenticationManagerPluginFactory myAuthManagerFactory = mock(AuthenticationManagerPluginFactory.class); + when(myAuthManagerFactory.getPluginClass()).thenReturn(myAuthManager.getClass()); + when(myAuthManagerFactory.getPluginName()).thenReturn(myAuthManager.getClass().getSimpleName()); + when(myAuthManagerFactory.newInstance(_securityConfiguration)).thenReturn(myAuthManager); + + _allCreatedAuthManagers.add(myAuthManager); + return myAuthManagerFactory; + } + + private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> createPluginMap( + AuthenticationManagerPluginFactory<? extends Plugin> myAuthManagerFactory) + { + return createPluginMap(myAuthManagerFactory, null); + } + + private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> createPluginMap( + AuthenticationManagerPluginFactory<? extends Plugin> authManagerFactory1, + AuthenticationManagerPluginFactory<? extends Plugin> authManagerFactory2) + { + Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> pluginMap = new HashMap<String, AuthenticationManagerPluginFactory<? extends Plugin>>(); + pluginMap.put("config.path.unused1", authManagerFactory1); + if (authManagerFactory2 != null) + { + pluginMap.put("config.path.unused2", authManagerFactory2); + } + return pluginMap; + } + + private void verifyAllCreatedAuthManagersClosed() + { + for (Iterator<AuthenticationManager> iterator = _allCreatedAuthManagers.iterator(); iterator.hasNext();) + { + AuthenticationManager authenticationManager = (AuthenticationManager) iterator.next(); + verify(authenticationManager).close(); + } + } + + private interface TestAuthenticationManager1 extends AuthenticationManager + { + } + + private interface TestAuthenticationManager2 extends AuthenticationManager + { + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java new file mode 100644 index 0000000000..c1a55ef2ad --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/ExternalAuthenticationManagerTest.java @@ -0,0 +1,120 @@ +/* + * 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.manager; + +import javax.security.auth.x500.X500Principal; +import javax.security.sasl.SaslException; +import javax.security.sasl.SaslServer; +import org.apache.commons.configuration.CompositeConfiguration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.configuration.XMLConfiguration; +import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; +import org.apache.qpid.server.security.auth.AuthenticationResult; +import org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase; +import org.apache.qpid.server.util.InternalBrokerBaseCase; + +public class ExternalAuthenticationManagerTest extends InternalBrokerBaseCase +{ + + private AuthenticationManager _manager = null; + + public void setUp() throws Exception + { + _manager = ExternalAuthenticationManager.INSTANCE; + } + + + public void tearDown() throws Exception + { + if(_manager != null) + { + _manager = null; + } + } + + private ConfigurationPlugin getPlainDatabaseConfig() throws ConfigurationException + { + final ConfigurationPlugin config = new PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration(); + + XMLConfiguration xmlconfig = new XMLConfiguration(); + xmlconfig.addProperty("pd-auth-manager.principal-database.class", PlainPasswordFilePrincipalDatabase.class.getName()); + + // Create a CompositeConfiguration as this is what the broker uses + CompositeConfiguration composite = new CompositeConfiguration(); + composite.addConfiguration(xmlconfig); + config.setConfiguration("security", xmlconfig); + return config; + } + + + public void testConfiguration() throws Exception + { + AuthenticationManager authenticationManager = + ExternalAuthenticationManager.FACTORY.newInstance(getPlainDatabaseConfig()); + + assertNull("ExternalAuthenticationManager unexpectedly created when not in config", authenticationManager); + } + + public void testGetMechanisms() throws Exception + { + assertEquals("EXTERNAL", _manager.getMechanisms()); + } + + public void testCreateSaslServer() throws Exception + { + SaslServer server = _manager.createSaslServer("EXTERNAL", "example.example.com", null); + + assertEquals("Sasl Server mechanism name is not as expected", "EXTERNAL", server.getMechanismName()); + + try + { + server = _manager.createSaslServer("PLAIN", "example.example.com", null); + fail("Expected creating SaslServer with incorrect mechanism to throw an exception"); + } + catch (SaslException e) + { + // pass + } + } + + public void testAuthenticate() throws Exception + { + X500Principal principal = new X500Principal("CN=person, DC=example, DC=com"); + SaslServer saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", principal); + + AuthenticationResult result = _manager.authenticate(saslServer, new byte[0]); + assertNotNull(result); + assertEquals("Expected authentication to be successful", + AuthenticationResult.AuthenticationStatus.SUCCESS, + result.getStatus()); + assertEquals("Expected principal to be unchanged", + principal, + result.getSubject().getPrincipals().iterator().next()); + + saslServer = _manager.createSaslServer("EXTERNAL", "example.example.com", null); + result = _manager.authenticate(saslServer, new byte[0]); + assertNotNull(result); + assertEquals("Expected authentication to be unsuccessful", + AuthenticationResult.AuthenticationStatus.ERROR, + result.getStatus()); + + } + + +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java index 1a42fe3886..47c189e4fa 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManagerTest.java @@ -167,7 +167,7 @@ public class PrincipalDatabaseAuthenticationManagerTest extends InternalBrokerBa */ public void testSaslMechanismCreation() throws Exception { - SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost"); + SaslServer server = _manager.createSaslServer("CRAM-MD5", "localhost", null); assertNotNull(server); // Merely tests the creation of the mechanism. Mechanisms themselves are tested // by their own tests. diff --git a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java index bef03057ec..c0c55de92a 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticatorTest.java @@ -20,23 +20,19 @@ */ package org.apache.qpid.server.security.auth.rmi; +import java.security.Principal; import junit.framework.TestCase; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -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; -import org.apache.qpid.server.util.TestApplicationRegistry; import javax.management.remote.JMXPrincipal; import javax.security.auth.Subject; -import javax.security.auth.callback.CallbackHandler; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; +import java.net.InetSocketAddress; import java.util.Collections; /** @@ -52,7 +48,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase protected void setUp() throws Exception { - _rmipa = new RMIPasswordAuthenticator(); + _rmipa = new RMIPasswordAuthenticator(new InetSocketAddress(5672)); _credentials = new String[] {USERNAME, PASSWORD}; } @@ -76,14 +72,14 @@ public class RMIPasswordAuthenticatorTest extends TestCase newSubject.equals(expectedSubject)); } - + /** * Tests a unsuccessful authentication. */ public void testUsernameOrPasswordInvalid() { _rmipa.setAuthenticationManager(createTestAuthenticationManager(false, null)); - + try { _rmipa.authenticate(_credentials); @@ -122,17 +118,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase */ public void testNullAuthenticationManager() throws Exception { - ServerConfiguration serverConfig = new ServerConfiguration(new XMLConfiguration()); - TestApplicationRegistry reg = new TestApplicationRegistry(serverConfig) - { - @Override - protected AuthenticationManager createAuthenticationManager() throws ConfigurationException - { - return null; - } - }; - ApplicationRegistry.initialise(reg); - + _rmipa.setAuthenticationManager(null); try { _rmipa.authenticate(_credentials); @@ -143,10 +129,6 @@ public class RMIPasswordAuthenticatorTest extends TestCase assertEquals("Unexpected exception message", RMIPasswordAuthenticator.UNABLE_TO_LOOKUP, se.getMessage()); } - finally - { - ApplicationRegistry.remove(); - } } /** @@ -185,7 +167,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase assertEquals("Unexpected exception message", RMIPasswordAuthenticator.SHOULD_HAVE_2_ELEMENTS, se.getMessage()); } - + // Test handling of null credentials try { @@ -199,7 +181,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase assertEquals("Unexpected exception message", RMIPasswordAuthenticator.CREDENTIALS_REQUIRED, se.getMessage()); } - + try { //send a null password @@ -212,7 +194,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase assertEquals("Unexpected exception message", RMIPasswordAuthenticator.SHOULD_BE_NON_NULL, se.getMessage()); } - + try { //send a null username @@ -251,7 +233,7 @@ public class RMIPasswordAuthenticatorTest extends TestCase throw new UnsupportedOperationException(); } - public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException + public SaslServer createSaslServer(String mechanism, String localFQDN, Principal externalPrincipal) throws SaslException { throw new UnsupportedOperationException(); } @@ -276,10 +258,6 @@ public class RMIPasswordAuthenticatorTest extends TestCase } } - public CallbackHandler getHandler(String mechanism) - { - return null; - } }; } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java index a1cbb2cbc8..cd8d91d835 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/DurableConfigurationStoreTest.java @@ -1,3 +1,23 @@ +/* + * + * 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.store; import static org.mockito.Matchers.any; @@ -27,7 +47,6 @@ import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.TestLogActor; -import org.apache.qpid.server.logging.subjects.TestBlankSubject; import org.apache.qpid.server.message.EnqueableMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.AMQQueue; @@ -41,7 +60,7 @@ import org.apache.qpid.server.store.ConfigurationRecoveryHandler.ExchangeRecover import org.apache.qpid.server.store.ConfigurationRecoveryHandler.QueueRecoveryHandler; import org.apache.qpid.server.store.MessageStoreRecoveryHandler.StoredMessageRecoveryHandler; import org.apache.qpid.server.store.Transaction.Record; -import org.apache.qpid.server.store.derby.DerbyMessageStoreFactory; +import org.apache.qpid.server.store.derby.DerbyMessageStore; import org.apache.qpid.test.utils.QpidTestCase; import org.apache.qpid.util.FileUtils; @@ -75,11 +94,11 @@ public class DurableConfigurationStoreTest extends QpidTestCase { super.setUp(); - _queueId = UUIDGenerator.generateUUID(); - _exchangeId = UUIDGenerator.generateUUID(); + _queueId = UUIDGenerator.generateRandomUUID(); + _exchangeId = UUIDGenerator.generateRandomUUID(); _storeName = getName(); - _storePath = TMP_FOLDER + "/" + _storeName; + _storePath = TMP_FOLDER + File.separator + _storeName; FileUtils.delete(new File(_storePath), true); setTestSystemProperty("QPID_WORK", TMP_FOLDER); _configuration = mock(Configuration.class); @@ -94,9 +113,9 @@ public class DurableConfigurationStoreTest extends QpidTestCase _dtxRecordRecoveryHandler = mock(TransactionLogRecoveryHandler.DtxRecordRecoveryHandler.class); when(_messageStoreRecoveryHandler.begin()).thenReturn(_storedMessageRecoveryHandler); - when(_recoveryHandler.begin(isA(MessageStore.class))).thenReturn(_queueRecoveryHandler); - when(_queueRecoveryHandler.completeQueueRecovery()).thenReturn(_exchangeRecoveryHandler); - when(_exchangeRecoveryHandler.completeExchangeRecovery()).thenReturn(_bindingRecoveryHandler); + when(_recoveryHandler.begin(isA(MessageStore.class))).thenReturn(_exchangeRecoveryHandler); + when(_exchangeRecoveryHandler.completeExchangeRecovery()).thenReturn(_queueRecoveryHandler); + when(_queueRecoveryHandler.completeQueueRecovery()).thenReturn(_bindingRecoveryHandler); when(_bindingRecoveryHandler.completeBindingRecovery()).thenReturn(_linkRecoveryHandler); when(_logRecoveryHandler.begin(any(MessageStore.class))).thenReturn(_queueEntryRecoveryHandler); when(_queueEntryRecoveryHandler.completeQueueEntryRecovery()).thenReturn(_dtxRecordRecoveryHandler); @@ -142,8 +161,8 @@ public class DurableConfigurationStoreTest extends QpidTestCase public void testBindQueue() throws Exception { AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false); - Binding binding = new Binding(UUIDGenerator.generateUUID(), ROUTING_KEY, queue, _exchange, - FieldTable.convertToMap(_bindingArgs)); + Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), null, ROUTING_KEY, queue, + _exchange, FieldTable.convertToMap(_bindingArgs)); _store.bindQueue(binding); reopenStore(); @@ -156,8 +175,8 @@ public class DurableConfigurationStoreTest extends QpidTestCase public void testUnbindQueue() throws Exception { AMQQueue queue = createTestQueue(QUEUE_NAME, "queueOwner", false); - Binding binding = new Binding(UUIDGenerator.generateUUID(), ROUTING_KEY, queue, _exchange, - FieldTable.convertToMap(_bindingArgs)); + Binding binding = new Binding(UUIDGenerator.generateRandomUUID(), null, ROUTING_KEY, queue, + _exchange, FieldTable.convertToMap(_bindingArgs)); _store.bindQueue(binding); _store.unbindQueue(binding); @@ -173,7 +192,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase _store.createQueue(queue); reopenStore(); - verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null); + verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null, null); } public void testCreateQueueAMQQueueFieldTable() throws Exception @@ -187,10 +206,29 @@ public class DurableConfigurationStoreTest extends QpidTestCase _store.createQueue(queue, arguments); reopenStore(); - verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, arguments); + verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, arguments, null); } - public void testUpdateQueue() throws Exception + public void testCreateQueueAMQQueueWithAlternateExchange() throws Exception + { + Exchange alternateExchange = createTestAlternateExchange(); + + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true, alternateExchange); + _store.createQueue(queue); + + reopenStore(); + verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", true, null, alternateExchange.getId()); + } + + private Exchange createTestAlternateExchange() + { + UUID exchUuid = UUID.randomUUID(); + Exchange alternateExchange = mock(Exchange.class); + when(alternateExchange.getId()).thenReturn(exchUuid); + return alternateExchange; + } + + public void testUpdateQueueExclusivity() throws Exception { // create queue AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true); @@ -205,7 +243,26 @@ public class DurableConfigurationStoreTest extends QpidTestCase _store.updateQueue(queue); reopenStore(); - verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments); + verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments, null); + } + + public void testUpdateQueueAlternateExchange() throws Exception + { + // create queue + AMQQueue queue = createTestQueue(getName(), getName() + "Owner", true); + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put("x-qpid-dlq-enabled", Boolean.TRUE); + attributes.put("x-qpid-maximum-delivery-count", new Integer(10)); + FieldTable arguments = FieldTable.convertToFieldTable(attributes); + _store.createQueue(queue, arguments); + + // update the queue to have exclusive=false + Exchange alternateExchange = createTestAlternateExchange(); + queue = createTestQueue(getName(), getName() + "Owner", false, alternateExchange); + _store.updateQueue(queue); + + reopenStore(); + verify(_queueRecoveryHandler).queue(_queueId, getName(), getName() + "Owner", false, arguments, alternateExchange.getId()); } public void testRemoveQueue() throws Exception @@ -222,17 +279,23 @@ public class DurableConfigurationStoreTest extends QpidTestCase _store.removeQueue(queue); reopenStore(); verify(_queueRecoveryHandler, never()).queue(any(UUID.class), anyString(), anyString(), anyBoolean(), - any(FieldTable.class)); + any(FieldTable.class), any(UUID.class)); } private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive) throws AMQStoreException { + return createTestQueue(queueName, queueOwner, exclusive, null); + } + + private AMQQueue createTestQueue(String queueName, String queueOwner, boolean exclusive, Exchange alternateExchange) throws AMQStoreException + { AMQQueue queue = mock(AMQQueue.class); when(queue.getName()).thenReturn(queueName); when(queue.getNameShortString()).thenReturn(AMQShortString.valueOf(queueName)); when(queue.getOwner()).thenReturn(AMQShortString.valueOf(queueOwner)); when(queue.isExclusive()).thenReturn(exclusive); when(queue.getId()).thenReturn(_queueId); + when(queue.getAlternateExchange()).thenReturn(alternateExchange); return queue; } @@ -262,14 +325,14 @@ public class DurableConfigurationStoreTest extends QpidTestCase protected MessageStore createStore() throws Exception { - String storeFactoryClass = System.getProperty(MS_FACTORY_CLASS_NAME_KEY); - if (storeFactoryClass == null) + String storeClass = System.getProperty(MESSAGE_STORE_CLASS_NAME_KEY); + if (storeClass == null) { - storeFactoryClass = DerbyMessageStoreFactory.class.getName(); + storeClass = DerbyMessageStore.class.getName(); } CurrentActor.set(new TestLogActor(new SystemOutMessageLogger())); - MessageStoreFactory factory = (MessageStoreFactory) Class.forName(storeFactoryClass).newInstance(); - return factory.createMessageStore(); + MessageStore messageStore = (MessageStore) Class.forName(storeClass).newInstance(); + return messageStore; } public void testRecordXid() throws Exception @@ -297,7 +360,7 @@ public class DurableConfigurationStoreTest extends QpidTestCase private Record getTestRecord(long messageNumber) { - UUID queueId1 = UUIDGenerator.generateUUID(); + UUID queueId1 = UUIDGenerator.generateRandomUUID(); TransactionLogResource queue1 = mock(TransactionLogResource.class); when(queue1.getId()).thenReturn(queueId1); EnqueableMessage message1 = mock(EnqueableMessage.class); diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java new file mode 100644 index 0000000000..f1976ecee3 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreQuotaEventsTestBase.java @@ -0,0 +1,178 @@ +/* + * + * 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.store; + +import java.io.File; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.apache.commons.configuration.XMLConfiguration; +import org.apache.log4j.Logger; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.framing.BasicContentHeaderProperties; +import org.apache.qpid.framing.ContentHeaderBody; +import org.apache.qpid.framing.MethodRegistry; +import org.apache.qpid.framing.ProtocolVersion; +import org.apache.qpid.framing.abstraction.MessagePublishInfo; +import org.apache.qpid.framing.abstraction.MessagePublishInfoImpl; +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.message.MessageMetaData; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.util.FileUtils; + +public abstract class MessageStoreQuotaEventsTestBase extends QpidTestCase implements EventListener, TransactionLogResource +{ + private static final Logger _logger = Logger.getLogger(MessageStoreQuotaEventsTestBase.class); + + protected static final byte[] MESSAGE_DATA = new byte[32 * 1024]; + + private MessageStore _store; + private File _storeLocation; + + private List<Event> _events; + private UUID _transactionResource; + + protected abstract MessageStore createStore() throws Exception; + + protected abstract void applyStoreSpecificConfiguration(XMLConfiguration config); + + protected abstract int getNumberOfMessagesToFillStore(); + + @Override + public void setUp() throws Exception + { + super.setUp(); + + _storeLocation = new File(new File(TMP_FOLDER), getTestName()); + FileUtils.delete(_storeLocation, true); + + XMLConfiguration config = new XMLConfiguration(); + config.addProperty("environment-path", _storeLocation.getAbsolutePath()); + applyStoreSpecificConfiguration(config); + + _store = createStore(); + _store.configureConfigStore("test", null, config); + + _transactionResource = UUID.randomUUID(); + _events = new ArrayList<Event>(); + _store.addEventListener(this, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); + } + + @Override + public void tearDown() throws Exception + { + super.tearDown(); + FileUtils.delete(_storeLocation, true); + } + + public void testOverflow() throws Exception + { + Transaction transaction = _store.newTransaction(); + + List<EnqueableMessage> messages = new ArrayList<EnqueableMessage>(); + for (int i = 0; i < getNumberOfMessagesToFillStore(); i++) + { + EnqueableMessage m = addMessage(i); + messages.add(m); + transaction.enqueueMessage(this, m); + } + transaction.commitTran(); + + assertEvent(1, Event.PERSISTENT_MESSAGE_SIZE_OVERFULL); + + for (EnqueableMessage m : messages) + { + m.getStoredMessage().remove(); + } + + assertEvent(2, Event.PERSISTENT_MESSAGE_SIZE_UNDERFULL); + } + + protected EnqueableMessage addMessage(long id) + { + MessagePublishInfo pubInfoBody = new MessagePublishInfoImpl(new AMQShortString(getName()), false, false, + new AMQShortString(getName())); + BasicContentHeaderProperties props = new BasicContentHeaderProperties(); + props.setDeliveryMode(Integer.valueOf(BasicContentHeaderProperties.PERSISTENT).byteValue()); + props.setContentType(getTestName()); + + MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9); + int classForBasic = methodRegistry.createBasicQosOkBody().getClazz(); + ContentHeaderBody contentHeaderBody = new ContentHeaderBody(classForBasic, 1, props, MESSAGE_DATA.length); + + MessageMetaData metaData = new MessageMetaData(pubInfoBody, contentHeaderBody, 1); + StoredMessage<MessageMetaData> handle = _store.addMessage(metaData); + handle.addContent(0, ByteBuffer.wrap(MESSAGE_DATA)); + TestMessage message = new TestMessage(id, handle); + return message; + } + + @Override + public void event(Event event) + { + _logger.debug("Test event listener received event " + event); + _events.add(event); + } + + private void assertEvent(int expectedNumberOfEvents, Event... expectedEvents) + { + assertEquals("Unexpected number of events received ", expectedNumberOfEvents, _events.size()); + for (Event event : expectedEvents) + { + assertTrue("Expected event is not found:" + event, _events.contains(event)); + } + } + + @Override + public UUID getId() + { + return _transactionResource; + } + + private static class TestMessage implements EnqueableMessage + { + private final StoredMessage<?> _handle; + private final long _messageId; + + public TestMessage(long messageId, StoredMessage<?> handle) + { + _messageId = messageId; + _handle = handle; + } + + public long getMessageNumber() + { + return _messageId; + } + + public boolean isPersistent() + { + return true; + } + + public StoredMessage<?> getStoredMessage() + { + return _handle; + } + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java index 3fb0776083..a1536565ad 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/MessageStoreTest.java @@ -59,7 +59,6 @@ import java.io.File; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.UUID; /** * This tests the MessageStores by using the available interfaces. @@ -100,10 +99,10 @@ public class MessageStoreTest extends InternalBrokerBaseCase { super.setUp(); - String storePath = System.getProperty("QPID_WORK") + "/" + getName(); + String storePath = System.getProperty("QPID_WORK") + File.separator + getName(); _config = new PropertiesConfiguration(); - _config.addProperty("store.factoryclass", getTestProfileMessageStoreFactoryClassName()); + _config.addProperty("store.class", getTestProfileMessageStoreClassName()); _config.addProperty("store.environment-path", storePath); cleanup(new File(storePath)); @@ -268,15 +267,9 @@ public class MessageStoreTest extends InternalBrokerBaseCase //Validate normally expected properties of Queues/Topics validateDurableQueueProperties(); - //Update the durable exclusive queue's exclusivity and verify it is persisted and recovered correctly + //Update the durable exclusive queue's exclusivity setQueueExclusivity(false); validateQueueExclusivityProperty(false); - - //Reload the Virtualhost to recover the queues again - reloadVirtualHost(); - - //verify the change was persisted and recovered correctly - validateQueueExclusivityProperty(false); } /** @@ -702,8 +695,8 @@ public class MessageStoreTest extends InternalBrokerBaseCase //Ideally we would be able to use the QueueDeclareHandler here. try { - queue = AMQQueueFactory.createAMQQueueImpl(queueName, durable, queueOwner, false, exclusive, - getVirtualHost(), queueArguments); + queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), queueName.asString(), durable, queueOwner.asString(), false, exclusive, + getVirtualHost(), FieldTable.convertToMap(queueArguments)); validateQueueProperties(queue, usePriority, durable, exclusive, lastValueQueue); @@ -741,7 +734,7 @@ public class MessageStoreTest extends InternalBrokerBaseCase try { - exchange = type.newInstance(UUIDGenerator.generateUUID(), getVirtualHost(), name, durable, 0, false); + exchange = type.newInstance(UUIDGenerator.generateRandomUUID(), getVirtualHost(), name, durable, 0, false); } catch (AMQException e) { diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java index 42746f9119..c309dad5eb 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/OperationalLoggingListenerTest.java @@ -1,3 +1,19 @@ +/* + * 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.store; import java.util.ArrayList; @@ -12,22 +28,6 @@ import org.apache.qpid.server.logging.messages.ConfigStoreMessages; import org.apache.qpid.server.logging.messages.MessageStoreMessages; import org.apache.qpid.server.logging.messages.TransactionLogMessages; -/** - * 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 OperationalLoggingListenerTest extends TestCase { @@ -73,11 +73,11 @@ public class OperationalLoggingListenerTest extends TestCase } - messageStore.attainState(State.CONFIGURING); + messageStore.attainState(State.INITIALISING); assertEquals("Unexpected number of operational log messages on configuring", 1, messages.size()); assertEquals(messages.remove(0).toString(), ConfigStoreMessages.CREATED().toString()); - messageStore.attainState(State.CONFIGURED); + messageStore.attainState(State.INITIALISED); assertEquals("Unexpected number of operational log messages on CONFIGURED", setStoreLocation ? 3 : 2, messages.size()); assertEquals(messages.remove(0).toString(), MessageStoreMessages.CREATED().toString()); assertEquals(messages.remove(0).toString(), TransactionLogMessages.CREATED().toString()); @@ -86,7 +86,7 @@ public class OperationalLoggingListenerTest extends TestCase assertEquals(messages.remove(0).toString(), MessageStoreMessages.STORE_LOCATION(STORE_LOCATION).toString()); } - messageStore.attainState(State.RECOVERING); + messageStore.attainState(State.ACTIVATING); assertEquals("Unexpected number of operational log messages on RECOVERING", 1, messages.size()); assertEquals(messages.remove(0).toString(), MessageStoreMessages.RECOVERY_START().toString()); @@ -147,6 +147,12 @@ public class OperationalLoggingListenerTest extends TestCase { _eventManager.addEventListener(eventListener, events); } + + @Override + public String getStoreType() + { + return "TEST"; + } } private static class TestActor implements LogActor diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java index 97c88ca1d3..18efb976eb 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/store/StateManagerTest.java @@ -45,8 +45,8 @@ public class StateManagerTest extends TestCase implements EventListener { assertEquals(State.INITIAL, _manager.getState()); - _manager.stateTransition(State.INITIAL, State.CONFIGURING); - assertEquals(State.CONFIGURING, _manager.getState()); + _manager.attainState(State.INITIALISING); + assertEquals(State.INITIALISING, _manager.getState()); } public void testStateTransitionDisallowed() @@ -55,7 +55,7 @@ public class StateManagerTest extends TestCase implements EventListener try { - _manager.stateTransition(State.ACTIVE, State.CLOSING); + _manager.attainState(State.CLOSING); fail("Exception not thrown"); } catch (IllegalStateException e) @@ -98,22 +98,29 @@ public class StateManagerTest extends TestCase implements EventListener public void testValidStateTransitions() { assertEquals(State.INITIAL, _manager.getState()); - performValidTransition(StateManager.CONFIGURE); - performValidTransition(StateManager.CONFIGURE_COMPLETE); - performValidTransition(StateManager.RECOVER); + performValidTransition(StateManager.INITIALISE); + performValidTransition(StateManager.INITALISE_COMPLETE); performValidTransition(StateManager.ACTIVATE); + performValidTransition(StateManager.ACTIVATE_COMPLETE); performValidTransition(StateManager.QUIESCE); performValidTransition(StateManager.QUIESCE_COMPLETE); performValidTransition(StateManager.RESTART); - performValidTransition(StateManager.ACTIVATE); + performValidTransition(StateManager.ACTIVATE_COMPLETE); performValidTransition(StateManager.CLOSE_ACTIVE); performValidTransition(StateManager.CLOSE_COMPLETE); + + _manager = new StateManager(this); + assertEquals(State.INITIAL, _manager.getState()); + performValidTransition(StateManager.INITIALISE); + performValidTransition(StateManager.INITALISE_COMPLETE); + performValidTransition(StateManager.CLOSE_INITIALISED); + performValidTransition(StateManager.CLOSE_COMPLETE); _manager = new StateManager(this); - performValidTransition(StateManager.CONFIGURE); - performValidTransition(StateManager.CONFIGURE_COMPLETE); - performValidTransition(StateManager.RECOVER); + performValidTransition(StateManager.INITIALISE); + performValidTransition(StateManager.INITALISE_COMPLETE); performValidTransition(StateManager.ACTIVATE); + performValidTransition(StateManager.ACTIVATE_COMPLETE); performValidTransition(StateManager.QUIESCE); performValidTransition(StateManager.QUIESCE_COMPLETE); performValidTransition(StateManager.CLOSE_QUIESCED); @@ -132,54 +139,50 @@ public class StateManagerTest extends TestCase implements EventListener { assertEquals(State.INITIAL, _manager.getState()); - - performInvalidTransitions(StateManager.CONFIGURE, State.CONFIGURED); - performInvalidTransitions(StateManager.CONFIGURE_COMPLETE, State.RECOVERING); - performInvalidTransitions(StateManager.RECOVER, State.ACTIVE); - performInvalidTransitions(StateManager.ACTIVATE, State.QUIESCING, State.CLOSING); + performInvalidTransitions(StateManager.INITIALISE, State.INITIALISED); + performInvalidTransitions(StateManager.INITALISE_COMPLETE, State.ACTIVATING, State.CLOSING); + performInvalidTransitions(StateManager.ACTIVATE, State.ACTIVE); + performInvalidTransitions(StateManager.ACTIVATE_COMPLETE, State.QUIESCING, State.CLOSING, State.INITIALISED); performInvalidTransitions(StateManager.QUIESCE, State.QUIESCED); - performInvalidTransitions(StateManager.QUIESCE_COMPLETE, State.RECOVERING, State.CLOSING); + performInvalidTransitions(StateManager.QUIESCE_COMPLETE, State.ACTIVATING, State.CLOSING); performInvalidTransitions(StateManager.CLOSE_QUIESCED, State.CLOSED); performInvalidTransitions(StateManager.CLOSE_COMPLETE); - - - } - private void performInvalidTransitions(StateManager.Transition preTransition, State... validTransitions) + private void performInvalidTransitions(StateManager.Transition preTransition, State... validEndStates) { if(preTransition != null) { performValidTransition(preTransition); } - EnumSet<State> nextStates = EnumSet.allOf(State.class); + EnumSet<State> endStates = EnumSet.allOf(State.class); - if(validTransitions != null) + if(validEndStates != null) { - for(State state: validTransitions) + for(State state: validEndStates) { - nextStates.remove(state); + endStates.remove(state); } } - for(State nextState : nextStates) + for(State invalidEndState : endStates) { - performInvalidStateTransition(nextState); + performInvalidStateTransition(invalidEndState); } } - private void performInvalidStateTransition(State state) + private void performInvalidStateTransition(State invalidEndState) { try { _event = null; State startState = _manager.getState(); - _manager.attainState(state); - fail("Invalid state transition performed: " + startState + " to " + state); + _manager.attainState(invalidEndState); + fail("Invalid state transition performed: " + startState + " to " + invalidEndState); } catch(IllegalStateException e) { @@ -188,6 +191,7 @@ public class StateManagerTest extends TestCase implements EventListener assertNull("No event should have be fired", _event); } + @Override public void event(Event event) { _event = event; diff --git a/java/broker/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java b/java/broker/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java new file mode 100644 index 0000000000..5d316fca43 --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/store/derby/DerbyMessageStoreQuotaEventsTest.java @@ -0,0 +1,62 @@ +/* + * + * 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.store.derby; + +import org.apache.commons.configuration.XMLConfiguration; +import org.apache.log4j.Logger; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.MessageStoreQuotaEventsTestBase; + +public class DerbyMessageStoreQuotaEventsTest extends MessageStoreQuotaEventsTestBase +{ + private static final Logger _logger = Logger.getLogger(DerbyMessageStoreQuotaEventsTest.class); + + private static final int NUMBER_OF_MESSAGES_TO_OVERFILL_STORE = 10; + + /** + * Estimated using an assumption that a physical disk space occupied by a + * message is 3 times bigger then a message size + */ + private static final int OVERFULL_SIZE = (int) (MESSAGE_DATA.length * 3 * NUMBER_OF_MESSAGES_TO_OVERFILL_STORE * 0.8); + + private static final int UNDERFULL_SIZE = (int) (OVERFULL_SIZE * 0.8); + + @Override + protected int getNumberOfMessagesToFillStore() + { + return NUMBER_OF_MESSAGES_TO_OVERFILL_STORE; + } + + @Override + protected void applyStoreSpecificConfiguration(XMLConfiguration config) + { + _logger.debug("Applying store specific config. overfull-sze=" + OVERFULL_SIZE + ", underfull-size=" + UNDERFULL_SIZE); + + config.addProperty("overfull-size", OVERFULL_SIZE); + config.addProperty("underfull-size", UNDERFULL_SIZE); + } + + @Override + protected MessageStore createStore() throws Exception + { + return new DerbyMessageStore(); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java index 5ba9c0c015..8c5d2684ff 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java +++ b/java/broker/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java @@ -1,5 +1,3 @@ -package org.apache.qpid.server.subscription; - /* * * Licensed to the Apache Software Foundation (ASF) under one @@ -21,16 +19,24 @@ package org.apache.qpid.server.subscription; * */ +package org.apache.qpid.server.subscription; + import org.apache.qpid.AMQException; import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.AMQChannel; +import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.logging.LogActor; +import org.apache.qpid.server.logging.LogSubject; +import org.apache.qpid.server.message.InboundMessage; +import org.apache.qpid.server.protocol.AMQConnectionModel; +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.queue.QueueEntry.SubscriptionAcquiredState; +import org.apache.qpid.server.stats.StatisticsCounter; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; @@ -42,7 +48,7 @@ public class MockSubscription implements Subscription private AMQShortString tag = new AMQShortString("mocktag"); private AMQQueue queue = null; private StateListener _listener = null; - private AMQQueue.Context _queueContext = null; + private volatile AMQQueue.Context _queueContext = null; private State _state = State.ACTIVE; private ArrayList<QueueEntry> messages = new ArrayList<QueueEntry>(); private final Lock _stateChangeLock = new ReentrantLock(); @@ -76,19 +82,9 @@ public class MockSubscription implements Subscription _state = State.CLOSED; } - public boolean filtersMessages() - { - return false; - } - - public AMQChannel getChannel() - { - return null; - } - - public AMQShortString getConsumerTag() + public String getConsumerName() { - return tag; + return tag == null ? null : tag.asString(); } public long getSubscriptionID() @@ -121,11 +117,36 @@ public class MockSubscription implements Subscription return false; } + public long getBytesOut() + { + return 0; // TODO - Implement + } + + public long getMessagesOut() + { + return 0; // TODO - Implement + } + + public long getUnacknowledgedBytes() + { + return 0; // TODO - Implement + } + + public long getUnacknowledgedMessages() + { + return 0; // TODO - Implement + } + public AMQQueue getQueue() { return queue; } + public AMQSessionModel getSessionModel() + { + return new MockSessionModel(); + } + public boolean trySendLock() { return _stateChangeLock.tryLock(); @@ -154,11 +175,6 @@ public class MockSubscription implements Subscription return _isActive ; } - public void confirmAutoClose() - { - - } - public void set(String key, Object value) { } @@ -173,11 +189,6 @@ public class MockSubscription implements Subscription return false; } - public boolean isBrowser() - { - return false; - } - public boolean isClosed() { return _closed; @@ -207,10 +218,6 @@ public class MockSubscription implements Subscription _stateChangeLock.unlock(); } - public void resend(QueueEntry entry) throws AMQException - { - } - public void onDequeue(QueueEntry queueEntry) { } @@ -232,7 +239,6 @@ public class MockSubscription implements Subscription messages.add(entry); } - @Override public void flushBatched() { @@ -249,7 +255,7 @@ public class MockSubscription implements Subscription } public void setNoLocal(boolean noLocal) - { + { } public void setStateListener(StateListener listener) @@ -285,4 +291,259 @@ public class MockSubscription implements Subscription { _isActive = isActive; } + + private static class MockSessionModel implements AMQSessionModel + { + + @Override + public int compareTo(AMQSessionModel o) + { + return 0; + } + + @Override + public UUID getQMFId() + { + return null; + } + + @Override + public AMQConnectionModel getConnectionModel() + { + return new MockConnectionModel(); + } + + @Override + public String getClientID() + { + return null; + } + + @Override + public void close() throws AMQException + { + } + + @Override + public LogSubject getLogSubject() + { + return null; + } + + @Override + public void checkTransactionStatus(long openWarn, long openClose, + long idleWarn, long idleClose) throws AMQException + { + } + + @Override + public void block(AMQQueue queue) + { + } + + @Override + public void unblock(AMQQueue queue) + { + } + + @Override + public void block() + { + } + + @Override + public void unblock() + { + } + + @Override + public boolean getBlocking() + { + return false; + } + + @Override + public boolean onSameConnection(InboundMessage inbound) + { + return false; + } + + @Override + public int getUnacknowledgedMessageCount() + { + return 0; + } + + @Override + public Long getTxnCount() + { + return null; + } + + @Override + public Long getTxnStart() + { + return null; + } + + @Override + public Long getTxnCommits() + { + return null; + } + + @Override + public Long getTxnRejects() + { + return null; + } + + @Override + public int getChannelId() + { + return 0; + } + + @Override + public int getConsumerCount() + { + return 0; + } + } + + private static class MockConnectionModel implements AMQConnectionModel + { + @Override + public void initialiseStatistics() + { + } + + @Override + public void registerMessageReceived(long messageSize, long timestamp) + { + } + + @Override + public void registerMessageDelivered(long messageSize) + { + } + + @Override + public StatisticsCounter getMessageDeliveryStatistics() + { + return null; + } + + @Override + public StatisticsCounter getMessageReceiptStatistics() + { + return null; + } + + @Override + public StatisticsCounter getDataDeliveryStatistics() + { + return null; + } + + @Override + public StatisticsCounter getDataReceiptStatistics() + { + return null; + } + + @Override + public void resetStatistics() + { + + } + + @Override + public void close(AMQConstant cause, String message) + throws AMQException + { + } + + @Override + public void closeSession(AMQSessionModel session, AMQConstant cause, + String message) throws AMQException + { + } + + @Override + public long getConnectionId() + { + return 0; + } + + @Override + public List<AMQSessionModel> getSessionModels() + { + return null; + } + + @Override + public void block() + { + } + + @Override + public void unblock() + { + } + + @Override + public LogSubject getLogSubject() + { + return null; + } + + @Override + public String getUserName() + { + return null; + } + + @Override + public boolean isSessionNameUnique(byte[] name) + { + return false; + } + + @Override + public String getRemoteAddressString() + { + return "remoteAddress:1234"; + } + + @Override + public String getClientId() + { + return null; + } + + @Override + public String getClientVersion() + { + return null; + } + + @Override + public String getPrincipalAsString() + { + return null; + } + + @Override + public long getSessionCountLimit() + { + return 0; + } + + @Override + public long getLastIoTime() + { + return 0; + } + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java b/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java deleted file mode 100644 index dcb3692cf5..0000000000 --- a/java/broker/src/test/java/org/apache/qpid/server/transport/ServerConnectionMBeanTest.java +++ /dev/null @@ -1,230 +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.ManagedConnection; -import org.apache.qpid.server.configuration.MockConnectionConfig; -import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.util.InternalBrokerBaseCase; -import org.apache.qpid.server.virtualhost.VirtualHost; -import org.apache.qpid.transport.Binary; -import org.apache.qpid.transport.Connection; -import org.apache.qpid.transport.Session; - -import javax.management.JMException; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.TabularData; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.UUID; -import java.util.concurrent.atomic.AtomicLong; - -public class ServerConnectionMBeanTest extends InternalBrokerBaseCase -{ - private ServerConnection _serverConnection; - private ServerSessionMock _serverSession; - private ServerConnectionMBean _mbean; - private List<Session> _sessions = new ArrayList<Session>(); - - @Override - public void setUp() throws Exception - { - super.setUp(); - - final VirtualHost vhost = ApplicationRegistry.getInstance().getVirtualHostRegistry().getVirtualHost("test"); - _serverConnection = new ServerConnection(1) - { - protected Collection<Session> getChannels() - { - return _sessions; - } - public Session getSession(int channelId) - { - for(Session session : _sessions) - { - if (session.getChannel() == channelId) - { - return session; - } - } - return null; - } - @Override - public AtomicLong getLastIoTime() - { - return new AtomicLong(1); - } - }; - final MockConnectionConfig config = new MockConnectionConfig(UUID.randomUUID(), null, null, - false, 1, vhost, "address", Boolean.TRUE, Boolean.TRUE, Boolean.TRUE, - "authid", "remoteProcessName", new Integer(1967), new Integer(1970), vhost.getConfigStore(), Boolean.FALSE); - _serverConnection.setConnectionConfig(config); - _serverConnection.setVirtualHost(vhost); - _serverConnection.setConnectionDelegate(new ServerConnectionDelegate(getRegistry(), "")); - _serverSession = new ServerSessionMock(_serverConnection, 1); - _mbean = (ServerConnectionMBean) _serverConnection.getManagedObject(); - } - - public void testChannels() throws Exception - { - // check the channel count is correct - TabularData tabularData = _mbean.channels(); - - int channelCount = tabularData.size(); - assertEquals("Unexpected number of channels",1,channelCount); - _sessions.add(new ServerSession(_serverConnection, new ServerSessionDelegate(), - new Binary(getName().getBytes()), 2 , _serverConnection.getConfig())); - - channelCount = _mbean.channels().size(); - assertEquals("Unexpected number of channels",2,channelCount); - - final CompositeData chanresult = tabularData.get(new Integer[]{1}); - assertNotNull(chanresult); - assertEquals("Unexpected channel id", new Integer(1),(Integer)chanresult.get(ManagedConnection.CHAN_ID)); - assertNull("Unexpected default queue", chanresult.get(ManagedConnection.DEFAULT_QUEUE)); - assertFalse("Unexpected transactional flag", (Boolean)chanresult.get(ManagedConnection.TRANSACTIONAL)); - assertFalse("Flow should have been blocked", (Boolean)chanresult.get(ManagedConnection.FLOW_BLOCKED)); - assertEquals("Unexpected unack'd count", new Integer(1967), (Integer)chanresult.get(ManagedConnection.UNACKED_COUNT)); - } - - public void testMaxChannels() throws Exception - { - _serverConnection.getConnectionDelegate().setChannelMax(10001); - assertEquals("Max channels not got correctly", new Long(10001), _mbean.getMaximumNumberOfChannels()); - } - - public void testRollback() throws Exception - { - _mbean.rollbackTransactions(1); - assertFalse("Rollback performed despite not being transacted", _serverSession.isRolledback()); - - _serverSession.setTransactional(true); - _mbean.rollbackTransactions(1); - assertTrue("Rollback not performed", _serverSession.isRolledback()); - - try - { - _mbean.rollbackTransactions(2); - fail("Exception expected"); - } - catch (JMException jme) - { - //pass - } - } - - public void testCommit() throws Exception - { - _mbean.commitTransactions(1); - assertFalse("Commit performed despite not being transacted", _serverSession.isCommitted()); - - _serverSession.setTransactional(true); - _mbean.commitTransactions(1); - assertTrue("Commit not performed", _serverSession.isCommitted()); - - try - { - _mbean.commitTransactions(2); - fail("Exception expected"); - } - catch (JMException jme) - { - //pass - } - } - - public void testGetName() - { - assertEquals("Unexpected Object Instance Name", "\"address\"", _mbean.getObjectInstanceName()); - } - - public void testEnableStatistics() - { - assertFalse("Unexpected statistics enable flag", _mbean.isStatisticsEnabled()); - _mbean.setStatisticsEnabled(true); - assertTrue("Unexpected statistics enable flag", _mbean.isStatisticsEnabled()); - } - - public void testLastIOTime() - { - assertEquals("Unexpected last IO time", new Date(1), _mbean.getLastIoTime()); - } - - private class ServerSessionMock extends ServerSession - { - private int _channelId = 0; - private boolean _committed = false; - private boolean _rolledback = false; - private boolean _transacted = false; - - ServerSessionMock(Connection connection, int channelId) - { - super(connection, new ServerSessionDelegate(), new Binary(String.valueOf(channelId).getBytes()), 1 , _serverConnection.getConfig()); - _channelId = channelId; - _sessions.add(this); - } - - public int getChannel() - { - return _channelId; - } - - @Override - public void commit() - { - _committed = true; - } - - @Override - public void rollback() - { - _rolledback = true; - } - - public boolean isCommitted() - { - return _committed; - } - - public boolean isRolledback() - { - return _rolledback; - } - - @Override - public int getUnacknowledgedMessageCount() - { - return 1967; - } - - public boolean isTransactional() - { - return _transacted; - } - - public void setTransactional(boolean transacted) - { - _transacted = transacted; - } - } -} diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java b/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java new file mode 100644 index 0000000000..1aa91fa98a --- /dev/null +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/AsyncAutoCommitTransactionTest.java @@ -0,0 +1,140 @@ +/* + * 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.txn; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.*; + +import java.util.Collections; + +import org.apache.qpid.server.message.EnqueableMessage; +import org.apache.qpid.server.queue.BaseQueue; +import org.apache.qpid.server.store.MessageStore; +import org.apache.qpid.server.store.StoreFuture; +import org.apache.qpid.server.store.Transaction; +import org.apache.qpid.server.txn.AsyncAutoCommitTransaction.FutureRecorder; +import org.apache.qpid.server.txn.ServerTransaction.Action; +import org.apache.qpid.test.utils.QpidTestCase; + +public class AsyncAutoCommitTransactionTest extends QpidTestCase +{ + private static final String STRICT_ORDER_SYSTEM_PROPERTY = AsyncAutoCommitTransaction.QPID_STRICT_ORDER_WITH_MIXED_DELIVERY_MODE; + + private FutureRecorder _futureRecorder = mock(FutureRecorder.class); + private EnqueableMessage _message = mock(EnqueableMessage.class); + private BaseQueue _queue = mock(BaseQueue.class); + private MessageStore _messageStore = mock(MessageStore.class); + private Transaction _storeTransaction = mock(Transaction.class); + private Action _postTransactionAction = mock(Action.class); + private StoreFuture _future = mock(StoreFuture.class); + + + @Override + protected void setUp() throws Exception + { + super.setUp(); + + when(_messageStore.newTransaction()).thenReturn(_storeTransaction); + when(_storeTransaction.commitTranAsync()).thenReturn(_future); + when(_queue.isDurable()).thenReturn(true); + } + + public void testEnqueuePersistentMessagePostCommitNotCalledWhenFutureAlreadyComplete() throws Exception + { + setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false"); + + when(_message.isPersistent()).thenReturn(true); + when(_future.isComplete()).thenReturn(true); + + AsyncAutoCommitTransaction asyncAutoCommitTransaction = + new AsyncAutoCommitTransaction(_messageStore, _futureRecorder); + + asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction); + + verify(_storeTransaction).enqueueMessage(_queue, _message); + verify(_futureRecorder).recordFuture(_future, _postTransactionAction); + verifyZeroInteractions(_postTransactionAction); + } + + public void testEnqueuePersistentMessageOnMultiplQueuesPostCommitNotCalled() throws Exception + { + setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false"); + + when(_message.isPersistent()).thenReturn(true); + when(_future.isComplete()).thenReturn(true); + + AsyncAutoCommitTransaction asyncAutoCommitTransaction = + new AsyncAutoCommitTransaction(_messageStore, _futureRecorder); + + asyncAutoCommitTransaction.enqueue(Collections.singletonList(_queue), _message, _postTransactionAction, System.currentTimeMillis()); + + verify(_storeTransaction).enqueueMessage(_queue, _message); + verify(_futureRecorder).recordFuture(_future, _postTransactionAction); + verifyZeroInteractions(_postTransactionAction); + } + + public void testEnqueuePersistentMessagePostCommitNotCalledWhenFutureNotYetComplete() throws Exception + { + setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false"); + + when(_message.isPersistent()).thenReturn(true); + when(_future.isComplete()).thenReturn(false); + + AsyncAutoCommitTransaction asyncAutoCommitTransaction = + new AsyncAutoCommitTransaction(_messageStore, _futureRecorder); + + asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction); + + verify(_storeTransaction).enqueueMessage(_queue, _message); + verify(_futureRecorder).recordFuture(_future, _postTransactionAction); + verifyZeroInteractions(_postTransactionAction); + } + + public void testEnqueueTransientMessagePostCommitIsCalledWhenNotBehavingStrictly() throws Exception + { + setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "false"); + + when(_message.isPersistent()).thenReturn(false); + + AsyncAutoCommitTransaction asyncAutoCommitTransaction = + new AsyncAutoCommitTransaction(_messageStore, _futureRecorder); + + asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction); + + verifyZeroInteractions(_storeTransaction); + verify(_postTransactionAction).postCommit(); + verifyZeroInteractions(_futureRecorder); + } + + public void testEnqueueTransientMessagePostCommitIsCalledWhenBehavingStrictly() throws Exception + { + setTestSystemProperty(STRICT_ORDER_SYSTEM_PROPERTY, "true"); + + when(_message.isPersistent()).thenReturn(false); + + AsyncAutoCommitTransaction asyncAutoCommitTransaction = + new AsyncAutoCommitTransaction(_messageStore, _futureRecorder); + + asyncAutoCommitTransaction.enqueue(_queue, _message, _postTransactionAction); + + verifyZeroInteractions(_storeTransaction); + verify(_futureRecorder).recordFuture(StoreFuture.IMMEDIATE_FUTURE, _postTransactionAction); + verifyZeroInteractions(_postTransactionAction); + } +} diff --git a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java index af49238998..0221f3d509 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java +++ b/java/broker/src/test/java/org/apache/qpid/server/txn/MockStoreTransaction.java @@ -124,6 +124,12 @@ class MockStoreTransaction implements Transaction storeTransaction.setState(TransactionState.STARTED); return storeTransaction; } + + @Override + public String getStoreType() + { + return "TEST"; + } }; } }
\ No newline at end of file diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java index 8a34e92985..d7a9078412 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java +++ b/java/broker/src/test/java/org/apache/qpid/server/util/InternalBrokerBaseCase.java @@ -20,8 +20,7 @@ */ package org.apache.qpid.server.util; -import java.util.UUID; - +import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; import org.apache.qpid.AMQException; @@ -38,6 +37,7 @@ import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.logging.SystemOutMessageLogger; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.protocol.InternalTestProtocolSession; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.AMQQueueFactory; @@ -45,7 +45,6 @@ import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.registry.IApplicationRegistry; import org.apache.qpid.server.store.MessageStore; import org.apache.qpid.server.store.TestableMemoryMessageStore; -import org.apache.qpid.server.store.TestableMemoryMessageStoreFactory; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; @@ -68,10 +67,10 @@ public class InternalBrokerBaseCase extends QpidTestCase super.setUp(); _configXml.addProperty("virtualhosts.virtualhost.name", "test"); - _configXml.addProperty("virtualhosts.virtualhost.test.store.factoryclass", TestableMemoryMessageStoreFactory.class.getName()); + _configXml.addProperty("virtualhosts.virtualhost.test.store.class", TestableMemoryMessageStore.class.getName()); _configXml.addProperty("virtualhosts.virtualhost(-1).name", getName()); - _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.factoryclass", TestableMemoryMessageStoreFactory.class.getName()); + _configXml.addProperty("virtualhosts.virtualhost(-1)."+getName()+".store.class", TestableMemoryMessageStore.class.getName()); createBroker(); } @@ -85,7 +84,7 @@ public class InternalBrokerBaseCase extends QpidTestCase configure(); - _registry = new TestApplicationRegistry(_configuration); + _registry = createApplicationRegistry(); ApplicationRegistry.initialise(_registry); _registry.getVirtualHostRegistry().setDefaultVirtualHostName(getName()); _virtualHost = _registry.getVirtualHostRegistry().getVirtualHost(getName()); @@ -93,7 +92,7 @@ public class InternalBrokerBaseCase extends QpidTestCase QUEUE_NAME = new AMQShortString("test"); // Create a queue on the test Vhost.. this will aid in diagnosing duff tests // as the ExpiredMessage Task will log with the test Name. - _queue = AMQQueueFactory.createAMQQueueImpl(QUEUE_NAME, false, new AMQShortString("testowner"), + _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), QUEUE_NAME.asString(), false, "testowner", false, false, _virtualHost, null); Exchange defaultExchange = _virtualHost.getExchangeRegistry().getDefaultExchange(); @@ -102,7 +101,7 @@ public class InternalBrokerBaseCase extends QpidTestCase _virtualHost = _registry.getVirtualHostRegistry().getVirtualHost("test"); _messageStore = _virtualHost.getMessageStore(); - _queue = AMQQueueFactory.createAMQQueueImpl(new AMQShortString(getName()), false, new AMQShortString("testowner"), + _queue = AMQQueueFactory.createAMQQueueImpl(UUIDGenerator.generateRandomUUID(), getName(), false, "testowner", false, false, _virtualHost, null); _virtualHost.getQueueRegistry().registerQueue(_queue); @@ -119,6 +118,11 @@ public class InternalBrokerBaseCase extends QpidTestCase _session.addChannel(_channel); } + protected IApplicationRegistry createApplicationRegistry() throws ConfigurationException + { + return new TestApplicationRegistry(_configuration); + } + protected void configure() { // Allow other tests to override configuration @@ -250,7 +254,7 @@ public class InternalBrokerBaseCase extends QpidTestCase channel.publishContentHeader(_headerBody); } - + channel.sync(); } public void acknowledge(AMQChannel channel, long deliveryTag) diff --git a/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java b/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java index 7aa5ed23fe..a64ab620ab 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java +++ b/java/broker/src/test/java/org/apache/qpid/server/util/TestApplicationRegistry.java @@ -20,6 +20,9 @@ */ package org.apache.qpid.server.util; +import java.net.SocketAddress; +import java.util.Collections; +import java.util.Map; import org.apache.commons.configuration.ConfigurationException; import org.apache.qpid.server.configuration.ServerConfiguration; @@ -28,9 +31,11 @@ import org.apache.qpid.server.logging.NullRootMessageLogger; 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.plugins.PluginManager; import org.apache.qpid.server.registry.ApplicationRegistry; import org.apache.qpid.server.security.auth.database.PropertiesPrincipalDatabase; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.manager.IAuthenticationManagerRegistry; import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager; import java.util.Properties; @@ -51,11 +56,10 @@ public class TestApplicationRegistry extends ApplicationRegistry super.initialise(); } - /** - * @see org.apache.qpid.server.registry.ApplicationRegistry#createAuthenticationManager() - */ @Override - protected AuthenticationManager createAuthenticationManager() throws ConfigurationException + protected IAuthenticationManagerRegistry createAuthenticationManagerRegistry( + ServerConfiguration _configuration, PluginManager _pluginManager) + throws ConfigurationException { final Properties users = new Properties(); users.put("guest","guest"); @@ -63,7 +67,7 @@ public class TestApplicationRegistry extends ApplicationRegistry final PropertiesPrincipalDatabase ppd = new PropertiesPrincipalDatabase(users); - AuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager() + final AuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager() { /** @@ -83,12 +87,35 @@ public class TestApplicationRegistry extends ApplicationRegistry super.initialise(); } }; - pdam.initialise(); - return pdam; - } + return new IAuthenticationManagerRegistry() + { + @Override + public void close() + { + pdam.close(); + } + + @Override + public AuthenticationManager getAuthenticationManager( + SocketAddress address) + { + return pdam; + } + @Override + public Map<String, AuthenticationManager> getAvailableAuthenticationManagers() + { + return Collections.singletonMap(pdam.getClass().getName(), pdam); + } + + @Override + public void addRegistryChangeListener(RegistryChangeListener listener) + { + } + }; + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java index 0794154e47..8b4a52bb79 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/HouseKeepingTaskTest.java @@ -64,4 +64,50 @@ public class HouseKeepingTaskTest extends QpidTestCase //clean up the test actor CurrentActor.remove(); } + + public void testThreadNameIsSetForDurationOfTask() throws Exception + { + //create and set a test actor + LogActor testActor = new TestLogActor(new NullRootMessageLogger()); + CurrentActor.set(testActor); + + String originalThreadName = Thread.currentThread().getName(); + + String vhostName = "HouseKeepingTaskTestVhost"; + + String expectedThreadNameDuringExecution = vhostName + ":" + "ThreadNameRememberingTask"; + + ThreadNameRememberingTask testTask = new ThreadNameRememberingTask(new MockVirtualHost(vhostName)); + + testTask.run(); + + assertEquals("Thread name should have been set during execution", expectedThreadNameDuringExecution, testTask.getThreadNameDuringExecution()); + assertEquals("Thread name should have been reverted after task has run", originalThreadName, Thread.currentThread().getName()); + + //clean up the test actor + CurrentActor.remove(); + } + + + private static final class ThreadNameRememberingTask extends HouseKeepingTask + { + private String _threadNameDuringExecution; + + private ThreadNameRememberingTask(VirtualHost vhost) + { + super(vhost); + } + + @Override + public void execute() + { + _threadNameDuringExecution = Thread.currentThread().getName(); // store current thread name so we can assert it later + throw new RuntimeException("deliberate exception to check that thread name still gets reverted"); + } + + public String getThreadNameDuringExecution() + { + return _threadNameDuringExecution; + } + } } diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java index 91174c5d10..290c465785 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.java +++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/MockVirtualHost.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; @@ -141,11 +140,6 @@ public class MockVirtualHost implements VirtualHost return 0; } - public ManagedObject getManagedObject() - { - return null; - } - public MessageStore getMessageStore() { return null; @@ -222,6 +216,12 @@ public class MockVirtualHost implements VirtualHost return null; } + @Override + public UUID getQMFId() + { + return null; + } + public ConfiguredObject<VirtualHostConfigType, VirtualHostConfig> getParent() { return null; @@ -257,11 +257,6 @@ public class MockVirtualHost implements VirtualHost } - public boolean isStatisticsEnabled() - { - return false; - } - public void registerMessageDelivered(long messageSize) { @@ -277,14 +272,16 @@ public class MockVirtualHost implements VirtualHost } - public void setStatisticsEnabled(boolean enabled) + public State getState() { + return State.ACTIVE; + } + public void block() + { } - @Override - public State getState() + public void unblock() { - return State.ACTIVE; } }
\ No newline at end of file diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java index 87eb0f9d16..b8ba76e43d 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/VirtualHostImplTest.java @@ -27,7 +27,7 @@ import org.apache.qpid.server.configuration.ServerConfiguration; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.registry.ApplicationRegistry; -import org.apache.qpid.server.store.MemoryMessageStoreFactory; +import org.apache.qpid.server.store.MemoryMessageStore; import org.apache.qpid.server.util.TestApplicationRegistry; import org.apache.qpid.test.utils.QpidTestCase; @@ -192,7 +192,7 @@ public class VirtualHostImplTest extends QpidTestCase writer.write(" <name>" + vhostName + "</name>"); writer.write(" <" + vhostName + ">"); writer.write(" <store>"); - writer.write(" <factoryclass>" + MemoryMessageStoreFactory.class.getName() + "</factoryclass>"); + writer.write(" <class>" + MemoryMessageStore.class.getName() + "</class>"); writer.write(" </store>"); if(exchangeName != null && !dontDeclare) { diff --git a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java index fdd163b323..aa8448b99d 100644 --- a/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java +++ b/java/broker/src/test/java/org/apache/qpid/server/virtualhost/plugins/policies/TopicDeletePolicyTest.java @@ -146,7 +146,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase MockAMQQueue queue = createOwnedQueue(); - queue.addBinding(new Binding(null, "bindingKey", queue, new DirectExchange(), null)); + queue.addBinding(new Binding(null, null, "bindingKey", queue, new DirectExchange(), null)); policy.performPolicy(queue); @@ -165,7 +165,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase MockAMQQueue queue = createOwnedQueue(); - queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null)); + queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); queue.setAutoDelete(false); @@ -186,7 +186,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase final MockAMQQueue queue = createOwnedQueue(); - queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null)); + queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); setQueueToAutoDelete(queue); @@ -207,7 +207,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase MockAMQQueue queue = createOwnedQueue(); - queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null)); + queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); policy.performPolicy(queue); @@ -233,7 +233,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase MockAMQQueue queue = createOwnedQueue(); - queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null)); + queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); policy.performPolicy(queue); @@ -253,7 +253,7 @@ public class TopicDeletePolicyTest extends InternalBrokerBaseCase MockAMQQueue queue = createOwnedQueue(); - queue.addBinding(new Binding(null, "bindingKey", queue, new TopicExchange(), null)); + queue.addBinding(new Binding(null, null, "bindingKey", queue, new TopicExchange(), null)); policy.performPolicy(queue); |