summaryrefslogtreecommitdiff
path: root/java/broker/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'java/broker/src/main')
-rw-r--r--java/broker/src/main/java/org/apache/qpid/qmf/QMFService.java76
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java70
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java100
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Broker.java441
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java170
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/Main.java665
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java73
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerConfiguration.java307
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java75
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/VirtualHostConfiguration.java40
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java33
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/ConnectionRegistry.java56
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/connection/IConnectionRegistry.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/AbstractExchangeMBean.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java126
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/Bridge.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/federation/BrokerLink.java1
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java31
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionSecureOkMethodHandler.java13
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionStartOkMethodHandler.java15
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/QueueDeclareHandler.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/information/management/ServerInformationMBean.java81
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java62
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/messages/VirtualHost_logmessages.properties5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/DefaultManagedObject.java56
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/JMXManagedObjectRegistry.java90
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/management/MBeanInvocationHandlerImpl.java43
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/ContentHeaderBodyAdapter.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData.java76
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java10
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java263
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java72
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java73
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java91
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties93
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/plugins/PluginManager.java294
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQConnectionModel.java41
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngine.java365
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSession.java14
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java115
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQSessionModel.java28
-rw-r--r--[-rwxr-xr-x]java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java (renamed from java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java)10
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java147
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java48
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/protocol/ProtocolEngine_0_10.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java16
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntry.java31
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueEntryImpl.java36
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java84
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java217
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ApplicationRegistry.java374
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/BrokerConfigAdapter.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/ConfigurationFileApplicationRegistry.java8
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/registry/IApplicationRegistry.java11
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java53
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java34
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java77
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java221
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java35
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java49
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/management/AMQUserManagementMBean.java407
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManager.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java32
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/PrincipalDatabaseAuthenticationManager.java406
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java54
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java21
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java99
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java58
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java9
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java89
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java163
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java118
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java46
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionImpl.java54
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java213
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/subscription/Subscription_0_10.java42
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/QpidAcceptor.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnection.java198
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerConnectionDelegate.java148
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSession.java155
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/transport/ServerSessionDelegate.java259
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java5
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/LocalTransaction.java47
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java7
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java87
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferOutputStream.java (renamed from java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java)42
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/HouseKeepingTask.java4
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHost.java32
-rwxr-xr-xjava/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostConfigRecoveryHandler.java12
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/virtualhost/VirtualHostImpl.java200
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java2
118 files changed, 5811 insertions, 3132 deletions
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 c0afae0773..6abef6fd6b 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
@@ -694,7 +694,8 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
public BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommand queueMoveMessages(final BrokerSchema.BrokerClass.QueueMoveMessagesMethodResponseCommandFactory factory,
final String srcQueue,
final String destQueue,
- final Long qty)
+ final Long qty,
+ final Map filter) // TODO: move based on group identifier
{
// TODO
return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
@@ -712,6 +713,46 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
}
+ public BrokerSchema.BrokerClass.GetTimestampConfigMethodResponseCommand getTimestampConfig(final BrokerSchema.BrokerClass.GetTimestampConfigMethodResponseCommandFactory factory)
+ {
+ // TODO: timestamp support
+ return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
+ }
+
+ public BrokerSchema.BrokerClass.SetTimestampConfigMethodResponseCommand setTimestampConfig(final BrokerSchema.BrokerClass.SetTimestampConfigMethodResponseCommandFactory factory,
+ final java.lang.Boolean receive)
+ {
+ // TODO: timestamp support
+ return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
+ }
+
+ public BrokerSchema.BrokerClass.CreateMethodResponseCommand create(final BrokerSchema.BrokerClass.CreateMethodResponseCommandFactory factory,
+ final String type,
+ final String name,
+ final Map properties,
+ final java.lang.Boolean lenient)
+ {
+ //TODO:
+ return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
+ }
+
+ public BrokerSchema.BrokerClass.DeleteMethodResponseCommand delete(final BrokerSchema.BrokerClass.DeleteMethodResponseCommandFactory factory,
+ final String type,
+ final String name,
+ final Map options)
+ {
+ //TODO:
+ return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
+ }
+
+ public BrokerSchema.BrokerClass.QueryMethodResponseCommand query(final BrokerSchema.BrokerClass.QueryMethodResponseCommandFactory factory,
+ final String type,
+ final String name)
+ {
+ //TODO:
+ return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
+ }
+
public UUID getId()
{
return _obj.getId();
@@ -1072,8 +1113,19 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
return 0l;
}
+ public Boolean getFlowStopped()
+ {
+ return Boolean.FALSE;
+ }
+
+ public Long getFlowStoppedCount()
+ {
+ return 0L;
+ }
+
public BrokerSchema.QueueClass.PurgeMethodResponseCommand purge(final BrokerSchema.QueueClass.PurgeMethodResponseCommandFactory factory,
- final Long request)
+ final Long request,
+ final Map filter) // TODO: support for purge-by-group-identifier
{
try
{
@@ -1089,7 +1141,8 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
public BrokerSchema.QueueClass.RerouteMethodResponseCommand reroute(final BrokerSchema.QueueClass.RerouteMethodResponseCommandFactory factory,
final Long request,
final Boolean useAltExchange,
- final String exchange)
+ final String exchange,
+ final Map filter) // TODO: support for re-route-by-group-identifier
{
//TODO
return factory.createResponseCommand(CompletionCode.NOT_IMPLEMENTED);
@@ -1282,6 +1335,23 @@ public class QMFService implements ConfigStore.ConfigEventListener, Closeable
{
return _obj.isShadow();
}
+
+ public Boolean getUserProxyAuth()
+ {
+ // TODO
+ return false;
+ }
+
+ public String getSaslMechanism()
+ {
+ // TODO
+ return null;
+ }
+ public Integer getSaslSsf()
+ {
+ // TODO
+ return 0;
+ }
}
private class SessionDelegate implements BrokerSchema.SessionDelegate
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
index a612f280d6..d1ea5dba69 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java
@@ -327,4 +327,74 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr
{
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 4f86c82578..34bc57a826 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
@@ -22,6 +22,7 @@ package org.apache.qpid.server;
import org.apache.log4j.Logger;
+import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQMethodBody;
@@ -49,6 +50,7 @@ import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.actors.AMQPChannelActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ChannelMessages;
+import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.logging.subjects.ChannelLogSubject;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.message.MessageMetaData;
@@ -74,6 +76,7 @@ import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
+import org.apache.qpid.transport.TransportException;
import java.util.ArrayList;
import java.util.Collection;
@@ -136,11 +139,12 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
private final AtomicBoolean _suspended = new AtomicBoolean(false);
private ServerTransaction _transaction;
-
+
private final AtomicLong _txnStarts = new AtomicLong(0);
private final AtomicLong _txnCommits = new AtomicLong(0);
private final AtomicLong _txnRejects = new AtomicLong(0);
private final AtomicLong _txnCount = new AtomicLong(0);
+ private final AtomicLong _txnUpdateTime = new AtomicLong(0);
private final AMQProtocolSession _session;
private AtomicBoolean _closing = new AtomicBoolean(false);
@@ -199,7 +203,12 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
// theory
return !(_transaction instanceof AutoCommitTransaction);
}
-
+
+ public boolean inTransaction()
+ {
+ return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0;
+ }
+
private void incrementOutstandingTxnsIfNecessary()
{
if(isTransactional())
@@ -209,7 +218,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
_txnCount.compareAndSet(0,1);
}
}
-
+
private void decrementOutstandingTxnsIfNecessary()
{
if(isTransactional())
@@ -295,7 +304,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
});
deliverCurrentMessageIfComplete();
-
}
}
@@ -308,7 +316,6 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
try
{
_currentMessage.getStoredMessage().flushToStore();
-
final ArrayList<? extends BaseQueue> destinationQueues = _currentMessage.getDestinationQueues();
if(!checkMessageUserId(_currentMessage.getContentHeader()))
@@ -317,7 +324,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
else
{
- if(destinationQueues == null || _currentMessage.getDestinationQueues().isEmpty())
+ if(destinationQueues == null || destinationQueues.isEmpty())
{
if (_currentMessage.isMandatory() || _currentMessage.isImmediate())
{
@@ -325,7 +332,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
else
{
- _logger.warn("MESSAGE DISCARDED: No routes for message - " + createAMQMessage(_currentMessage));
+ _actor.message(ExchangeMessages.DISCARDMSG(_currentMessage.getExchange().asString(), _currentMessage.getRoutingKey()));
}
}
@@ -333,11 +340,15 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
_transaction.enqueue(destinationQueues, _currentMessage, new MessageDeliveryAction(_currentMessage, destinationQueues, isTransactional()));
incrementOutstandingTxnsIfNecessary();
+ updateTransactionalActivity();
}
}
}
finally
{
+ long bodySize = _currentMessage.getSize();
+ long timestamp = ((BasicContentHeaderProperties) _currentMessage.getContentHeader().getProperties()).getTimestamp();
+ _session.registerMessageReceived(bodySize, timestamp);
_currentMessage = null;
}
}
@@ -375,6 +386,13 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
_currentMessage = null;
throw e;
}
+ catch (RuntimeException e)
+ {
+ // we want to make sure we don't keep a reference to the message in the
+ // event of an error
+ _currentMessage = null;
+ throw e;
+ }
}
protected void routeCurrentMessage() throws AMQException
@@ -425,7 +443,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
throw new AMQException("Consumer already exists with same tag: " + tag);
}
-
+
Subscription subscription =
SubscriptionFactoryImpl.INSTANCE.createSubscription(_channelId, _session, tag, acks, filters, noLocal, _creditManager);
@@ -446,6 +464,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
_tag2SubscriptionMap.remove(tag);
throw e;
}
+ catch (RuntimeException e)
+ {
+ _tag2SubscriptionMap.remove(tag);
+ throw e;
+ }
return tag;
}
@@ -503,7 +526,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
catch (AMQException e)
{
- _logger.error("Caught AMQException whilst attempting to reque:" + e);
+ _logger.error("Caught AMQException whilst attempting to requeue:" + e);
+ }
+ catch (TransportException e)
+ {
+ _logger.error("Caught TransportException whilst attempting to requeue:" + e);
}
getConfigStore().removeConfiguredObject(this);
@@ -794,6 +821,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
Collection<QueueEntry> ackedMessages = getAckedMessages(deliveryTag, multiple);
_transaction.dequeue(ackedMessages, new MessageAcknowledgeAction(ackedMessages));
+ updateTransactionalActivity();
}
private Collection<QueueEntry> getAckedMessages(long deliveryTag, boolean multiple)
@@ -933,7 +961,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
finally
{
_rollingBack = false;
-
+
_txnRejects.incrementAndGet();
_txnStarts.incrementAndGet();
decrementOutstandingTxnsIfNecessary();
@@ -968,6 +996,17 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
}
+ /**
+ * Update last transaction activity timestamp
+ */
+ private void updateTransactionalActivity()
+ {
+ if (isTransactional())
+ {
+ _txnUpdateTime.set(System.currentTimeMillis());
+ }
+ }
+
public String toString()
{
return "["+_session.toString()+":"+_channelId+"]";
@@ -1016,6 +1055,7 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
public void deliverToClient(final Subscription sub, final QueueEntry entry, final long deliveryTag)
throws AMQException
{
+ _session.registerMessageDelivered(entry.getMessage().getSize());
getProtocolSession().getProtocolOutputConverter().writeDeliver(entry, getChannelId(),
deliveryTag, sub.getConsumerTag());
}
@@ -1056,11 +1096,11 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
private boolean checkMessageUserId(ContentHeaderBody header)
{
AMQShortString userID =
- header.properties instanceof BasicContentHeaderProperties
- ? ((BasicContentHeaderProperties) header.properties).getUserId()
+ header.getProperties() instanceof BasicContentHeaderProperties
+ ? ((BasicContentHeaderProperties) header.getProperties()).getUserId()
: null;
- return (!MSG_AUTH || _session.getPrincipal().getName().equals(userID == null? "" : userID.toString()));
+ return (!MSG_AUTH || _session.getAuthorizedPrincipal().getName().equals(userID == null? "" : userID.toString()));
}
@@ -1402,9 +1442,41 @@ public class AMQChannel implements SessionConfig, AMQSessionModel
{
return _createTime;
}
-
+
public void mgmtClose() throws AMQException
{
_session.mgmtCloseChannel(_channelId);
}
+
+ public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException
+ {
+ if (inTransaction())
+ {
+ long currentTime = System.currentTimeMillis();
+ 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)
+ {
+ CurrentActor.get().message(_logSubject, ChannelMessages.OPEN_TXN(openTime));
+ _logger.warn("OPEN TRANSACTION ALERT " + _logSubject.toString() + " " + openTime + " ms");
+ }
+
+ // Close connection for idle or open transactions that have timed out
+ if (idleClose > 0L && idleTime > idleClose)
+ {
+ 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");
+ }
+ }
+ }
}
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
new file mode 100644
index 0000000000..1632effaf0
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/Broker.java
@@ -0,0 +1,441 @@
+/*
+ *
+ * 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.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
+
+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.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import javax.net.ssl.SSLContext;
+
+import org.apache.log4j.PropertyConfigurator;
+import org.apache.log4j.xml.QpidLog4JConfigurator;
+import org.apache.qpid.server.configuration.ServerConfiguration;
+import org.apache.qpid.server.configuration.ServerNetworkTransportConfiguration;
+import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean;
+import org.apache.qpid.server.information.management.ServerInformationMBean;
+import org.apache.qpid.server.logging.SystemOutMessageLogger;
+import org.apache.qpid.server.logging.actors.BrokerActor;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.actors.GenericActor;
+import org.apache.qpid.server.logging.management.LoggingManagementMBean;
+import org.apache.qpid.server.logging.messages.BrokerMessages;
+import org.apache.qpid.server.protocol.AmqpProtocolVersion;
+import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
+import org.apache.qpid.server.transport.QpidAcceptor;
+import org.apache.qpid.ssl.SSLContextFactory;
+import org.apache.qpid.transport.NetworkTransportConfiguration;
+import org.apache.qpid.transport.network.IncomingNetworkTransport;
+import org.apache.qpid.transport.network.Transport;
+
+public class Broker
+{
+ private static final int IPV4_ADDRESS_LENGTH = 4;
+ private static final char IPV4_LITERAL_SEPARATOR = '.';
+
+ protected static class InitException extends RuntimeException
+ {
+ private static final long serialVersionUID = 1L;
+
+ InitException(String msg, Throwable cause)
+ {
+ super(msg, cause);
+ }
+ }
+
+ public void shutdown()
+ {
+ ApplicationRegistry.remove();
+ }
+
+ public void startup() throws Exception
+ {
+ startup(new BrokerOptions());
+ }
+
+ public void startup(final BrokerOptions options) throws Exception
+ {
+ try
+ {
+ CurrentActor.set(new BrokerActor(new SystemOutMessageLogger()));
+ startupImpl(options);
+ }
+ finally
+ {
+ CurrentActor.remove();
+ }
+ }
+
+ private void startupImpl(final BrokerOptions options) throws Exception
+ {
+ final String qpidHome = options.getQpidHome();
+ final File configFile = getConfigFile(options.getConfigFile(),
+ BrokerOptions.DEFAULT_CONFIG_FILE, qpidHome, true);
+
+ CurrentActor.get().message(BrokerMessages.CONFIG(configFile.getAbsolutePath()));
+
+ File logConfigFile = getConfigFile(options.getLogConfigFile(),
+ BrokerOptions.DEFAULT_LOG_CONFIG_FILE, qpidHome, false);
+
+ configureLogging(logConfigFile, options.getLogWatchFrequency());
+
+ ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile, options.getBundleContext());
+ ServerConfiguration serverConfig = config.getConfiguration();
+ updateManagementPorts(serverConfig, options.getJmxPortRegistryServer(), options.getJmxPortConnectorServer());
+
+ ApplicationRegistry.initialise(config);
+
+ // We have already loaded the BrokerMessages class by this point so we
+ // need to refresh the locale setting incase we had a different value in
+ // the configuration.
+ BrokerMessages.reload();
+
+ // AR.initialise() sets and removes its own actor so we now need to set the actor
+ // for the remainder of the startup, and the default actor if the stack is empty
+ CurrentActor.set(new BrokerActor(config.getCompositeStartupMessageLogger()));
+ CurrentActor.setDefault(new BrokerActor(config.getRootMessageLogger()));
+ GenericActor.setDefaultMessageLogger(config.getRootMessageLogger());
+
+ 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())
+ {
+ parsePortList(ports, serverConfig.getPorts());
+ }
+
+ Set<Integer> sslPorts = new HashSet<Integer>(options.getSSLPorts());
+ if(sslPorts.isEmpty())
+ {
+ parsePortList(sslPorts, serverConfig.getSSLPorts());
+ }
+
+ 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> 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> exclude_0_9 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_9));
+ if(exclude_0_9.isEmpty())
+ {
+ parsePortList(exclude_0_9, serverConfig.getPortExclude09());
+ }
+
+ Set<Integer> exclude_0_8 = new HashSet<Integer>(options.getExcludedPorts(ProtocolExclusion.v0_8));
+ if(exclude_0_8.isEmpty())
+ {
+ parsePortList(exclude_0_8, serverConfig.getPortExclude08());
+ }
+
+ String bindAddr = options.getBind();
+ if (bindAddr == null)
+ {
+ bindAddr = serverConfig.getBind();
+ }
+
+ InetAddress bindAddress = null;
+ if (bindAddr.equals(WILDCARD_ADDRESS))
+ {
+ bindAddress = new InetSocketAddress(0).getAddress();
+ }
+ else
+ {
+ bindAddress = InetAddress.getByAddress(parseIP(bindAddr));
+ }
+ String hostName = bindAddress.getCanonicalHostName();
+
+ if (!serverConfig.getSSLOnly())
+ {
+ for(int port : ports)
+ {
+ final Set<AmqpProtocolVersion> supported =
+ getSupportedVersions(port, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8);
+ final NetworkTransportConfiguration settings =
+ new ServerNetworkTransportConfiguration(serverConfig, port, bindAddress.getHostName(), Transport.TCP);
+
+ final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance();
+ final MultiVersionProtocolEngineFactory protocolEngineFactory =
+ new MultiVersionProtocolEngineFactory(hostName, supported);
+
+ transport.accept(settings, protocolEngineFactory, null);
+ ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
+ new QpidAcceptor(transport,"TCP"));
+ CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port));
+ }
+ }
+
+ if (serverConfig.getEnableSSL())
+ {
+ final String keystorePath = serverConfig.getConnectorKeyStorePath();
+ final String keystorePassword = serverConfig.getConnectorKeyStorePassword();
+ final String certType = serverConfig.getConnectorCertType();
+ final SSLContext sslContext = SSLContextFactory.buildServerContext(keystorePath, keystorePassword, certType);
+
+ for(int sslPort : sslPorts)
+ {
+ final Set<AmqpProtocolVersion> supported =
+ getSupportedVersions(sslPort, exclude_0_10, exclude_0_9_1, exclude_0_9, exclude_0_8);
+ final NetworkTransportConfiguration settings =
+ new ServerNetworkTransportConfiguration(serverConfig, sslPort, bindAddress.getHostName(), Transport.TCP);
+
+ final IncomingNetworkTransport transport = Transport.getIncomingTransportInstance();
+ final MultiVersionProtocolEngineFactory protocolEngineFactory =
+ new MultiVersionProtocolEngineFactory(hostName, supported);
+
+ transport.accept(settings, protocolEngineFactory, sslContext);
+ ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, sslPort),
+ new QpidAcceptor(transport,"TCP"));
+ CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", sslPort));
+ }
+ }
+
+ CurrentActor.get().message(BrokerMessages.READY());
+ }
+ finally
+ {
+ // Startup is complete so remove the AR initialised Startup actor
+ CurrentActor.remove();
+ }
+ }
+
+ private static Set<AmqpProtocolVersion> getSupportedVersions(final int port, final Set<Integer> exclude_0_10,
+ final Set<Integer> exclude_0_9_1, final Set<Integer> exclude_0_9,
+ final Set<Integer> exclude_0_8)
+ {
+ final EnumSet<AmqpProtocolVersion> supported = EnumSet.allOf(AmqpProtocolVersion.class);
+
+ if(exclude_0_10.contains(port))
+ {
+ supported.remove(AmqpProtocolVersion.v0_10);
+ }
+ if(exclude_0_9_1.contains(port))
+ {
+ supported.remove(AmqpProtocolVersion.v0_9_1);
+ }
+ if(exclude_0_9.contains(port))
+ {
+ supported.remove(AmqpProtocolVersion.v0_9);
+ }
+ if(exclude_0_8.contains(port))
+ {
+ supported.remove(AmqpProtocolVersion.v0_8);
+ }
+
+ return supported;
+ }
+
+ private File getConfigFile(final String fileName,
+ final String defaultFileName,
+ final String qpidHome, boolean throwOnFileNotFound) throws InitException
+ {
+ File configFile = null;
+ if (fileName != null)
+ {
+ configFile = new File(fileName);
+ }
+ else
+ {
+ configFile = new File(qpidHome, defaultFileName);
+ }
+
+ if (!configFile.exists() && throwOnFileNotFound)
+ {
+ String error = "File " + fileName + " could not be found. Check the file exists and is readable.";
+
+ if (qpidHome == null)
+ {
+ error = error + "\nNote: " + BrokerOptions.QPID_HOME + " is not set.";
+ }
+
+ throw new InitException(error, null);
+ }
+
+ return configFile;
+ }
+
+ public static void parsePortList(Set<Integer> output, List<?> ports) throws InitException
+ {
+ if(ports != null)
+ {
+ for(Object o : ports)
+ {
+ try
+ {
+ output.add(Integer.parseInt(String.valueOf(o)));
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid port: " + o, e);
+ }
+ }
+ }
+ }
+
+ /**
+ * Update the configuration data with the management port.
+ * @param configuration
+ * @param registryServerPort The string from the command line
+ */
+ private void updateManagementPorts(ServerConfiguration configuration, Integer registryServerPort, Integer connectorServerPort)
+ {
+ if (registryServerPort != null)
+ {
+ try
+ {
+ configuration.setJMXPortRegistryServer(registryServerPort);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid management (registry server) port: " + registryServerPort, null);
+ }
+ }
+ if (connectorServerPort != null)
+ {
+ try
+ {
+ configuration.setJMXPortConnectorServer(connectorServerPort);
+ }
+ catch (NumberFormatException e)
+ {
+ throw new InitException("Invalid management (connector server) port: " + connectorServerPort, null);
+ }
+ }
+ }
+
+ private byte[] parseIP(String address) throws Exception
+ {
+ char[] literalBuffer = address.toCharArray();
+ int byteCount = 0;
+ int currByte = 0;
+ byte[] ip = new byte[IPV4_ADDRESS_LENGTH];
+ for (int i = 0; i < literalBuffer.length; i++)
+ {
+ char currChar = literalBuffer[i];
+ if ((currChar >= '0') && (currChar <= '9'))
+ {
+ currByte = (currByte * 10) + (Character.digit(currChar, 10) & 0xFF);
+ }
+
+ if (currChar == IPV4_LITERAL_SEPARATOR || (i + 1 == literalBuffer.length))
+ {
+ ip[byteCount++] = (byte) currByte;
+ currByte = 0;
+ }
+ }
+
+ if (byteCount != 4)
+ {
+ throw new Exception("Invalid IP address: " + address);
+ }
+ return ip;
+ }
+
+ private void configureLogging(File logConfigFile, long logWatchTime) throws InitException, IOException
+ {
+ if (logConfigFile.exists() && logConfigFile.canRead())
+ {
+ CurrentActor.get().message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath()));
+
+ if (logWatchTime > 0)
+ {
+ System.out.println("log file " + logConfigFile.getAbsolutePath() + " will be checked for changes every "
+ + logWatchTime + " seconds");
+ // log4j expects the watch interval in milliseconds
+ try
+ {
+ QpidLog4JConfigurator.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000);
+ }
+ catch (Exception e)
+ {
+ throw new InitException(e.getMessage(),e);
+ }
+ }
+ else
+ {
+ try
+ {
+ QpidLog4JConfigurator.configure(logConfigFile.getPath());
+ }
+ catch (Exception e)
+ {
+ throw new InitException(e.getMessage(),e);
+ }
+ }
+ }
+ else
+ {
+ System.err.println("Logging configuration error: unable to read file " + logConfigFile.getAbsolutePath());
+ System.err.println("Using the fallback internal log4j.properties configuration");
+
+ InputStream propsFile = this.getClass().getResourceAsStream("/log4j.properties");
+ if(propsFile == null)
+ {
+ throw new IOException("Unable to load the fallback internal log4j.properties configuration file");
+ }
+ else
+ {
+ try
+ {
+ Properties fallbackProps = new Properties();
+ fallbackProps.load(propsFile);
+ PropertyConfigurator.configure(fallbackProps);
+ }
+ finally
+ {
+ propsFile.close();
+ }
+ }
+ }
+ }
+
+ private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception
+ {
+ LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime);
+
+ blm.register();
+ }
+}
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
new file mode 100644
index 0000000000..3defd8260c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/BrokerOptions.java
@@ -0,0 +1,170 @@
+/*
+ *
+ * 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.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.BundleContext;
+
+public class BrokerOptions
+{
+ /** serialVersionUID */
+ private static final long serialVersionUID = 8051825964945442234L;
+
+ 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";
+
+ 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 String _configFile;
+ private String _logConfigFile;
+ private String _bind;
+ private Integer _jmxPortRegistryServer;
+ private Integer _jmxPortConnectorServer;
+ private BundleContext _bundleContext;
+
+ private Integer _logWatchFrequency = 0;
+
+
+ public void addPort(final int port)
+ {
+ _ports.add(port);
+ }
+
+ public void addSSLPort(final int sslPort)
+ {
+ _sslPorts.add(sslPort);
+ }
+
+ public Set<Integer> getPorts()
+ {
+ return Collections.unmodifiableSet(_ports);
+ }
+
+ public Set<Integer> getSSLPorts()
+ {
+ return Collections.unmodifiableSet(_sslPorts);
+ }
+
+ public String getConfigFile()
+ {
+ return _configFile;
+ }
+
+ public void setConfigFile(final String configFile)
+ {
+ _configFile = configFile;
+ }
+
+ public String getLogConfigFile()
+ {
+ return _logConfigFile;
+ }
+
+ public void setLogConfigFile(final String logConfigFile)
+ {
+ _logConfigFile = logConfigFile;
+ }
+
+ public Integer getJmxPortRegistryServer()
+ {
+ return _jmxPortRegistryServer;
+ }
+
+ public void setJmxPortRegistryServer(final int jmxPortRegistryServer)
+ {
+ _jmxPortRegistryServer = jmxPortRegistryServer;
+ }
+
+ public Integer getJmxPortConnectorServer()
+ {
+ return _jmxPortConnectorServer;
+ }
+
+ public void setJmxPortConnectorServer(final int jmxPortConnectorServer)
+ {
+ _jmxPortConnectorServer = jmxPortConnectorServer;
+ }
+
+ public String getQpidHome()
+ {
+ return System.getProperty(QPID_HOME);
+ }
+
+ public Set<Integer> getExcludedPorts(final ProtocolExclusion excludeProtocol)
+ {
+ final Set<Integer> excludedPorts = _exclusionMap.get(excludeProtocol);
+ return excludedPorts == null ? Collections.<Integer>emptySet() : excludedPorts;
+ }
+
+ public void addExcludedPort(final ProtocolExclusion excludeProtocol, final int port)
+ {
+ if (!_exclusionMap.containsKey(excludeProtocol))
+ {
+ _exclusionMap.put(excludeProtocol, new HashSet<Integer>());
+ }
+
+ Set<Integer> ports = _exclusionMap.get(excludeProtocol);
+ ports.add(port);
+ }
+
+ public String getBind()
+ {
+ return _bind;
+ }
+
+ public void setBind(final String bind)
+ {
+ _bind = bind;
+ }
+
+ public int getLogWatchFrequency()
+ {
+ return _logWatchFrequency;
+ }
+
+ /**
+ * Set the frequency with which the log config file will be checked for updates.
+ * @param logWatchFrequency frequency in seconds
+ */
+ public void setLogWatchFrequency(final int logWatchFrequency)
+ {
+ _logWatchFrequency = logWatchFrequency;
+ }
+
+ public BundleContext getBundleContext()
+ {
+ return _bundleContext ;
+ }
+
+ public void setBundleContext(final BundleContext bundleContext)
+ {
+ _bundleContext = bundleContext;
+ }
+
+} \ 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 71cf17ed60..0c038c7800 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
@@ -20,17 +20,6 @@
*/
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.EnumSet;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
@@ -38,29 +27,9 @@ import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
-import org.apache.log4j.Logger;
-import org.apache.log4j.PropertyConfigurator;
-import org.apache.log4j.xml.QpidLog4JConfigurator;
-import org.apache.qpid.common.QpidProperties;
-import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.configuration.management.ConfigurationManagementMBean;
-import org.apache.qpid.server.information.management.ServerInformationMBean;
-import org.apache.qpid.server.logging.SystemOutMessageLogger;
-import org.apache.qpid.server.logging.actors.BrokerActor;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.GenericActor;
-import org.apache.qpid.server.logging.management.LoggingManagementMBean;
-import org.apache.qpid.server.logging.messages.BrokerMessages;
-import org.apache.qpid.server.protocol.AMQProtocolEngineFactory;
-import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory;
-import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory.VERSION;
+import org.apache.qpid.server.Broker.InitException;
import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.ConfigurationFileApplicationRegistry;
-import org.apache.qpid.server.transport.QpidAcceptor;
-import org.apache.qpid.ssl.SSLContextFactory;
-import org.apache.qpid.transport.NetworkDriver;
-import org.apache.qpid.transport.network.mina.MINANetworkDriver;
+
/**
* Main entry point for AMQPD.
@@ -68,41 +37,129 @@ import org.apache.qpid.transport.network.mina.MINANetworkDriver;
*/
public class Main
{
- private static Logger _logger;
- private static final String DEFAULT_CONFIG_FILE = "etc/config.xml";
-
- public static final String DEFAULT_LOG_CONFIG_FILENAME = "log4j.xml";
- public static final String QPID_HOME = "QPID_HOME";
- private static final int IPV4_ADDRESS_LENGTH = 4;
+ private static final Option OPTION_HELP = new Option("h", "help", false, "print this message");
+
+ private static final Option OPTION_VERSION = new Option("v", "version", false, "print the version information and exit");
+
+ private static final Option OPTION_CONFIG_FILE =
+ OptionBuilder.withArgName("file").hasArg().withDescription("use given configuration file").withLongOpt("config")
+ .create("c");
+
+ private static final Option OPTION_PORT =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("listen on the specified port. Overrides any value in the config file")
+ .withLongOpt("port").create("p");
+
+ private static final Option OPTION_SSLPORT =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("SSL port. Overrides any value in the config file")
+ .withLongOpt("sslport").create("s");
+
+ private static final Option OPTION_EXCLUDE_0_10 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-10 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-10").create();
+
+ private static final Option OPTION_EXCLUDE_0_9_1 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-9-1 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-9-1").create();
+
+ private static final Option OPTION_EXCLUDE_0_9 =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("when listening on the specified port do not accept AMQP0-9 connections. The specified port must be one specified on the command line")
+ .withLongOpt("exclude-0-9").create();
+
+ private static final Option OPTION_EXCLUDE_0_8 =
+ OptionBuilder.withArgName("port").hasArg()
+ .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_JMX_PORT_REGISTRY_SERVER =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("listen on the specified management (registry server) port. Overrides any value in the config file")
+ .withLongOpt("jmxregistryport").create("m");
+
+ private static final Option OPTION_JMX_PORT_CONNECTOR_SERVER =
+ OptionBuilder.withArgName("port").hasArg()
+ .withDescription("listen on the specified management (connector server) port. Overrides any value in the config file")
+ .withLongOpt("jmxconnectorport").create();
+
+ private static final Option OPTION_BIND =
+ OptionBuilder.withArgName("address").hasArg()
+ .withDescription("bind to the specified address. Overrides any value in the config file")
+ .withLongOpt("bind").create("b");
+
+ private static final Option OPTION_LOG_CONFIG_FILE =
+ OptionBuilder.withArgName("file").hasArg()
+ .withDescription("use the specified log4j xml configuration file. By "
+ + "default looks for a file named " + BrokerOptions.DEFAULT_LOG_CONFIG_FILE
+ + " in the same directory as the configuration file").withLongOpt("logconfig").create("l");
+
+ private static final Option OPTION_LOG_WATCH =
+ OptionBuilder.withArgName("period").hasArg()
+ .withDescription("monitor the log file configuration file for changes. Units are seconds. "
+ + "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
+
+ private static final Options OPTIONS = new Options();
+
+ static
+ {
+ OPTIONS.addOption(OPTION_HELP);
+ OPTIONS.addOption(OPTION_VERSION);
+ OPTIONS.addOption(OPTION_CONFIG_FILE);
+ OPTIONS.addOption(OPTION_LOG_CONFIG_FILE);
+ OPTIONS.addOption(OPTION_LOG_WATCH);
+ OPTIONS.addOption(OPTION_PORT);
+ OPTIONS.addOption(OPTION_SSLPORT);
+ OPTIONS.addOption(OPTION_EXCLUDE_0_10);
+ OPTIONS.addOption(OPTION_EXCLUDE_0_9_1);
+ OPTIONS.addOption(OPTION_EXCLUDE_0_9);
+ OPTIONS.addOption(OPTION_EXCLUDE_0_8);
+ OPTIONS.addOption(OPTION_BIND);
+
+ OPTIONS.addOption(OPTION_JMX_PORT_REGISTRY_SERVER);
+ OPTIONS.addOption(OPTION_JMX_PORT_CONNECTOR_SERVER);
+ }
- private static final char IPV4_LITERAL_SEPARATOR = '.';
+ private CommandLine commandLine;
- protected static class InitException extends Exception
+ public static void main(String[] args)
{
- InitException(String msg, Throwable cause)
+ //if the -Dlog4j.configuration property has not been set, enable the init override
+ //to stop Log4J wondering off and picking up the first log4j.xml/properties file it
+ //finds from the classpath when we get the first Loggers
+ if(System.getProperty("log4j.configuration") == null)
{
- super(msg, cause);
+ System.setProperty("log4j.defaultInitOverride", "true");
}
- }
- protected final Options options = new Options();
- protected CommandLine commandLine;
+ new Main(args);
+ }
- protected Main(String[] args)
+ public Main(final String[] args)
{
- setOptions(options);
if (parseCommandline(args))
{
- execute();
+ try
+ {
+ execute();
+ }
+ catch(Throwable e)
+ {
+ System.err.println("Exception during startup: " + e);
+ e.printStackTrace();
+ shutdown(1);
+ }
}
}
- protected boolean parseCommandline(String[] args)
+ protected boolean parseCommandline(final String[] args)
{
try
{
- commandLine = new PosixParser().parse(options, args);
+ commandLine = new PosixParser().parse(OPTIONS, args);
return true;
}
@@ -110,509 +167,129 @@ public class Main
{
System.err.println("Error: " + e.getMessage());
HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("Qpid", options, true);
+ formatter.printHelp("Qpid", OPTIONS, true);
return false;
}
}
- @SuppressWarnings("static-access")
- protected void setOptions(Options options)
- {
- Option help = new Option("h", "help", false, "print this message");
- Option version = new Option("v", "version", false, "print the version information and exit");
- Option configFile =
- OptionBuilder.withArgName("file").hasArg().withDescription("use given configuration file").withLongOpt("config")
- .create("c");
- Option port =
- OptionBuilder.withArgName("port").hasArg()
- .withDescription("listen on the specified port. Overrides any value in the config file")
- .withLongOpt("port").create("p");
-
- Option exclude0_10 =
- OptionBuilder.withArgName("exclude-0-10").hasArg()
- .withDescription("when listening on the specified port do not accept AMQP0-10 connections. The specified port must be one specified on the command line")
- .withLongOpt("exclude-0-10").create();
-
- Option exclude0_9_1 =
- OptionBuilder.withArgName("exclude-0-9-1").hasArg()
- .withDescription("when listening on the specified port do not accept AMQP0-9-1 connections. The specified port must be one specified on the command line")
- .withLongOpt("exclude-0-9-1").create();
-
-
- Option exclude0_9 =
- OptionBuilder.withArgName("exclude-0-9").hasArg()
- .withDescription("when listening on the specified port do not accept AMQP0-9 connections. The specified port must be one specified on the command line")
- .withLongOpt("exclude-0-9").create();
-
-
- Option exclude0_8 =
- OptionBuilder.withArgName("exclude-0-8").hasArg()
- .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();
-
-
- Option mport =
- OptionBuilder.withArgName("mport").hasArg()
- .withDescription("listen on the specified management port. Overrides any value in the config file")
- .withLongOpt("mport").create("m");
-
-
- Option bind =
- OptionBuilder.withArgName("bind").hasArg()
- .withDescription("bind to the specified address. Overrides any value in the config file")
- .withLongOpt("bind").create("b");
- Option logconfig =
- OptionBuilder.withArgName("logconfig").hasArg()
- .withDescription("use the specified log4j xml configuration file. By "
- + "default looks for a file named " + DEFAULT_LOG_CONFIG_FILENAME
- + " in the same directory as the configuration file").withLongOpt("logconfig").create("l");
- Option logwatchconfig =
- OptionBuilder.withArgName("logwatch").hasArg()
- .withDescription("monitor the log file configuration file for changes. Units are seconds. "
- + "Zero means do not check for changes.").withLongOpt("logwatch").create("w");
-
- options.addOption(help);
- options.addOption(version);
- options.addOption(configFile);
- options.addOption(logconfig);
- options.addOption(logwatchconfig);
- options.addOption(port);
- options.addOption(exclude0_10);
- options.addOption(exclude0_9_1);
- options.addOption(exclude0_9);
- options.addOption(exclude0_8);
- options.addOption(mport);
- options.addOption(bind);
- }
-
- protected void execute()
+ protected void execute() throws Exception
{
- // note this understands either --help or -h. If an option only has a long name you can use that but if
- // an option has a short name and a long name you must use the short name here.
- if (commandLine.hasOption("h"))
+ BrokerOptions options = new BrokerOptions();
+ String configFile = commandLine.getOptionValue(OPTION_CONFIG_FILE.getOpt());
+ if(configFile != null)
{
- HelpFormatter formatter = new HelpFormatter();
- formatter.printHelp("Qpid", options, true);
+ options.setConfigFile(configFile);
}
- else if (commandLine.hasOption("v"))
- {
- String ver = QpidProperties.getVersionString();
- StringBuilder protocol = new StringBuilder("AMQP version(s) [major.minor]: ");
-
- boolean first = true;
- for (ProtocolVersion pv : ProtocolVersion.getSupportedProtocolVersions())
- {
- if (first)
- {
- first = false;
- }
- else
- {
- protocol.append(", ");
- }
-
- protocol.append(pv.getMajorVersion()).append('-').append(pv.getMinorVersion());
-
- }
-
- System.out.println(ver + " (" + protocol + ")");
- }
- else
+ String logWatchConfig = commandLine.getOptionValue(OPTION_LOG_WATCH.getOpt());
+ if(logWatchConfig != null)
{
- try
- {
- CurrentActor.set(new BrokerActor(new SystemOutMessageLogger()));
- startup();
- CurrentActor.remove();
- }
- catch (InitException e)
- {
- System.out.println("Initialisation Error : " + e.getMessage());
- shutdown(1);
- }
- catch (Throwable e)
- {
- System.out.println("Error initialising message broker: " + e);
- e.printStackTrace();
- shutdown(1);
- }
+ options.setLogWatchFrequency(Integer.parseInt(logWatchConfig));
}
- }
-
- protected void shutdown(int status)
- {
- ApplicationRegistry.removeAll();
- System.exit(status);
- }
- protected void startup() throws Exception
- {
- final String QpidHome = System.getProperty(QPID_HOME);
- final File defaultConfigFile = new File(QpidHome, DEFAULT_CONFIG_FILE);
- final File configFile = new File(commandLine.getOptionValue("c", defaultConfigFile.getPath()));
- if (!configFile.exists())
- {
- String error = "File " + configFile + " could not be found. Check the file exists and is readable.";
-
- if (QpidHome == null)
- {
- error = error + "\nNote: " + QPID_HOME + " is not set.";
- }
-
- throw new InitException(error, null);
- }
- else
+ String logConfig = commandLine.getOptionValue(OPTION_LOG_CONFIG_FILE.getOpt());
+ if(logConfig != null)
{
- CurrentActor.get().message(BrokerMessages.CONFIG(configFile.getAbsolutePath()));
+ options.setLogConfigFile(logConfig);
}
- String logConfig = commandLine.getOptionValue("l");
- String logWatchConfig = commandLine.getOptionValue("w", "0");
-
- int logWatchTime = 0;
- try
- {
- logWatchTime = Integer.parseInt(logWatchConfig);
- }
- catch (NumberFormatException e)
+ String jmxPortRegistryServer = commandLine.getOptionValue(OPTION_JMX_PORT_REGISTRY_SERVER.getOpt());
+ if(jmxPortRegistryServer != null)
{
- System.err.println("Log watch configuration value of " + logWatchConfig + " is invalid. Must be "
- + "a non-negative integer. Using default of zero (no watching configured");
+ options.setJmxPortRegistryServer(Integer.parseInt(jmxPortRegistryServer));
}
- File logConfigFile;
- if (logConfig != null)
- {
- logConfigFile = new File(logConfig);
- configureLogging(logConfigFile, logWatchTime);
- }
- else
+ String jmxPortConnectorServer = commandLine.getOptionValue(OPTION_JMX_PORT_CONNECTOR_SERVER.getLongOpt());
+ if(jmxPortConnectorServer != null)
{
- File configFileDirectory = configFile.getParentFile();
- logConfigFile = new File(configFileDirectory, DEFAULT_LOG_CONFIG_FILENAME);
- configureLogging(logConfigFile, logWatchTime);
+ options.setJmxPortConnectorServer(Integer.parseInt(jmxPortConnectorServer));
}
- ConfigurationFileApplicationRegistry config = new ConfigurationFileApplicationRegistry(configFile);
- ServerConfiguration serverConfig = config.getConfiguration();
- updateManagementPort(serverConfig, commandLine.getOptionValue("m"));
-
- ApplicationRegistry.initialise(config);
-
- // We have already loaded the BrokerMessages class by this point so we
- // need to refresh the locale setting incase we had a different value in
- // the configuration.
- BrokerMessages.reload();
-
- // AR.initialise() sets and removes its own actor so we now need to set the actor
- // for the remainder of the startup, and the default actor if the stack is empty
- CurrentActor.set(new BrokerActor(config.getCompositeStartupMessageLogger()));
- CurrentActor.setDefault(new BrokerActor(config.getRootMessageLogger()));
- GenericActor.setDefaultMessageLogger(config.getRootMessageLogger());
-
-
- try
+ String bindAddr = commandLine.getOptionValue(OPTION_BIND.getOpt());
+ if (bindAddr != null)
{
- configureLoggingManagementMBean(logConfigFile, logWatchTime);
-
- ConfigurationManagementMBean configMBean = new ConfigurationManagementMBean();
- configMBean.register();
-
- ServerInformationMBean sysInfoMBean =
- new ServerInformationMBean(QpidProperties.getBuildVersion(), QpidProperties.getReleaseVersion());
- sysInfoMBean.register();
-
-
- String[] portStr = commandLine.getOptionValues("p");
-
- Set<Integer> ports = new HashSet<Integer>();
- Set<Integer> exclude_0_10 = new HashSet<Integer>();
- Set<Integer> exclude_0_9_1 = new HashSet<Integer>();
- Set<Integer> exclude_0_9 = new HashSet<Integer>();
- Set<Integer> exclude_0_8 = new HashSet<Integer>();
-
- if(portStr == null || portStr.length == 0)
- {
-
- parsePortList(ports, serverConfig.getPorts());
- parsePortList(exclude_0_10, serverConfig.getPortExclude010());
- parsePortList(exclude_0_9_1, serverConfig.getPortExclude091());
- parsePortList(exclude_0_9, serverConfig.getPortExclude09());
- parsePortList(exclude_0_8, serverConfig.getPortExclude08());
-
- }
- else
- {
- parsePortArray(ports, portStr);
- parsePortArray(exclude_0_10, commandLine.getOptionValues("exclude-0-10"));
- parsePortArray(exclude_0_9_1, commandLine.getOptionValues("exclude-0-9-1"));
- parsePortArray(exclude_0_9, commandLine.getOptionValues("exclude-0-9"));
- parsePortArray(exclude_0_8, commandLine.getOptionValues("exclude-0-8"));
-
- }
-
-
-
-
- String bindAddr = commandLine.getOptionValue("b");
- if (bindAddr == null)
- {
- bindAddr = serverConfig.getBind();
- }
- InetAddress bindAddress = null;
-
-
-
- if (bindAddr.equals("wildcard"))
- {
- bindAddress = new InetSocketAddress(0).getAddress();
- }
- else
- {
- bindAddress = InetAddress.getByAddress(parseIP(bindAddr));
- }
-
- String hostName = bindAddress.getCanonicalHostName();
-
-
- String keystorePath = serverConfig.getKeystorePath();
- String keystorePassword = serverConfig.getKeystorePassword();
- String certType = serverConfig.getCertType();
- SSLContextFactory sslFactory = null;
-
- if (!serverConfig.getSSLOnly())
- {
-
- for(int port : ports)
- {
-
- NetworkDriver driver = new MINANetworkDriver();
-
- Set<VERSION> supported = EnumSet.allOf(VERSION.class);
-
- if(exclude_0_10.contains(port))
- {
- supported.remove(VERSION.v0_10);
- }
-
- if(exclude_0_9_1.contains(port))
- {
- supported.remove(VERSION.v0_9_1);
- }
- if(exclude_0_9.contains(port))
- {
- supported.remove(VERSION.v0_9);
- }
- if(exclude_0_8.contains(port))
- {
- supported.remove(VERSION.v0_8);
- }
-
- MultiVersionProtocolEngineFactory protocolEngineFactory =
- new MultiVersionProtocolEngineFactory(hostName, supported);
-
-
-
- driver.bind(port, new InetAddress[]{bindAddress}, protocolEngineFactory,
- serverConfig.getNetworkConfiguration(), null);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, port),
- new QpidAcceptor(driver,"TCP"));
- CurrentActor.get().message(BrokerMessages.LISTENING("TCP", port));
-
- }
-
- }
-
- if (serverConfig.getEnableSSL())
- {
- sslFactory = new SSLContextFactory(keystorePath, keystorePassword, certType);
- NetworkDriver driver = new MINANetworkDriver();
- driver.bind(serverConfig.getSSLPort(), new InetAddress[]{bindAddress},
- new AMQProtocolEngineFactory(), serverConfig.getNetworkConfiguration(), sslFactory);
- ApplicationRegistry.getInstance().addAcceptor(new InetSocketAddress(bindAddress, serverConfig.getSSLPort()),
- new QpidAcceptor(driver,"TCP"));
- CurrentActor.get().message(BrokerMessages.LISTENING("TCP/SSL", serverConfig.getSSLPort()));
- }
-
- CurrentActor.get().message(BrokerMessages.READY());
-
- }
- finally
- {
- // Startup is complete so remove the AR initialised Startup actor
- CurrentActor.remove();
+ options.setBind(bindAddr);
}
-
-
- }
-
- private void parsePortArray(Set<Integer> ports, String[] portStr)
- throws InitException
- {
+ String[] portStr = commandLine.getOptionValues(OPTION_PORT.getOpt());
if(portStr != null)
{
- for(int i = 0; i < portStr.length; i++)
+ parsePortArray(options, portStr, false);
+ for(ProtocolExclusion pe : ProtocolExclusion.values())
{
- try
- {
- ports.add(Integer.parseInt(portStr[i]));
- }
- catch (NumberFormatException e)
- {
- throw new InitException("Invalid port: " + portStr[i], e);
- }
+ parsePortArray(options, commandLine.getOptionValues(pe.getExcludeName()), pe);
}
}
- }
- private void parsePortList(Set<Integer> output, List input)
- throws InitException
- {
- if(input != null)
+ String[] sslPortStr = commandLine.getOptionValues(OPTION_SSLPORT.getOpt());
+ if(sslPortStr != null)
{
- for(Object port : input)
+ parsePortArray(options, sslPortStr, true);
+ for(ProtocolExclusion pe : ProtocolExclusion.values())
{
- try
- {
- output.add(Integer.parseInt(String.valueOf(port)));
- }
- catch (NumberFormatException e)
- {
- throw new InitException("Invalid port: " + port, e);
- }
- }
- }
- }
-
- /**
- * Update the configuration data with the management port.
- * @param configuration
- * @param managementPort The string from the command line
- */
- private void updateManagementPort(ServerConfiguration configuration, String managementPort)
- {
- if (managementPort != null)
- {
- try
- {
- configuration.setJMXManagementPort(Integer.parseInt(managementPort));
- }
- catch (NumberFormatException e)
- {
- _logger.warn("Invalid management port: " + managementPort + " will use:" + configuration.getJMXManagementPort(), e);
+ parsePortArray(options, commandLine.getOptionValues(pe.getExcludeName()), pe);
}
}
+
+ startBroker(options);
}
- public static void main(String[] args)
+ protected void startBroker(final BrokerOptions options) throws Exception
{
- //if the -Dlog4j.configuration property has not been set, enable the init override
- //to stop Log4J wondering off and picking up the first log4j.xml/properties file it
- //finds from the classpath when we get the first Loggers
- if(System.getProperty("log4j.configuration") == null)
- {
- System.setProperty("log4j.defaultInitOverride", "true");
- }
-
- //now that the override status is know, we can instantiate the Loggers
- _logger = Logger.getLogger(Main.class);
-
- new Main(args);
+ Broker broker = new Broker();
+ broker.startup(options);
}
- private byte[] parseIP(String address) throws Exception
+ protected void shutdown(final int status)
{
- char[] literalBuffer = address.toCharArray();
- int byteCount = 0;
- int currByte = 0;
- byte[] ip = new byte[IPV4_ADDRESS_LENGTH];
- for (int i = 0; i < literalBuffer.length; i++)
- {
- char currChar = literalBuffer[i];
- if ((currChar >= '0') && (currChar <= '9'))
- {
- currByte = (currByte * 10) + (Character.digit(currChar, 10) & 0xFF);
- }
-
- if (currChar == IPV4_LITERAL_SEPARATOR || (i + 1 == literalBuffer.length))
- {
- ip[byteCount++] = (byte) currByte;
- currByte = 0;
- }
- }
-
- if (byteCount != 4)
- {
- throw new Exception("Invalid IP address: " + address);
- }
- return ip;
+ ApplicationRegistry.remove();
+ System.exit(status);
}
- private void configureLogging(File logConfigFile, int logWatchTime) throws InitException, IOException
+ private static void parsePortArray(final BrokerOptions options,final Object[] ports,
+ final boolean ssl) throws InitException
{
- if (logConfigFile.exists() && logConfigFile.canRead())
+ if(ports != null)
{
- CurrentActor.get().message(BrokerMessages.LOG_CONFIG(logConfigFile.getAbsolutePath()));
-
- if (logWatchTime > 0)
+ for(int i = 0; i < ports.length; i++)
{
- System.out.println("log file " + logConfigFile.getAbsolutePath() + " will be checked for changes every "
- + logWatchTime + " seconds");
- // log4j expects the watch interval in milliseconds
try
{
- QpidLog4JConfigurator.configureAndWatch(logConfigFile.getPath(), logWatchTime * 1000);
- }
- catch (Exception e)
- {
- throw new InitException(e.getMessage(),e);
- }
- }
- else
- {
- try
- {
- QpidLog4JConfigurator.configure(logConfigFile.getPath());
+ if(ssl)
+ {
+ options.addSSLPort(Integer.parseInt(String.valueOf(ports[i])));
+ }
+ else
+ {
+ options.addPort(Integer.parseInt(String.valueOf(ports[i])));
+ }
}
- catch (Exception e)
+ catch (NumberFormatException e)
{
- throw new InitException(e.getMessage(),e);
+ throw new InitException("Invalid port: " + ports[i], e);
}
}
}
- else
- {
- System.err.println("Logging configuration error: unable to read file " + logConfigFile.getAbsolutePath());
- System.err.println("Using the fallback internal log4j.properties configuration");
+ }
- InputStream propsFile = this.getClass().getResourceAsStream("/log4j.properties");
- if(propsFile == null)
- {
- throw new IOException("Unable to load the fallback internal log4j.properties configuration file");
- }
- else
+ private static void parsePortArray(final BrokerOptions options, final Object[] ports,
+ final ProtocolExclusion excludedProtocol) throws InitException
+ {
+ if(ports != null)
+ {
+ for(int i = 0; i < ports.length; i++)
{
try
{
- Properties fallbackProps = new Properties();
- fallbackProps.load(propsFile);
- PropertyConfigurator.configure(fallbackProps);
+ options.addExcludedPort(excludedProtocol,
+ Integer.parseInt(String.valueOf(ports[i])));
}
- finally
+ catch (NumberFormatException e)
{
- propsFile.close();
+ throw new InitException("Invalid port for exclusion: " + ports[i], e);
}
}
}
}
-
- private void configureLoggingManagementMBean(File logConfigFile, int logWatchTime) throws Exception
- {
- LoggingManagementMBean blm = new LoggingManagementMBean(logConfigFile.getPath(),logWatchTime);
-
- blm.register();
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java b/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java
new file mode 100644
index 0000000000..22d97d36dd
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/ProtocolExclusion.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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 ProtocolExclusion
+{
+ v0_8("exclude-0-8","--exclude-0-8"),
+ v0_9("exclude-0-9", "--exclude-0-9"),
+ v0_9_1("exclude-0-9-1", "--exclude-0-9-1"),
+ v0_10("exclude-0-10", "--exclude-0-10");
+
+ private static final Map<String, ProtocolExclusion> MAP = new HashMap<String,ProtocolExclusion>();
+
+ static
+ {
+ for(ProtocolExclusion pe : ProtocolExclusion.values())
+ {
+ MAP.put(pe.getArg(), pe);
+ }
+ }
+
+ private String _arg;
+ private String _excludeName;
+
+ private ProtocolExclusion(final String excludeName, final String arg)
+ {
+ _excludeName = excludeName;
+ _arg = arg;
+ }
+
+ public String getArg()
+ {
+ return _arg;
+ }
+
+ public String getExcludeName()
+ {
+ return _excludeName;
+ }
+
+ public static ProtocolExclusion lookup(final String arg)
+ {
+ ProtocolExclusion ex = MAP.get(arg);
+
+ if(ex == null)
+ {
+ throw new IllegalArgumentException(arg + " is not a valid protocol exclusion");
+ }
+
+ return ex;
+ }
+}
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 7197ec8cdc..70fa39c71d 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,8 @@
package org.apache.qpid.server.configuration;
+import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS;
+
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
@@ -37,33 +39,28 @@ 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.management.ConfigurationManagementMBean;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.signal.SignalHandlerTask;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.qpid.transport.NetworkDriverConfiguration;
-
-import sun.misc.Signal;
-import sun.misc.SignalHandler;
-public class ServerConfiguration extends ConfigurationPlugin implements SignalHandler
+public class ServerConfiguration extends ConfigurationPlugin
{
protected static final Logger _logger = Logger.getLogger(ServerConfiguration.class);
// Default Configuration values
- public static final int DEFAULT_BUFFER_READ_LIMIT_SIZE = 262144;
- public static final int DEFAULT_BUFFER_WRITE_LIMIT_SIZE = 262144;
- public static final boolean DEFAULT_BROKER_CONNECTOR_PROTECTIO_ENABLED = false;
+ public static final int DEFAULT_BUFFER_SIZE = 262144;
public static final String DEFAULT_STATUS_UPDATES = "on";
public static final String SECURITY_CONFIG_RELOADED = "SECURITY CONFIGURATION RELOADED";
public static final int DEFAULT_FRAME_SIZE = 65536;
public static final int DEFAULT_PORT = 5672;
- public static final int DEFAULT_SSL_PORT = 8672;
+ public static final int DEFAULT_SSL_PORT = 5671;
public static final long DEFAULT_HOUSEKEEPING_PERIOD = 30000L;
- public static final int DEFAULT_JMXPORT = 8999;
-
+ public static final int DEFAULT_JMXPORT_REGISTRYSERVER = 8999;
+ public static final int JMXPORT_CONNECTORSERVER_OFFSET = 100;
+
public static final String QPID_HOME = "QPID_HOME";
public static final String QPID_WORK = "QPID_WORK";
public static final String LIB_DIR = "lib";
@@ -75,19 +72,14 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
private File _configFile;
private File _vhostsFile;
- private Logger _log = Logger.getLogger(this.getClass());
-
- private ConfigurationManagementMBean _mbean;
-
// Map of environment variables to config items
private static final Map<String, String> envVarMap = new HashMap<String, String>();
// Configuration values to be read from the configuration file
//todo Move all properties to static values to ensure system testing can be performed.
- public static final String CONNECTOR_PROTECTIO_ENABLED = "connector.protectio.enabled";
- public static final String CONNECTOR_PROTECTIO_READ_BUFFER_LIMIT_SIZE = "connector.protectio.readBufferLimitSize";
- public static final String CONNECTOR_PROTECTIO_WRITE_BUFFER_LIMIT_SIZE = "connector.protectio.writeBufferLimitSize";
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 STATUS_UPDATES = "status-updates";
public static final String ADVANCED_LOCALE = "advanced.locale";
@@ -95,9 +87,9 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
envVarMap.put("QPID_PORT", "connector.port");
envVarMap.put("QPID_ENABLEDIRECTBUFFERS", "advanced.enableDirectBuffers");
envVarMap.put("QPID_SSLPORT", "connector.ssl.port");
- envVarMap.put("QPID_NIO", "connector.qpidnio");
envVarMap.put("QPID_WRITEBIASED", "advanced.useWriteBiasedPool");
- envVarMap.put("QPID_JMXPORT", "management.jmxport");
+ envVarMap.put("QPID_JMXPORT_REGISTRYSERVER", MGMT_JMXPORT_REGISTRYSERVER);
+ envVarMap.put("QPID_JMXPORT_CONNECTORSERVER", MGMT_JMXPORT_CONNECTORSERVER);
envVarMap.put("QPID_FRAMESIZE", "advanced.framesize");
envVarMap.put("QPID_MSGAUTH", "security.msg-auth");
envVarMap.put("QPID_AUTOREGISTER", "auto_register");
@@ -131,7 +123,7 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
* Configuration Manager to be initialised in the Application Registry.
* <p>
* If using this ServerConfiguration via an ApplicationRegistry there is no
- * need to explictly call {@link #initialise()} as this is done via the
+ * need to explicitly call {@link #initialise()} as this is done via the
* {@link ApplicationRegistry#initialise()} method.
*
* @param configurationURL
@@ -141,15 +133,26 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
{
this(parseConfig(configurationURL));
_configFile = configurationURL;
- try
+
+ SignalHandlerTask hupReparseTask = new SignalHandlerTask()
{
- Signal sig = new sun.misc.Signal("HUP");
- sun.misc.Signal.handle(sig, this);
- }
- catch (Exception e)
+ public void handle()
+ {
+ try
+ {
+ reparseConfigFileSecuritySections();
+ }
+ catch (ConfigurationException e)
+ {
+ _logger.error("Could not reload configuration file security sections", e);
+ }
+ }
+ };
+
+ if(!hupReparseTask.register("HUP"))
{
- _logger.error("Signal HUP not supported for OS: " + System.getProperty("os.name"));
- // We're on something that doesn't handle SIGHUP, how sad, Windows.
+ _logger.info("Unable to register Signal HUP handler to reload security configuration.");
+ _logger.info("Signal HUP not supported for this OS / JVM combination - " + SignalHandlerTask.getPlatformDescription());
}
}
@@ -166,7 +169,7 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
* Configuration Manager to be initialised in the Application Registry.
* <p>
* If using this ServerConfiguration via an ApplicationRegistry there is no
- * need to explictly call {@link #initialise()} as this is done via the
+ * need to explicitly call {@link #initialise()} as this is done via the
* {@link ApplicationRegistry#initialise()} method.
*
* @param conf
@@ -205,7 +208,53 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
@Override
public void validateConfiguration() throws ConfigurationException
{
- //Currently doesn't do validation
+ // 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."
+ + (_configFile == null ? "" : " Configuration file : " + _configFile);
+ throw new ConfigurationException(message);
+ }
+
+ if (getListValue("security.jmx.principal-database").size() > 0)
+ {
+ String message = "Validation error : security/jmx/principal-database is no longer a supported element within the configuration xml."
+ + (_configFile == null ? "" : " Configuration file : " + _configFile);
+ throw new ConfigurationException(message);
+ }
+
+ 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."
+ + (_configFile == null ? "" : " Configuration file : " + _configFile);
+ throw new ConfigurationException(message);
+ }
+
+ // QPID-3266. Tidy up housekeeping configuration option for scheduling frequency
+ if (contains("housekeeping.expiredMessageCheckPeriod"))
+ {
+ String message = "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod."
+ + (_configFile == null ? "" : " Configuration file : " + _configFile);
+ throw new ConfigurationException(message);
+ }
+
+ // 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",
+ "management.ssl.keystorePassword," +
+ "connector.ssl.keystorePath",
+ "connector.ssl.keystorePassword"})
+ {
+ if (contains(key))
+ {
+ final String deprecatedXpath = key.replaceAll("\\.", "/");
+ final String preferredXpath = deprecatedXpath.replaceAll("keystore", "keyStore");
+ _logger.warn("Validation warning: " + deprecatedXpath + " is deprecated and must be replaced by " + preferredXpath
+ + (_configFile == null ? "" : " Configuration file : " + _configFile));
+ }
+ }
}
/*
@@ -371,7 +420,7 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
public final static Configuration flatConfig(File file) throws ConfigurationException
{
// We have to override the interpolate methods so that
- // interpolation takes place accross the entirety of the
+ // interpolation takes place across the entirety of the
// composite configuration. Without doing this each
// configuration object only interpolates variables defined
// inside itself.
@@ -398,18 +447,6 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
return _configFile == null ? "" : _configFile.getAbsolutePath();
}
- public void handle(Signal arg0)
- {
- try
- {
- reparseConfigFileSecuritySections();
- }
- catch (ConfigurationException e)
- {
- _logger.error("Could not reload configuration file security sections", e);
- }
- }
-
public void reparseConfigFileSecuritySections() throws ConfigurationException
{
if (_configFile != null)
@@ -453,14 +490,24 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
return System.getProperty(QPID_HOME);
}
- public void setJMXManagementPort(int mport)
+ public void setJMXPortRegistryServer(int registryServerPort)
+ {
+ getConfig().setProperty(MGMT_JMXPORT_REGISTRYSERVER, registryServerPort);
+ }
+
+ public int getJMXPortRegistryServer()
{
- getConfig().setProperty("management.jmxport", mport);
+ return getIntValue(MGMT_JMXPORT_REGISTRYSERVER, DEFAULT_JMXPORT_REGISTRYSERVER);
}
- public int getJMXManagementPort()
+ public void setJMXPortConnectorServer(int connectorServerPort)
{
- return getIntValue("management.jmxport", DEFAULT_JMXPORT);
+ getConfig().setProperty(MGMT_JMXPORT_CONNECTORSERVER, connectorServerPort);
+ }
+
+ public int getJMXConnectorServerPort()
+ {
+ return getIntValue(MGMT_JMXPORT_CONNECTORSERVER, getJMXPortRegistryServer() + JMXPORT_CONNECTORSERVER_OFFSET);
}
public boolean getUseCustomRMISocketFactory()
@@ -503,58 +550,11 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
_virtualHosts.put(config.getName(), config);
}
- public List<String> getPrincipalDatabaseNames()
- {
- return getListValue("security.principal-databases.principal-database.name");
- }
-
- public List<String> getPrincipalDatabaseClass()
- {
- return getListValue("security.principal-databases.principal-database.class");
- }
-
- public List<String> getPrincipalDatabaseAttributeNames(int index)
- {
- String name = "security.principal-databases.principal-database(" + index + ")." + "attributes.attribute.name";
- return getListValue(name);
- }
-
- public List<String> getPrincipalDatabaseAttributeValues(int index)
- {
- String name = "security.principal-databases.principal-database(" + index + ")." + "attributes.attribute.value";
- return getListValue(name);
- }
-
- public List<String> getManagementPrincipalDBs()
- {
- return getListValue("security.jmx.principal-database");
- }
-
- public List<String> getManagementAccessList()
- {
- return getListValue("security.jmx.access");
- }
-
public int getFrameSize()
{
return getIntValue("advanced.framesize", DEFAULT_FRAME_SIZE);
}
- public boolean getProtectIOEnabled()
- {
- return getBooleanValue(CONNECTOR_PROTECTIO_ENABLED, DEFAULT_BROKER_CONNECTOR_PROTECTIO_ENABLED);
- }
-
- public int getBufferReadLimit()
- {
- return getIntValue(CONNECTOR_PROTECTIO_READ_BUFFER_LIMIT_SIZE, DEFAULT_BUFFER_READ_LIMIT_SIZE);
- }
-
- public int getBufferWriteLimit()
- {
- return getIntValue(CONNECTOR_PROTECTIO_WRITE_BUFFER_LIMIT_SIZE, DEFAULT_BUFFER_WRITE_LIMIT_SIZE);
- }
-
public boolean getSynchedClocks()
{
return getBooleanValue("advanced.synced-clocks");
@@ -565,14 +565,10 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
return getBooleanValue("security.msg-auth");
}
- public String getJMXPrincipalDatabase()
- {
- return getStringValue("security.jmx.principal-database");
- }
-
public String getManagementKeyStorePath()
{
- return getStringValue("management.ssl.keyStorePath");
+ final String fallback = getStringValue("management.ssl.keystorePath");
+ return getStringValue("management.ssl.keyStorePath", fallback);
}
public boolean getManagementSSLEnabled()
@@ -582,7 +578,8 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
public String getManagementKeyStorePassword()
{
- return getStringValue("management.ssl.keyStorePassword");
+ final String fallback = getStringValue("management.ssl.keystorePassword");
+ return getStringValue("management.ssl.keyStorePassword", fallback);
}
public boolean getQueueAutoRegister()
@@ -650,14 +647,14 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
return getLongValue("flowResumeCapacity", getCapacity());
}
- public int getProcessors()
+ public int getConnectorProcessors()
{
return getIntValue("connector.processors", 4);
}
public List getPorts()
{
- return getListValue("connector.port", Collections.singletonList(DEFAULT_PORT));
+ return getListValue("connector.port", Collections.<Integer>singletonList(DEFAULT_PORT));
}
public List getPortExclude010()
@@ -682,17 +679,17 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
public String getBind()
{
- return getStringValue("connector.bind", "wildcard");
+ return getStringValue("connector.bind", WILDCARD_ADDRESS);
}
public int getReceiveBufferSize()
{
- return getIntValue("connector.socketReceiveBuffer", 32767);
+ return getIntValue("connector.socketReceiveBuffer", DEFAULT_BUFFER_SIZE);
}
public int getWriteBufferSize()
{
- return getIntValue("connector.socketWriteBuffer", 32767);
+ return getIntValue("connector.socketWriteBuffer", DEFAULT_BUFFER_SIZE);
}
public boolean getTcpNoDelay()
@@ -715,31 +712,28 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
return getBooleanValue("connector.ssl.sslOnly");
}
- public int getSSLPort()
+ public List getSSLPorts()
{
- return getIntValue("connector.ssl.port", DEFAULT_SSL_PORT);
+ return getListValue("connector.ssl.port", Collections.<Integer>singletonList(DEFAULT_SSL_PORT));
}
- public String getKeystorePath()
+ public String getConnectorKeyStorePath()
{
- return getStringValue("connector.ssl.keystorePath", "none");
+ final String fallback = getStringValue("connector.ssl.keystorePath"); // pre-0.13 broker supported this name.
+ return getStringValue("connector.ssl.keyStorePath", fallback);
}
- public String getKeystorePassword()
+ public String getConnectorKeyStorePassword()
{
- return getStringValue("connector.ssl.keystorePassword", "none");
+ final String fallback = getStringValue("connector.ssl.keystorePassword"); // pre-0.13 brokers supported this name.
+ return getStringValue("connector.ssl.keyStorePassword", fallback);
}
- public String getCertType()
+ public String getConnectorCertType()
{
return getStringValue("connector.ssl.certType", "SunX509");
}
- public boolean getQpidNIO()
- {
- return getBooleanValue("connector.qpidnio");
- }
-
public boolean getUseBiasedWrites()
{
return getBooleanValue("advanced.useWriteBiasedPool");
@@ -755,69 +749,44 @@ public class ServerConfiguration extends ConfigurationPlugin implements SignalHa
getConfig().setProperty("virtualhosts.default", vhost);
}
- public void setHousekeepingExpiredMessageCheckPeriod(long value)
+ public void setHousekeepingCheckPeriod(long value)
{
- getConfig().setProperty("housekeeping.expiredMessageCheckPeriod", value);
+ getConfig().setProperty("housekeeping.checkPeriod", value);
}
public long getHousekeepingCheckPeriod()
{
- return getLongValue("housekeeping.checkPeriod",
- getLongValue("housekeeping.expiredMessageCheckPeriod",
- DEFAULT_HOUSEKEEPING_PERIOD));
+ return getLongValue("housekeeping.checkPeriod", DEFAULT_HOUSEKEEPING_PERIOD);
}
- public NetworkDriverConfiguration getNetworkConfiguration()
+ public long getStatisticsSamplePeriod()
{
- return new NetworkDriverConfiguration()
- {
-
- public Integer getTrafficClass()
- {
- return null;
- }
-
- public Boolean getTcpNoDelay()
- {
- // Can't call parent getTcpNoDelay since it just calls this one
- return getBooleanValue("connector.tcpNoDelay", true);
- }
-
- public Integer getSoTimeout()
- {
- return null;
- }
-
- public Integer getSoLinger()
- {
- return null;
- }
+ return getConfig().getLong("statistics.sample.period", 5000L);
+ }
- public Integer getSendBufferSize()
- {
- return getBufferWriteLimit();
- }
+ public boolean isStatisticsGenerationBrokerEnabled()
+ {
+ return getConfig().getBoolean("statistics.generation.broker", false);
+ }
- public Boolean getReuseAddress()
- {
- return null;
- }
+ public boolean isStatisticsGenerationVirtualhostsEnabled()
+ {
+ return getConfig().getBoolean("statistics.generation.virtualhosts", false);
+ }
- public Integer getReceiveBufferSize()
- {
- return getBufferReadLimit();
- }
+ public boolean isStatisticsGenerationConnectionsEnabled()
+ {
+ return getConfig().getBoolean("statistics.generation.connections", false);
+ }
- public Boolean getOOBInline()
- {
- return null;
- }
+ public long getStatisticsReportingPeriod()
+ {
+ return getConfig().getLong("statistics.reporting.period", 0L);
+ }
- public Boolean getKeepAlive()
- {
- return null;
- }
- };
+ public boolean isStatisticsReportResetEnabled()
+ {
+ return getConfig().getBoolean("statistics.reporting.reset", false);
}
public int getMaxChannelCount()
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
new file mode 100644
index 0000000000..81dfcb4465
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/ServerNetworkTransportConfiguration.java
@@ -0,0 +1,75 @@
+/*
+ * 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;
+
+import org.apache.qpid.transport.NetworkTransportConfiguration;
+
+public class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration
+{
+ private final ServerConfiguration _serverConfig;
+ private final int _port;
+ private final String _host;
+ private final String _transport;
+
+ public ServerNetworkTransportConfiguration(final ServerConfiguration serverConfig,
+ final int port, final String host,
+ final String transport)
+ {
+ _serverConfig = serverConfig;
+ _port = port;
+ _host = host;
+ _transport = transport;
+ }
+
+ public Boolean getTcpNoDelay()
+ {
+ return _serverConfig.getTcpNoDelay();
+ }
+
+ public Integer getSendBufferSize()
+ {
+ return _serverConfig.getWriteBufferSize();
+ }
+
+ public Integer getReceiveBufferSize()
+ {
+ return _serverConfig.getReceiveBufferSize();
+ }
+
+ public Integer getPort()
+ {
+ return _port;
+ }
+
+ public String getHost()
+ {
+ return _host;
+ }
+
+ public String getTransport()
+ {
+ return _transport;
+ }
+
+ public Integer getConnectorProcessors()
+ {
+ return _serverConfig.getConnectorProcessors();
+ }
+}
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 d9d7083543..6729a5ce0f 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
@@ -86,9 +86,9 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
return _name;
}
- public long getHousekeepingExpiredMessageCheckPeriod()
+ public long getHousekeepingCheckPeriod()
{
- return getLongValue("housekeeping.expiredMessageCheckPeriod", ApplicationRegistry.getInstance().getConfiguration().getHousekeepingCheckPeriod());
+ return getLongValue("housekeeping.checkPeriod", ApplicationRegistry.getInstance().getConfiguration().getHousekeepingCheckPeriod());
}
public String getAuthenticationDatabase()
@@ -306,11 +306,45 @@ public class VirtualHostConfiguration extends ConfigurationPlugin
@Override
public void validateConfiguration() throws ConfigurationException
{
- //Currently doesn't do validation
+ // QPID-3249. Support for specifying authentication name at vhost level is no longer supported.
+ if (getListValue("security.authentication.name").size() > 0)
+ {
+ String message = "Validation error : security/authentication/name is no longer a supported element within the configuration xml."
+ + " It appears in virtual host definition : " + _name;
+ throw new ConfigurationException(message);
+ }
+
+ // QPID-3266. Tidy up housekeeping configuration option for scheduling frequency
+ if (contains("housekeeping.expiredMessageCheckPeriod"))
+ {
+ String message = "Validation error : housekeeping/expiredMessageCheckPeriod must be replaced by housekeeping/checkPeriod."
+ + " It appears in virtual host definition : " + _name;
+ throw new ConfigurationException(message);
+ }
}
public int getHouseKeepingThreadCount()
{
return getIntValue("housekeeping.poolSize", Runtime.getRuntime().availableProcessors());
}
+
+ public long getTransactionTimeoutOpenWarn()
+ {
+ return getLongValue("transactionTimeout.openWarn", 0L);
+ }
+
+ public long getTransactionTimeoutOpenClose()
+ {
+ return getLongValue("transactionTimeout.openClose", 0L);
+ }
+
+ public long getTransactionTimeoutIdleWarn()
+ {
+ return getLongValue("transactionTimeout.idleWarn", 0L);
+ }
+
+ public long getTransactionTimeoutIdleClose()
+ {
+ return getLongValue("transactionTimeout.idleClose", 0L);
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java
index 82b576ea51..b4f82649b0 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/configuration/plugins/ConfigurationPlugin.java
@@ -24,6 +24,7 @@ import org.apache.commons.configuration.ConversionException;
import org.apache.log4j.Logger;
import org.apache.qpid.server.configuration.ConfigurationManager;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
import java.util.Collections;
import java.util.HashMap;
@@ -138,10 +139,28 @@ public abstract class ConfigurationPlugin
}
}
+ offerRemainingConfigurationToOtherPlugins(path, configuration, elements);
+
+ validateConfiguration();
+ }
+
+ private void offerRemainingConfigurationToOtherPlugins(String path,
+ Configuration configuration, Set<String> elements) throws ConfigurationException
+ {
+ final IApplicationRegistry appRegistry = safeGetApplicationRegistryInstance();
+
+ if (appRegistry == null)
+ {
+ // We see this happen during shutdown due to asynchronous reconfig using IO threads.
+ // Need to remove the responsibility for offering configuration to other class.
+ _logger.info("Cannot offer remaining config to other plugins, can't find app registry");
+ return;
+ }
+
+ final ConfigurationManager configurationManager = appRegistry.getConfigurationManager();
// Process the elements in the configuration
for (String element : elements)
{
- ConfigurationManager configurationManager = ApplicationRegistry.getInstance().getConfigurationManager();
Configuration handled = element.length() == 0 ? configuration : configuration.subset(element);
String configurationElement = element;
@@ -162,8 +181,18 @@ public abstract class ConfigurationPlugin
_pluginConfiguration.put(plugin.getClass().getName(), plugin);
}
}
+ }
- validateConfiguration();
+ private IApplicationRegistry safeGetApplicationRegistryInstance()
+ {
+ try
+ {
+ return ApplicationRegistry.getInstance();
+ }
+ catch (IllegalStateException ise)
+ {
+ return null;
+ }
}
/** Helper method to print out list of keys in a {@link Configuration}. */
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 bac751e0c8..1c01ce465d 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
@@ -20,19 +20,21 @@
*/
package org.apache.qpid.server.connection;
+import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.apache.log4j.Logger;
-import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
import org.apache.qpid.common.Closeable;
import org.apache.qpid.protocol.AMQConstant;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
+import org.apache.qpid.server.protocol.AMQProtocolEngine;
+import org.apache.qpid.transport.TransportException;
public class ConnectionRegistry implements IConnectionRegistry, Closeable
{
- private List<AMQProtocolSession> _registry = new CopyOnWriteArrayList<AMQProtocolSession>();
+ private List<AMQConnectionModel> _registry = new CopyOnWriteArrayList<AMQConnectionModel>();
private Logger _logger = Logger.getLogger(ConnectionRegistry.class);
@@ -40,44 +42,46 @@ public class ConnectionRegistry implements IConnectionRegistry, Closeable
{
// None required
}
-
- public void expireClosedChannels()
- {
- for (AMQProtocolSession connection : _registry)
- {
- connection.closeIfLingeringClosedChannels();
- }
- }
/** Close all of the currently open connections. */
public void close()
{
+ _logger.debug("Closing connection registry :" + _registry.size() + " connections.");
while (!_registry.isEmpty())
{
- AMQProtocolSession connection = _registry.get(0);
+ AMQConnectionModel connection = _registry.get(0);
+ closeConnection(connection, AMQConstant.CONNECTION_FORCED, "Broker is shutting down");
+ }
+ }
- try
- {
- connection.closeConnection(0, new AMQConnectionException(AMQConstant.INTERNAL_ERROR, "Broker is shutting down",
- 0, 0,
- connection.getProtocolOutputConverter().getProtocolMajorVersion(),
- connection.getProtocolOutputConverter().getProtocolMinorVersion(),
- (Throwable) null), true);
- }
- catch (AMQException e)
- {
- _logger.warn("Error closing connection:" + e.getMessage());
- }
+ public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message)
+ {
+ try
+ {
+ connection.close(cause, message);
+ }
+ catch (TransportException e)
+ {
+ _logger.warn("Error closing connection:" + e.getMessage());
+ }
+ catch (AMQException e)
+ {
+ _logger.warn("Error closing connection:" + e.getMessage());
}
}
- public void registerConnection(AMQProtocolSession connnection)
+ public void registerConnection(AMQConnectionModel connnection)
{
_registry.add(connnection);
}
- public void deregisterConnection(AMQProtocolSession connnection)
+ public void deregisterConnection(AMQConnectionModel connnection)
{
_registry.remove(connnection);
}
+
+ public List<AMQConnectionModel> getConnections()
+ {
+ 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 002269bbaa..b4f5bffa57 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
@@ -20,18 +20,23 @@
*/
package org.apache.qpid.server.connection;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
+import java.util.List;
+
import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.protocol.AMQConnectionModel;
public interface IConnectionRegistry
{
-
public void initialise();
public void close() throws AMQException;
+
+ public void closeConnection(AMQConnectionModel connection, AMQConstant cause, String message);
+
+ public List<AMQConnectionModel> getConnections();
- public void registerConnection(AMQProtocolSession connnection);
-
- public void deregisterConnection(AMQProtocolSession connnection);
+ public void registerConnection(AMQConnectionModel connnection);
+ public void deregisterConnection(AMQConnectionModel connnection);
}
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 d0231e4d80..d693c6962b 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
@@ -356,7 +356,7 @@ public abstract class AbstractExchange implements Exchange, Managable
_receivedMessageCount.incrementAndGet();
_receivedMessageSize.addAndGet(message.getSize());
final ArrayList<? extends BaseQueue> queues = doRoute(message);
- if(queues != null && !queues.isEmpty())
+ if(!queues.isEmpty())
{
_routedMessageCount.incrementAndGet();
_routedMessageSize.addAndGet(message.getSize());
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
index 7aeff2561e..0f1b709475 100644
--- 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
@@ -90,12 +90,12 @@ public abstract class AbstractExchangeMBean<T extends AbstractExchange> extends
public String getObjectInstanceName()
{
- return _exchange.getNameShortString().toString();
+ return ObjectName.quote(_exchange.getName());
}
public String getName()
{
- return _exchange.getNameShortString().toString();
+ return _exchange.getName();
}
public String getExchangeType()
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 356a7f89b9..29a3611709 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
@@ -30,15 +30,12 @@ import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.message.InboundMessage;
-import org.apache.qpid.server.binding.BindingFactory;
import org.apache.qpid.server.binding.Binding;
import org.apache.qpid.server.configuration.ExchangeConfig;
import javax.management.JMException;
import java.util.ArrayList;
-import java.util.List;
import java.util.Collection;
-import java.util.concurrent.CopyOnWriteArrayList;
public interface Exchange extends ExchangeReferrer, ExchangeConfig
{
@@ -67,7 +64,12 @@ public interface Exchange extends ExchangeReferrer, ExchangeConfig
void close() throws AMQException;
-
+ /**
+ * Returns a list of queues to which to route this message. If there are
+ * no queues the empty list must be returned.
+ *
+ * @return list of queues to which to route the message.
+ */
ArrayList<? extends BaseQueue> route(InboundMessage message);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
index 0e3a3894fe..d76b163fa1 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/headers/HeadersParser.java
@@ -274,132 +274,6 @@ public class HeadersParser
}
- public static void main(String[] args) throws AMQFrameDecodingException
- {
-
- FieldTable bindingTable = new FieldTable();
-
- bindingTable.setString(new AMQShortString("x-match"),"all");
- bindingTable.setInteger("a",1);
- bindingTable.setVoid(new AMQShortString("b"));
- bindingTable.setString("c","");
- bindingTable.setInteger("d",4);
- bindingTable.setInteger("e",1);
-
-
-
- FieldTable bindingTable2 = new FieldTable();
- bindingTable2.setString(new AMQShortString("x-match"),"all");
- bindingTable2.setInteger("a",1);
- bindingTable2.setVoid(new AMQShortString("b"));
- bindingTable2.setString("c","");
- bindingTable2.setInteger("d",4);
- bindingTable2.setInteger("e",1);
- bindingTable2.setInteger("f",1);
-
-
- FieldTable table = new FieldTable();
- table.setInteger("a",1);
- table.setInteger("b",2);
- table.setString("c","");
- table.setInteger("d",4);
- table.setInteger("e",1);
- table.setInteger("f",1);
- table.setInteger("h",1);
- table.setInteger("i",1);
- table.setInteger("j",1);
- table.setInteger("k",1);
- table.setInteger("l",1);
-
- org.apache.mina.common.ByteBuffer buffer = org.apache.mina.common.ByteBuffer.allocate( (int) table.getEncodedSize());
- EncodingUtils.writeFieldTableBytes(buffer, table);
- buffer.flip();
-
- FieldTable table2 = EncodingUtils.readFieldTable(buffer);
-
-
-
- FieldTable bindingTable3 = new FieldTable();
- bindingTable3.setString(new AMQShortString("x-match"),"any");
- bindingTable3.setInteger("a",1);
- bindingTable3.setInteger("b",3);
-
-
- FieldTable bindingTable4 = new FieldTable();
- bindingTable4.setString(new AMQShortString("x-match"),"any");
- bindingTable4.setVoid(new AMQShortString("a"));
-
-
- FieldTable bindingTable5 = new FieldTable();
- bindingTable5.setString(new AMQShortString("x-match"),"all");
- bindingTable5.setString(new AMQShortString("h"),"hello");
-
- for(int i = 0; i < 100; i++)
- {
- printMatches(new FieldTable[] {bindingTable5} , table2);
- }
-
-
-
- }
-
-
-
- private static void printMatches(final FieldTable[] bindingKeys, final FieldTable routingKey)
- {
- HeadersMatcherDFAState sm = null;
- Map<HeaderMatcherResult, String> resultMap = new HashMap<HeaderMatcherResult, String>();
-
- HeadersParser parser = new HeadersParser();
-
- for(int i = 0; i < bindingKeys.length; i++)
- {
- HeaderMatcherResult r = new HeaderMatcherResult();
- resultMap.put(r, bindingKeys[i].toString());
-
-
- if(i==0)
- {
- sm = parser.createStateMachine(bindingKeys[i], r);
- }
- else
- {
- sm = sm.mergeStateMachines(parser.createStateMachine(bindingKeys[i], r));
- }
- }
-
- Collection<HeaderMatcherResult> results = null;
- long beforeTime = System.currentTimeMillis();
- for(int i = 0; i < 1000000; i++)
- {
- routingKey.size();
-
- assert sm != null;
- results = sm.match(routingKey);
-
- }
- long elapsed = System.currentTimeMillis() - beforeTime;
- System.out.println("1000000 Iterations took: " + elapsed);
- Collection<String> resultStrings = new ArrayList<String>();
-
- assert results != null;
- for(HeaderMatcherResult result : results)
- {
- resultStrings.add(resultMap.get(result));
- }
-
- final ArrayList<String> nonMatches = new ArrayList<String>();
- for(FieldTable key : bindingKeys)
- {
- nonMatches.add(key.toString());
- }
- nonMatches.removeAll(resultStrings);
- System.out.println("\""+routingKey+"\" matched with " + resultStrings + " DID NOT MATCH with " + nonMatches);
-
-
- }
-
-
public final static class KeyValuePair
{
public final HeaderKey _key;
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 fbc5387daf..2dff45c326 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
@@ -38,6 +38,7 @@ import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.transport.ServerSession;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -696,7 +697,7 @@ public class Bridge implements BridgeConfig
//TODO Handle the passing of non-null Filters and Arguments here
- Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
+ Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session,
_destination,
MessageAcceptMode.NONE,
MessageAcquireMode.PRE_ACQUIRED,
@@ -768,7 +769,7 @@ public class Bridge implements BridgeConfig
//TODO Handle the passing of non-null Filters and Arguments here
- Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
+ Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session,
_destination,
MessageAcceptMode.NONE,
MessageAcquireMode.PRE_ACQUIRED,
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 fa2fb9ead1..f21158cd0c 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
@@ -258,7 +258,6 @@ public class BrokerLink implements LinkConfig, ConnectionListener
_remoteFederationTag = UUID.fromString(_transport+":"+_host+":"+_port).toString();
}
_qpidConnection.setSessionFactory(new SessionFactory());
- _qpidConnection.setAuthorizationID(_username == null ? "" : _username);
updateState(State.ESTABLISHING, State.OPERATIONAL);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java b/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
index 11fdeae2b1..9848f90ea9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/filter/PropertyExpression.java
@@ -37,8 +37,8 @@ import org.apache.qpid.server.queue.Filterable;
public class PropertyExpression implements Expression
{
// Constants - defined the same as JMS
- private static final int NON_PERSISTENT = 1;
- private static final int PERSISTENT = 2;
+ private static enum JMSDeliveryMode { NON_PERSISTENT, PERSISTENT }
+
private static final int DEFAULT_PRIORITY = 4;
private static final Logger _logger = org.apache.log4j.Logger.getLogger(PropertyExpression.class);
@@ -172,13 +172,14 @@ public class PropertyExpression implements Expression
{
public Object evaluate(Filterable message)
{
- int mode = message.isPersistent() ? PERSISTENT : NON_PERSISTENT;
+ JMSDeliveryMode mode = message.isPersistent() ? JMSDeliveryMode.PERSISTENT :
+ JMSDeliveryMode.NON_PERSISTENT;
if (_logger.isDebugEnabled())
{
_logger.debug("JMSDeliveryMode is :" + mode);
}
- return mode;
+ return mode.toString();
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
index a5999711bc..765dee2878 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
@@ -144,7 +144,7 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
_logger.debug("Closing connection due to invalid selector");
MethodRegistry methodRegistry = protocolConnection.getMethodRegistry();
- AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.INVALID_ARGUMENT.getCode(),
+ AMQMethodBody responseBody = methodRegistry.createChannelCloseBody(AMQConstant.ARGUMENT_INVALID.getCode(),
new AMQShortString(ise.getMessage()),
body.getClazz(),
body.getMethod());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
index 790027f293..14ce85530e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicGetMethodHandler.java
@@ -162,14 +162,7 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
}
else
{
- sub = new GetNoAckSubscription(channel,
- session,
- null,
- null,
- false,
- singleMessageCredit,
- getDeliveryMethod,
- getRecordMethod);
+ sub = SubscriptionFactoryImpl.INSTANCE.createBasicGetNoAckSubscription(channel, session, null, null, false, singleMessageCredit, getDeliveryMethod, getRecordMethod);
}
queue.registerSubscription(sub,false);
@@ -180,27 +173,5 @@ public class BasicGetMethodHandler implements StateAwareMethodListener<BasicGetB
}
- public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription
- {
- public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
- AMQShortString consumerTag, FieldTable filters,
- boolean noLocal, FlowCreditManager creditManager,
- ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
- throws AMQException
- {
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
- }
- public boolean isTransient()
- {
- return true;
- }
-
- public boolean wouldSuspend(QueueEntry msg)
- {
- return !getCreditManager().useCreditForMessage(msg.getMessage());
- }
-
- }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java
index dade5d5f54..f8e4eab0b6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ConnectionCloseMethodHandler.java
@@ -68,5 +68,7 @@ public class ConnectionCloseMethodHandler implements StateAwareMethodListener<Co
ConnectionCloseOkBody responseBody = methodRegistry.createConnectionCloseOkBody();
session.writeFrame(responseBody.generateFrame(channelId));
+ session.closeProtocolSession();
+
}
}
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 d4b79134a2..09f35da41d 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
@@ -20,9 +20,9 @@
*/
package org.apache.qpid.server.handler;
+
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
-
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.ConnectionCloseBody;
@@ -68,7 +68,7 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
}
MethodRegistry methodRegistry = session.getMethodRegistry();
AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
- switch (authResult.status)
+ switch (authResult.getStatus())
{
case ERROR:
Exception cause = authResult.getCause();
@@ -88,7 +88,10 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
disposeSaslServer(session);
break;
case SUCCESS:
- _logger.info("Connected as: " + ss.getAuthorizationID());
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
+ }
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
ConnectionTuneBody tuneBody =
@@ -96,13 +99,13 @@ public class ConnectionSecureOkMethodHandler implements StateAwareMethodListener
ConnectionStartOkMethodHandler.getConfiguredFrameSize(),
ApplicationRegistry.getInstance().getConfiguration().getHeartBeatDelay());
session.writeFrame(tuneBody.generateFrame(0));
- session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
+ session.setAuthorizedSubject(authResult.getSubject());
disposeSaslServer(session);
break;
case CONTINUE:
stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
- ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
+ ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
session.writeFrame(secureBody.generateFrame(0));
}
}
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 4442f969c4..2dd9a63540 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
@@ -65,7 +65,6 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
_logger.info("Locale selected: " + body.getLocale());
AuthenticationManager authMgr = ApplicationRegistry.getInstance().getAuthenticationManager();
-
SaslServer ss = null;
try
{
@@ -78,8 +77,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
session.setSaslServer(ss);
- AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
-
+ final AuthenticationResult authResult = authMgr.authenticate(ss, body.getResponse());
//save clientProperties
if (session.getClientProperties() == null)
{
@@ -88,7 +86,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
MethodRegistry methodRegistry = session.getMethodRegistry();
- switch (authResult.status)
+ switch (authResult.getStatus())
{
case ERROR:
Exception cause = authResult.getCause();
@@ -108,8 +106,11 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
break;
case SUCCESS:
- _logger.info("Connected as: " + ss.getAuthorizationID());
- session.setAuthorizedID(new UsernamePrincipal(ss.getAuthorizationID()));
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Connected as: " + UsernamePrincipal.getUsernamePrincipalFromSubject(authResult.getSubject()));
+ }
+ session.setAuthorizedSubject(authResult.getSubject());
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
@@ -121,7 +122,7 @@ public class ConnectionStartOkMethodHandler implements StateAwareMethodListener<
case CONTINUE:
stateManager.changeState(AMQState.CONNECTION_NOT_AUTH);
- ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.challenge);
+ ConnectionSecureBody secureBody = methodRegistry.createConnectionSecureBody(authResult.getChallenge());
session.writeFrame(secureBody.generateFrame(0));
}
}
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 8939cfa334..0cfed77f2e 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
@@ -106,7 +106,7 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
else
{
queue = createQueue(queueName, body, virtualHost, protocolConnection);
- queue.setPrincipalHolder(protocolConnection);
+ queue.setAuthorizationHolder(protocolConnection);
if (queue.isDurable() && !queue.isAutoDelete())
{
store.createQueue(queue, body.getArguments());
@@ -119,7 +119,7 @@ public class QueueDeclareHandler implements StateAwareMethodListener<QueueDeclar
if (body.getExclusive())
{
queue.setExclusiveOwningSession(protocolConnection.getChannel(channelId));
- queue.setPrincipalHolder(protocolConnection);
+ queue.setAuthorizationHolder(protocolConnection);
if(!body.getDurable())
{
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
index db2cc970b2..5e6a143d52 100644
--- 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
@@ -22,9 +22,11 @@ package org.apache.qpid.server.information.management;
import java.io.IOException;
+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;
@@ -34,12 +36,15 @@ public class ServerInformationMBean extends AMQManagedObject implements ServerIn
{
private String buildVersion;
private String productVersion;
+ private ApplicationRegistry registry;
- public ServerInformationMBean(String buildVersion, String productVersion) throws JMException
+ public ServerInformationMBean(ApplicationRegistry applicationRegistry) throws JMException
{
super(ServerInformation.class, ServerInformation.TYPE);
- this.buildVersion = buildVersion;
- this.productVersion = productVersion;
+
+ registry = applicationRegistry;
+ buildVersion = QpidProperties.getBuildVersion();
+ productVersion = QpidProperties.getReleaseVersion();
}
public String getObjectInstanceName()
@@ -67,5 +72,75 @@ public class ServerInformationMBean extends AMQManagedObject implements ServerIn
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/actors/ManagementActor.java b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java
index 2825fa1b75..286fc78719 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/actors/ManagementActor.java
@@ -20,11 +20,15 @@
*/
package org.apache.qpid.server.logging.actors;
-import org.apache.qpid.server.logging.LogMessage;
-import org.apache.qpid.server.logging.LogSubject;
import org.apache.qpid.server.logging.RootMessageLogger;
+import java.security.AccessController;
+import java.security.Principal;
import java.text.MessageFormat;
+import java.util.Set;
+
+import javax.management.remote.JMXPrincipal;
+import javax.security.auth.Subject;
/**
* NOTE: This actor is not thread safe.
@@ -40,16 +44,23 @@ import java.text.MessageFormat;
*/
public class ManagementActor extends AbstractActor
{
+ /**
+ * Holds the principal name to display when principal subject is not available.
+ * <p>
+ * This is useful for cases when users invoke JMX operation over JConsole
+ * attached to the local JVM.
+ */
+ private static final String UNKNOWN_PRINCIPAL = "N/A";
+
String _lastThreadName = null;
/**
* LOG FORMAT for the ManagementActor,
- * Uses a MessageFormat call to insert the requried values according to
- * these indicies:
+ * Uses a MessageFormat call to insert the required values according to
+ * these indices:
*
- * 0 - Connection ID
- * 1 - User ID
- * 2 - IP
+ * 0 - User ID
+ * 1 - IP
*/
public static final String MANAGEMENT_FORMAT = "mng:{0}({1})";
@@ -75,19 +86,20 @@ public class ManagementActor extends AbstractActor
_lastThreadName = currentName;
// Management Thread names have this format.
- //RMI TCP Connection(2)-169.24.29.116
+ // RMI TCP Connection(2)-169.24.29.116
// This is true for both LocalAPI and JMX Connections
// However to be defensive lets test.
String[] split = currentName.split("\\(");
if (split.length == 2)
{
- String connectionID = split[1].split("\\)")[0];
String ip = currentName.split("-")[1];
-
- actor = MessageFormat.format(MANAGEMENT_FORMAT,
- connectionID,
- ip);
+ String principalName = getPrincipalName();
+ if (principalName == null)
+ {
+ principalName = UNKNOWN_PRINCIPAL;
+ }
+ actor = MessageFormat.format(MANAGEMENT_FORMAT, principalName, ip);
}
else
{
@@ -105,6 +117,30 @@ public class ManagementActor extends AbstractActor
}
}
+ /**
+ * Returns current JMX principal name.
+ *
+ * @return principal name or null if principal can not be found
+ */
+ protected String getPrincipalName()
+ {
+ String identity = null;
+
+ // retrieve Subject from current AccessControlContext
+ final Subject subject = Subject.getSubject(AccessController.getContext());
+ if (subject != null)
+ {
+ // retrieve JMXPrincipal from Subject
+ final Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
+ if (principals != null && !principals.isEmpty())
+ {
+ final Principal principal = principals.iterator().next();
+ identity = principal.getName();
+ }
+ }
+ return identity;
+ }
+
public String getLogMessage()
{
updateLogString();
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
index 6b83a7e7a5..5d1e85fe41 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Broker_logmessages.properties
@@ -32,4 +32,7 @@ STOPPED = BRK-1005 : Stopped
# 0 - path
CONFIG = BRK-1006 : Using configuration : {0}
# 0 - path
-LOG_CONFIG = BRK-1007 : Using logging configuration : {0} \ No newline at end of file
+LOG_CONFIG = BRK-1007 : Using logging configuration : {0}
+
+STATS_DATA = BRK-1008 : {0,choice,0#delivered|1#received} : {1,number,#.###} kB/s peak : {2,number,#} bytes total
+STATS_MSGS = BRK-1009 : {0,choice,0#delivered|1#received} : {1,number,#.###} msg/s peak : {2,number,#} msgs total \ No newline at end of file
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties
index 53bcd712f2..ed8c0d0ce9 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Channel_logmessages.properties
@@ -28,3 +28,7 @@ PREFETCH_SIZE = CHN-1004 : Prefetch Size (bytes) {0,number} : Count {1,number}
# 0 - queue causing flow control
FLOW_ENFORCED = CHN-1005 : Flow Control Enforced (Queue {0})
FLOW_REMOVED = CHN-1006 : Flow Control Removed
+# Channel Transactions
+# 0 - time in milliseconds
+OPEN_TXN = CHN-1007 : Open Transaction : {0,number} ms
+IDLE_TXN = CHN-1008 : Idle Transaction : {0,number} ms
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties
index b9890d9f27..b25a6a7301 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/Exchange_logmessages.properties
@@ -21,4 +21,5 @@
# 0 - type
# 1 - name
CREATED = EXH-1001 : Create :[ Durable] Type: {0} Name: {1}
-DELETED = EXH-1002 : Deleted \ No newline at end of file
+DELETED = EXH-1002 : Deleted
+DISCARDMSG = EXH-1003 : Discarded Message : Name: {0} Routing Key: {1}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties
index ab77476da2..ac77f674f2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/messages/ManagementConsole_logmessages.properties
@@ -30,4 +30,4 @@ STOPPED = MNG-1005 : Stopped
# 0 - Path
SSL_KEYSTORE = MNG-1006 : Using SSL Keystore : {0}
OPEN = MNG-1007 : Open : User {0}
-CLOSE = MNG-1008 : Close \ No newline at end of file
+CLOSE = MNG-1008 : Close : User {0} \ No newline at end of file
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 66bbefacb0..3e640c7929 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
@@ -20,4 +20,7 @@
#
# 0 - name
CREATED = VHT-1001 : Created : {0}
-CLOSED = VHT-1002 : Closed \ No newline at end of file
+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
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
index f28873940b..9b357403a8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ChannelLogSubject.java
@@ -47,7 +47,7 @@ public class ChannelLogSubject extends AbstractLogSubject
*/
setLogStringWithFormat(CHANNEL_FORMAT,
session.getSessionID(),
- session.getPrincipal().getName(),
+ session.getAuthorizedPrincipal().getName(),
session.getRemoteAddress(),
session.getVirtualHost().getName(),
channel.getChannelId());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
index a697029d24..c1c836f9b4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/logging/subjects/ConnectionLogSubject.java
@@ -56,7 +56,7 @@ public class ConnectionLogSubject extends AbstractLogSubject
{
if (!_upToDate)
{
- if (_session.getPrincipal() != null)
+ if (_session.getAuthorizedPrincipal() != null)
{
if (_session.getVirtualHost() != null)
{
@@ -72,7 +72,7 @@ public class ConnectionLogSubject extends AbstractLogSubject
*/
_logString = "[" + MessageFormat.format(CONNECTION_FORMAT,
_session.getSessionID(),
- _session.getPrincipal().getName(),
+ _session.getAuthorizedPrincipal().getName(),
_session.getRemoteAddress(),
_session.getVirtualHost().getName())
+ "] ";
@@ -83,7 +83,7 @@ public class ConnectionLogSubject extends AbstractLogSubject
{
_logString = "[" + MessageFormat.format(USER_FORMAT,
_session.getSessionID(),
- _session.getPrincipal().getName(),
+ _session.getAuthorizedPrincipal().getName(),
_session.getRemoteAddress())
+ "] ";
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
index 0a739af695..e44b8c41cb 100644
--- 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
@@ -26,8 +26,9 @@ import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.StandardMBean;
-import org.apache.qpid.AMQException;
+import org.apache.log4j.Logger;
import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
/**
* Provides implementation of the boilerplate ManagedObject interface. Most managed objects should find it useful
@@ -36,10 +37,14 @@ import org.apache.qpid.server.registry.ApplicationRegistry;
*/
public abstract class DefaultManagedObject extends StandardMBean implements ManagedObject
{
+ private static final Logger LOGGER = Logger.getLogger(ApplicationRegistry.class);
+
private Class<?> _managementInterface;
private String _typeName;
+ private ManagedObjectRegistry _registry;
+
protected DefaultManagedObject(Class<?> managementInterface, String typeName)
throws NotCompliantMBeanException
{
@@ -65,23 +70,26 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
public void register() throws JMException
{
- getManagedObjectRegistry().registerObject(this);
+ _registry = ApplicationRegistry.getInstance().getManagedObjectRegistry();
+ _registry.registerObject(this);
}
- protected ManagedObjectRegistry getManagedObjectRegistry()
- {
- return ApplicationRegistry.getInstance().getManagedObjectRegistry();
- }
-
- public void unregister() throws AMQException
+ public void unregister()
{
try
{
- getManagedObjectRegistry().unregisterObject(this);
+ if(_registry != null)
+ {
+ _registry.unregisterObject(this);
+ }
}
catch (JMException e)
{
- throw new AMQException("Error unregistering managed object: " + this + ": " + e, e);
+ LOGGER.error("Error unregistering managed object: " + this + ": " + e, e);
+ }
+ finally
+ {
+ _registry = null;
}
}
@@ -153,32 +161,4 @@ public abstract class DefaultManagedObject extends StandardMBean implements Mana
return "";
}
- protected static StringBuffer jmxEncode(StringBuffer jmxName, int attrPos)
- {
- for (int i = attrPos; i < jmxName.length(); i++)
- {
- if (jmxName.charAt(i) == ',')
- {
- jmxName.setCharAt(i, ';');
- }
- else if (jmxName.charAt(i) == ':')
- {
- jmxName.setCharAt(i, '-');
- }
- else if (jmxName.charAt(i) == '?' ||
- jmxName.charAt(i) == '*' ||
- jmxName.charAt(i) == '\\')
- {
- jmxName.insert(i, '\\');
- i++;
- }
- else if (jmxName.charAt(i) == '\n')
- {
- jmxName.insert(i, '\\');
- i++;
- jmxName.setCharAt(i, 'n');
- }
- }
- return jmxName;
- }
}
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
index 0334a856c1..b44964f176 100644
--- 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
@@ -20,32 +20,6 @@
*/
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.registry.ApplicationRegistry;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
-
-import javax.management.JMException;
-import javax.management.MBeanServer;
-import javax.management.MBeanServerFactory;
-import javax.management.ObjectName;
-import javax.management.NotificationListener;
-import javax.management.NotificationFilterSupport;
-import javax.management.remote.JMXConnectorServer;
-import javax.management.remote.JMXServiceURL;
-import javax.management.remote.MBeanServerForwarder;
-import javax.management.remote.JMXConnectionNotification;
-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 java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
@@ -64,7 +38,31 @@ import java.rmi.server.RMIClientSocketFactory;
import java.rmi.server.RMIServerSocketFactory;
import java.rmi.server.UnicastRemoteObject;
import java.util.HashMap;
-import java.util.Map;
+
+import javax.management.JMException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+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.RMIConnectorServer;
+import javax.management.remote.rmi.RMIJRMPServerImpl;
+import javax.management.remote.rmi.RMIServerImpl;
+import javax.rmi.ssl.SslRMIClientSocketFactory;
+import javax.rmi.ssl.SslRMIServerSocketFactory;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.registry.IApplicationRegistry;
+import org.apache.qpid.server.security.auth.rmi.RMIPasswordAuthenticator;
/**
* This class starts up an MBeanserver. If out of the box agent has been enabled then there are no
@@ -74,15 +72,14 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
{
private static final Logger _log = Logger.getLogger(JMXManagedObjectRegistry.class);
- public static final String MANAGEMENT_PORT_CONFIG_PATH = "management.jmxport";
- public static final int MANAGEMENT_PORT_DEFAULT = 8999;
- public static final int PORT_EXPORT_OFFSET = 100;
-
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");
@@ -95,8 +92,11 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_mbeanServer =
platformServer ? ManagementFactory.getPlatformMBeanServer()
: MBeanServerFactory.createMBeanServer(ManagedObject.DOMAIN);
- }
+ _jmxPortRegistryServer = appRegistry.getConfiguration().getJMXPortRegistryServer();
+ _jmxPortConnectorServer = appRegistry.getConfiguration().getJMXConnectorServerPort();
+
+ }
public void start() throws IOException, ConfigurationException
{
@@ -111,14 +111,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
IApplicationRegistry appRegistry = ApplicationRegistry.getInstance();
- int port = appRegistry.getConfiguration().getJMXManagementPort();
- //retrieve the Principal Database assigned to JMX authentication duties
- String jmxDatabaseName = appRegistry.getConfiguration().getJMXPrincipalDatabase();
- Map<String, PrincipalDatabase> map = appRegistry.getDatabaseManager().getDatabases();
- PrincipalDatabase db = map.get(jmxDatabaseName);
-
- HashMap<String,Object> env = new HashMap<String,Object>();
//Socket factories for the RMIConnectorServer, either default or SLL depending on configuration
RMIClientSocketFactory csf;
@@ -200,7 +193,8 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
//add a JMXAuthenticator implementation the env map to authenticate the RMI based JMX connector server
RMIPasswordAuthenticator rmipa = new RMIPasswordAuthenticator();
- rmipa.setPrincipalDatabase(db);
+ rmipa.setAuthenticationManager(appRegistry.getAuthenticationManager());
+ HashMap<String,Object> env = new HashMap<String,Object>();
env.put(JMXConnectorServer.AUTHENTICATOR, rmipa);
/*
@@ -211,14 +205,14 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
System.setProperty("java.rmi.server.randomIDs", "true");
if(_useCustomSocketFactory)
{
- _rmiRegistry = LocateRegistry.createRegistry(port, null, new CustomRMIServerSocketFactory());
+ _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, new CustomRMIServerSocketFactory());
}
else
{
- _rmiRegistry = LocateRegistry.createRegistry(port, null, null);
+ _rmiRegistry = LocateRegistry.createRegistry(_jmxPortRegistryServer, null, null);
}
- CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", port));
+ CurrentActor.get().message(ManagementConsoleMessages.LISTENING("RMI Registry", _jmxPortRegistryServer));
/*
* We must now create the RMI ConnectorServer manually, as the JMX Factory methods use RMI calls
@@ -229,7 +223,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
* 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 RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(port+PORT_EXPORT_OFFSET, csf, ssf, env);
+ final RMIServerImpl rmiConnectorServerStub = new RMIJRMPServerImpl(_jmxPortConnectorServer, csf, ssf, env);
String localHost;
try
{
@@ -241,9 +235,9 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
}
final String hostname = localHost;
final JMXServiceURL externalUrl = new JMXServiceURL(
- "service:jmx:rmi://"+hostname+":"+(port+PORT_EXPORT_OFFSET)+"/jndi/rmi://"+hostname+":"+port+"/jmxrmi");
+ "service:jmx:rmi://"+hostname+":"+(_jmxPortConnectorServer)+"/jndi/rmi://"+hostname+":"+_jmxPortRegistryServer+"/jmxrmi");
- final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, port+PORT_EXPORT_OFFSET);
+ final JMXServiceURL internalUrl = new JMXServiceURL("rmi", hostname, _jmxPortConnectorServer);
_cs = new RMIConnectorServer(internalUrl, env, rmiConnectorServerStub, _mbeanServer)
{
@Override
@@ -312,7 +306,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
_cs.start();
String connectorServer = (sslEnabled ? "SSL " : "") + "JMX RMIConnectorServer";
- CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, port + PORT_EXPORT_OFFSET));
+ CurrentActor.get().message(ManagementConsoleMessages.LISTENING(connectorServer, _jmxPortConnectorServer));
CurrentActor.get().message(ManagementConsoleMessages.READY(false));
}
@@ -407,7 +401,7 @@ public class JMXManagedObjectRegistry implements ManagedObjectRegistry
if (_rmiRegistry != null)
{
// Stopping the RMI registry
- CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _cs.getAddress().getPort() - PORT_EXPORT_OFFSET));
+ CurrentActor.get().message(ManagementConsoleMessages.SHUTTING_DOWN("RMI Registry", _jmxPortRegistryServer));
try
{
UnicastRemoteObject.unexportObject(_rmiRegistry, false);
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
index 964b5ed5a0..169195304c 100644
--- 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
@@ -26,8 +26,6 @@ import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.security.AccessControlContext;
import java.security.AccessController;
-import java.security.Principal;
-import java.util.Properties;
import java.util.Set;
import javax.management.Attribute;
@@ -44,7 +42,6 @@ import javax.management.remote.MBeanServerForwarder;
import javax.security.auth.Subject;
import org.apache.log4j.Logger;
-import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.actors.ManagementActor;
import org.apache.qpid.server.logging.messages.ManagementConsoleMessages;
import org.apache.qpid.server.registry.ApplicationRegistry;
@@ -52,20 +49,15 @@ import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
/**
- * This class can be used by the JMXConnectorServer as an InvocationHandler for the mbean operations. This implements
- * the logic for allowing the users to invoke MBean operations and implements the restrictions for readOnly, readWrite
- * and admin users.
+ * 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);
- public final static String ADMIN = "admin";
- public final static String READWRITE = "readwrite";
- public final static String READONLY = "readonly";
private final static String DELEGATE = "JMImplementation:type=MBeanServerDelegate";
private MBeanServer _mbs;
- private static Properties _userRoles = new Properties();
private static ManagementActor _logActor;
public static MBeanServerForwarder newProxyInstance()
@@ -137,14 +129,13 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
if (principals == null || principals.isEmpty())
{
- throw new SecurityException("Access denied: no principal");
+ throw new SecurityException("Access denied: no JMX principal");
}
-
- // Save the principal
- Principal principal = principals.iterator().next();
- SecurityManager.setThreadPrincipal(principal);
-
- // Get the component, type and impact, which may be null
+
+ // 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);
@@ -213,6 +204,20 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
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;
@@ -272,7 +277,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
}
catch (JMException ex)
{
- ex.printStackTrace();
+ _logger.error("Unable to determine mbean impact for method : " + mbeanMethod, ex);
}
}
@@ -308,7 +313,7 @@ public class MBeanInvocationHandlerImpl implements InvocationHandler, Notificati
else if (notification.getType().equals(JMXConnectionNotification.CLOSED) ||
notification.getType().equals(JMXConnectionNotification.FAILED))
{
- _logActor.message(ManagementConsoleMessages.CLOSE());
+ _logActor.message(ManagementConsoleMessages.CLOSE(user));
}
}
}
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 194835ac02..84a1642578 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
@@ -37,7 +37,7 @@ public class ContentHeaderBodyAdapter implements AMQMessageHeader
private BasicContentHeaderProperties getProperties()
{
- return (BasicContentHeaderProperties) _contentHeaderBody.properties;
+ return (BasicContentHeaderProperties) _contentHeaderBody.getProperties();
}
public String getCorrelationId()
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 30bea7b6e6..5992e42fb7 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
@@ -29,7 +29,10 @@ import org.apache.qpid.framing.abstraction.MessagePublishInfo;
import org.apache.qpid.server.store.StorableMessageMetaData;
import org.apache.qpid.server.store.MessageMetaDataType;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.util.ByteBufferInputStream;
+import org.apache.qpid.server.util.ByteBufferOutputStream;
+import java.io.*;
import java.nio.ByteBuffer;
import java.util.Set;
@@ -120,38 +123,38 @@ public class MessageMetaData implements StorableMessageMetaData
return size;
}
+
public int writeToBuffer(int offset, ByteBuffer dest)
{
- ByteBuffer src = ByteBuffer.allocate((int)getStorableSize());
-
- org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(src);
- EncodingUtils.writeInteger(minaSrc, _contentHeaderBody.getSize());
- _contentHeaderBody.writePayload(minaSrc);
- EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getExchange());
- EncodingUtils.writeShortStringBytes(minaSrc, _messagePublishInfo.getRoutingKey());
- byte flags = 0;
- if(_messagePublishInfo.isMandatory())
- {
- flags |= MANDATORY_FLAG;
- }
- if(_messagePublishInfo.isImmediate())
+ int oldPosition = dest.position();
+ try
{
- flags |= IMMEDIATE_FLAG;
+
+ DataOutputStream dataOutputStream = new DataOutputStream(new ByteBufferOutputStream(dest));
+ EncodingUtils.writeInteger(dataOutputStream, _contentHeaderBody.getSize());
+ _contentHeaderBody.writePayload(dataOutputStream);
+ EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getExchange());
+ EncodingUtils.writeShortStringBytes(dataOutputStream, _messagePublishInfo.getRoutingKey());
+ byte flags = 0;
+ if(_messagePublishInfo.isMandatory())
+ {
+ flags |= MANDATORY_FLAG;
+ }
+ if(_messagePublishInfo.isImmediate())
+ {
+ flags |= IMMEDIATE_FLAG;
+ }
+ dest.put(flags);
+ dest.putLong(_arrivalTime);
+
}
- EncodingUtils.writeByte(minaSrc, flags);
- EncodingUtils.writeLong(minaSrc,_arrivalTime);
- src.position(minaSrc.position());
- src.flip();
- src.position(offset);
- src = src.slice();
- if(dest.remaining() < src.limit())
+ catch (IOException e)
{
- src.limit(dest.remaining());
+ // This shouldn't happen as we are not actually using anything that can throw an IO Exception
+ throw new RuntimeException(e);
}
- dest.put(src);
-
- return src.limit();
+ return dest.position()-oldPosition;
}
public int getContentSize()
@@ -161,7 +164,7 @@ public class MessageMetaData implements StorableMessageMetaData
public boolean isPersistent()
{
- BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.properties);
+ BasicContentHeaderProperties properties = (BasicContentHeaderProperties) (_contentHeaderBody.getProperties());
return properties.getDeliveryMode() == BasicContentHeaderProperties.PERSISTENT;
}
@@ -173,14 +176,15 @@ public class MessageMetaData implements StorableMessageMetaData
{
try
{
- org.apache.mina.common.ByteBuffer minaSrc = org.apache.mina.common.ByteBuffer.wrap(buf);
- int size = EncodingUtils.readInteger(minaSrc);
- ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(minaSrc, size);
- final AMQShortString exchange = EncodingUtils.readAMQShortString(minaSrc);
- final AMQShortString routingKey = EncodingUtils.readAMQShortString(minaSrc);
+ ByteBufferInputStream bbis = new ByteBufferInputStream(buf);
+ DataInputStream dais = new DataInputStream(bbis);
+ int size = EncodingUtils.readInteger(dais);
+ ContentHeaderBody chb = ContentHeaderBody.createFromBuffer(dais, size);
+ final AMQShortString exchange = EncodingUtils.readAMQShortString(dais);
+ final AMQShortString routingKey = EncodingUtils.readAMQShortString(dais);
- final byte flags = EncodingUtils.readByte(minaSrc);
- long arrivalTime = EncodingUtils.readLong(minaSrc);
+ final byte flags = EncodingUtils.readByte(dais);
+ long arrivalTime = EncodingUtils.readLong(dais);
MessagePublishInfo publishBody =
new MessagePublishInfo()
@@ -216,6 +220,10 @@ public class MessageMetaData implements StorableMessageMetaData
{
throw new RuntimeException(e);
}
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
+ }
}
};
@@ -229,7 +237,7 @@ public class MessageMetaData implements StorableMessageMetaData
{
private BasicContentHeaderProperties getProperties()
{
- return (BasicContentHeaderProperties) getContentHeaderBody().properties;
+ return (BasicContentHeaderProperties) getContentHeaderBody().getProperties();
}
public String getCorrelationId()
diff --git a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
index cf8ae2166c..2297e4200d 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/message/MessageMetaData_0_10.java
@@ -34,7 +34,7 @@ import org.apache.qpid.transport.codec.BBDecoder;
import java.nio.ByteBuffer;
import java.lang.ref.SoftReference;
-public class MessageMetaData_0_10 implements StorableMessageMetaData
+public class MessageMetaData_0_10 implements StorableMessageMetaData, InboundMessage
{
private Header _header;
private DeliveryProperties _deliveryProps;
@@ -194,6 +194,12 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData
return _deliveryProps == null ? 0L : _deliveryProps.getExpiration();
}
+ public boolean isRedelivered()
+ {
+ // The *Message* is never redelivered, only queue entries are...
+ return false;
+ }
+
public long getArrivalTime()
{
return _arrivalTime;
@@ -239,4 +245,6 @@ public class MessageMetaData_0_10 implements StorableMessageMetaData
}
}
+
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
index 2cebec373e..3970e5a2d4 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_8/ProtocolOutputConverterImpl.java
@@ -26,6 +26,7 @@
*/
package org.apache.qpid.server.output.amqp0_8;
+import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.message.AMQMessage;
import org.apache.qpid.server.queue.QueueEntry;
@@ -34,22 +35,18 @@ import org.apache.qpid.server.output.HeaderPropertiesConverter;
import org.apache.qpid.server.message.MessageContentSource;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
-import org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
import org.apache.qpid.transport.DeliveryProperties;
-import java.nio.ByteBuffer;
+import java.io.DataOutputStream;
+import java.io.IOException;
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v8_0);
- private static final ProtocolVersionMethodConverter PROTOCOL_CONVERTER =
- METHOD_REGISTRY.getProtocolVersionMethodConverter();
-
public static Factory getInstanceFactory()
{
return new Factory()
@@ -62,6 +59,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
};
}
+
private final AMQProtocolSession _protocolSession;
private ProtocolOutputConverterImpl(AMQProtocolSession session)
@@ -78,10 +76,11 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
public void writeDeliver(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
throws AMQException
{
- AMQDataBlock deliver = createEncodedDeliverFrame(entry, channelId, deliveryTag, consumerTag);
- writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
+ AMQBody deliverBody = createEncodedDeliverBody(entry, deliveryTag, consumerTag);
+ writeMessageDelivery(entry, channelId, deliverBody);
}
+
private ContentHeaderBody getContentHeaderBody(QueueEntry entry)
throws AMQException
{
@@ -93,65 +92,120 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
final MessageTransferMessage message = (MessageTransferMessage) entry.getMessage();
BasicContentHeaderProperties props = HeaderPropertiesConverter.convert(message);
- ContentHeaderBody chb = new ContentHeaderBody(props, BasicGetBodyImpl.CLASS_ID);
- chb.bodySize = message.getSize();
+ ContentHeaderBody chb = new ContentHeaderBody(props, org.apache.qpid.framing.amqp_8_0.BasicGetBodyImpl.CLASS_ID);
+ chb.bodySize = message.getSize();
return chb;
}
}
- public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
+ private void writeMessageDelivery(QueueEntry entry, int channelId, AMQBody deliverBody)
+ throws AMQException
{
- AMQDataBlock deliver = createEncodedGetOkFrame(entry, channelId, deliveryTag, queueSize);
- writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliver);
+ writeMessageDelivery(entry.getMessage(), getContentHeaderBody(entry), channelId, deliverBody);
}
- private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody chb, int channelId, AMQDataBlock deliver)
+ private void writeMessageDelivery(MessageContentSource message, ContentHeaderBody contentHeaderBody, int channelId, AMQBody deliverBody)
throws AMQException
{
- AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId, chb);
-
+ int bodySize = (int) message.getSize();
- final int bodySize = (int) message.getSize();
if(bodySize == 0)
{
- SmallCompositeAMQDataBlock compositeBlock = new SmallCompositeAMQDataBlock(deliver,
- contentHeader);
+ SmallCompositeAMQBodyBlock compositeBlock = new SmallCompositeAMQBodyBlock(channelId, deliverBody,
+ contentHeaderBody);
+
writeFrame(compositeBlock);
}
else
{
int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
- final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
- ByteBuffer buf = ByteBuffer.allocate(capacity);
- int writtenSize = 0;
+ int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
+
+ int writtenSize = capacity;
+
+ AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
- writtenSize += message.getContent(buf, writtenSize);
- buf.flip();
- AMQDataBlock firstContentBody = new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf));
- AMQDataBlock[] blocks = new AMQDataBlock[]{deliver, contentHeader, firstContentBody};
- CompositeAMQDataBlock compositeBlock = new CompositeAMQDataBlock(blocks);
+ CompositeAMQBodyBlock
+ compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
writeFrame(compositeBlock);
while(writtenSize < bodySize)
{
- buf = java.nio.ByteBuffer.allocate(capacity);
- writtenSize += message.getContent(buf, writtenSize);
- buf.flip();
- writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
+ capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
+ MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
+ writtenSize += capacity;
+
+ writeFrame(new AMQFrame(channelId, body));
}
+ }
+ }
+ private class MessageContentSourceBody implements AMQBody
+ {
+ public static final byte TYPE = 3;
+ private int _length;
+ private MessageContentSource _message;
+ private int _offset;
+
+ public MessageContentSourceBody(MessageContentSource message, int offset, int length)
+ {
+ _message = message;
+ _offset = offset;
+ _length = length;
+ }
+
+ public byte getFrameType()
+ {
+ return TYPE;
}
+
+ public int getSize()
+ {
+ return _length;
+ }
+
+ public void writePayload(DataOutputStream buffer) throws IOException
+ {
+ byte[] data = new byte[_length];
+
+ _message.getContent(java.nio.ByteBuffer.wrap(data), _offset);
+
+ buffer.write(data);
+ }
+
+ public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
+ {
+
+ AMQDataBlock contentHeader = ContentHeaderBody.createAMQFrame(channelId,
+ contentHeaderBody);
+ return contentHeader;
}
- private AMQDataBlock createEncodedDeliverFrame(QueueEntry entry, int channelId, long deliveryTag, AMQShortString consumerTag)
+ public void writeGetOk(QueueEntry entry, int channelId, long deliveryTag, int queueSize) throws AMQException
+ {
+ AMQBody deliver = createEncodedGetOkBody(entry, deliveryTag, queueSize);
+ writeMessageDelivery(entry, channelId, deliver);
+ }
+
+
+ private AMQBody createEncodedDeliverBody(QueueEntry entry,
+ final long deliveryTag,
+ final AMQShortString consumerTag)
throws AMQException
{
+
final AMQShortString exchangeName;
final AMQShortString routingKey;
@@ -172,21 +226,58 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
final boolean isRedelivered = entry.isRedelivered();
+ final AMQBody returnBlock = new AMQBody()
+ {
+
+ public AMQBody _underlyingBody;
- BasicDeliverBody deliverBody =
- METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
- deliveryTag,
- isRedelivered,
- exchangeName,
- routingKey);
+ public AMQBody createAMQBody()
+ {
+ return METHOD_REGISTRY.createBasicDeliverBody(consumerTag,
+ deliveryTag,
+ isRedelivered,
+ exchangeName,
+ routingKey);
- AMQFrame deliverFrame = deliverBody.generateFrame(channelId);
- return deliverFrame;
+
+
+ }
+
+ public byte getFrameType()
+ {
+ return AMQMethodBody.TYPE;
+ }
+
+ public int getSize()
+ {
+ if(_underlyingBody == null)
+ {
+ _underlyingBody = createAMQBody();
+ }
+ return _underlyingBody.getSize();
+ }
+
+ public void writePayload(DataOutputStream buffer) throws IOException
+ {
+ if(_underlyingBody == null)
+ {
+ _underlyingBody = createAMQBody();
+ }
+ _underlyingBody.writePayload(buffer);
+ }
+
+ public void handle(final int channelId, final AMQVersionAwareProtocolSession amqMinaProtocolSession)
+ throws AMQException
+ {
+ throw new AMQException("This block should never be dispatched!");
+ }
+ };
+ return returnBlock;
}
- private AMQDataBlock createEncodedGetOkFrame(QueueEntry entry, int channelId, long deliveryTag, int queueSize)
+ private AMQBody createEncodedGetOkBody(QueueEntry entry, long deliveryTag, int queueSize)
throws AMQException
{
final AMQShortString exchangeName;
@@ -215,9 +306,8 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
exchangeName,
routingKey,
queueSize);
- AMQFrame getOkFrame = getOkBody.generateFrame(channelId);
- return getOkFrame;
+ return getOkBody;
}
public byte getProtocolMinorVersion()
@@ -230,31 +320,28 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return getProtocolSession().getProtocolMajorVersion();
}
- private AMQDataBlock createEncodedReturnFrame(MessagePublishInfo messagePublishInfo, int channelId, int replyCode, AMQShortString replyText) throws AMQException
+ private AMQBody createEncodedReturnFrame(MessagePublishInfo messagePublishInfo,
+ int replyCode,
+ AMQShortString replyText) throws AMQException
{
+
BasicReturnBody basicReturnBody =
METHOD_REGISTRY.createBasicReturnBody(replyCode,
- replyText,
- messagePublishInfo.getExchange(),
- messagePublishInfo.getRoutingKey());
- AMQFrame returnFrame = basicReturnBody.generateFrame(channelId);
+ replyText,
+ messagePublishInfo.getExchange(),
+ messagePublishInfo.getRoutingKey());
- return returnFrame;
+
+ return basicReturnBody;
}
- public void writeReturn(MessagePublishInfo messagePublishInfo,
- ContentHeaderBody header,
- MessageContentSource content,
- int channelId,
- int replyCode,
- AMQShortString replyText)
+ public void writeReturn(MessagePublishInfo messagePublishInfo, ContentHeaderBody header, MessageContentSource message, int channelId, int replyCode, AMQShortString replyText)
throws AMQException
{
- AMQDataBlock returnFrame = createEncodedReturnFrame(messagePublishInfo, channelId, replyCode, replyText);
-
- writeMessageDelivery(content, header, channelId, returnFrame);
+ AMQBody returnFrame = createEncodedReturnFrame(messagePublishInfo, replyCode, replyText);
+ writeMessageDelivery(message, header, channelId, returnFrame);
}
@@ -266,8 +353,68 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
public void confirmConsumerAutoClose(int channelId, AMQShortString consumerTag)
{
+
BasicCancelOkBody basicCancelOkBody = METHOD_REGISTRY.createBasicCancelOkBody(consumerTag);
writeFrame(basicCancelOkBody.generateFrame(channelId));
}
+
+
+ public static final class CompositeAMQBodyBlock extends AMQDataBlock
+ {
+ public static final int OVERHEAD = 3 * AMQFrame.getFrameOverhead();
+
+ private final AMQBody _methodBody;
+ private final AMQBody _headerBody;
+ private final AMQBody _contentBody;
+ private final int _channel;
+
+
+ public CompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody, AMQBody contentBody)
+ {
+ _channel = channel;
+ _methodBody = methodBody;
+ _headerBody = headerBody;
+ _contentBody = contentBody;
+
+ }
+
+ public long getSize()
+ {
+ return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
+ }
+
+ public void writePayload(DataOutputStream buffer) throws IOException
+ {
+ AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
+ }
+ }
+
+ public static final class SmallCompositeAMQBodyBlock extends AMQDataBlock
+ {
+ public static final int OVERHEAD = 2 * AMQFrame.getFrameOverhead();
+
+ private final AMQBody _methodBody;
+ private final AMQBody _headerBody;
+ private final int _channel;
+
+
+ public SmallCompositeAMQBodyBlock(int channel, AMQBody methodBody, AMQBody headerBody)
+ {
+ _channel = channel;
+ _methodBody = methodBody;
+ _headerBody = headerBody;
+
+ }
+
+ public long getSize()
+ {
+ return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
+ }
+
+ public void writePayload(DataOutputStream buffer) throws IOException
+ {
+ AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
+ }
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
index 319b5cc7bd..aef3483282 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9/ProtocolOutputConverterImpl.java
@@ -20,9 +20,6 @@ package org.apache.qpid.server.output.amqp0_9;
*
*/
-
-import org.apache.mina.common.ByteBuffer;
-
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.output.HeaderPropertiesConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
@@ -38,11 +35,13 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_9);
- private static final ProtocolVersionMethodConverter
- PROTOCOL_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
public static Factory getInstanceFactory()
@@ -121,15 +120,12 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
- final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacity);
+ int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
- int writtenSize = 0;
+ int writtenSize = capacity;
+ AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
- writtenSize += message.getContent(buf, writtenSize);
- buf.flip();
- AMQBody firstContentBody = PROTOCOL_CONVERTER.convertToBody(buf);
CompositeAMQBodyBlock
compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
@@ -137,15 +133,55 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
while(writtenSize < bodySize)
{
- buf = java.nio.ByteBuffer.allocate(capacity);
+ capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
+ MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
+ writtenSize += capacity;
- writtenSize += message.getContent(buf, writtenSize);
- buf.flip();
- writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
+ writeFrame(new AMQFrame(channelId, body));
}
}
}
+ private class MessageContentSourceBody implements AMQBody
+ {
+ public static final byte TYPE = 3;
+ private int _length;
+ private MessageContentSource _message;
+ private int _offset;
+
+ public MessageContentSourceBody(MessageContentSource message, int offset, int length)
+ {
+ _message = message;
+ _offset = offset;
+ _length = length;
+ }
+
+ public byte getFrameType()
+ {
+ return TYPE;
+ }
+
+ public int getSize()
+ {
+ return _length;
+ }
+
+ public void writePayload(DataOutputStream buffer) throws IOException
+ {
+ byte[] data = new byte[_length];
+
+ _message.getContent(ByteBuffer.wrap(data), _offset);
+
+ buffer.write(data);
+ }
+
+ public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+
private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
{
@@ -221,7 +257,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return _underlyingBody.getSize();
}
- public void writePayload(ByteBuffer buffer)
+ public void writePayload(DataOutputStream buffer) throws IOException
{
if(_underlyingBody == null)
{
@@ -346,7 +382,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
}
- public void writePayload(ByteBuffer buffer)
+ public void writePayload(DataOutputStream buffer) throws IOException
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
}
@@ -374,7 +410,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
}
- public void writePayload(ByteBuffer buffer)
+ public void writePayload(DataOutputStream buffer) throws IOException
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java
index cffbe445ee..10748298bc 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/output/amqp0_9_1/ProtocolOutputConverterImpl.java
@@ -20,9 +20,6 @@ package org.apache.qpid.server.output.amqp0_9_1;
*
*/
-
-import org.apache.mina.common.ByteBuffer;
-
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.output.HeaderPropertiesConverter;
import org.apache.qpid.server.protocol.AMQProtocolSession;
@@ -33,17 +30,16 @@ import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.framing.*;
import org.apache.qpid.framing.amqp_0_91.BasicGetBodyImpl;
import org.apache.qpid.framing.abstraction.MessagePublishInfo;
-import org.apache.qpid.framing.abstraction.ProtocolVersionMethodConverter;
import org.apache.qpid.AMQException;
import org.apache.qpid.transport.DeliveryProperties;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
+import java.io.DataOutputStream;
+import java.io.IOException;
+
public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
{
private static final MethodRegistry METHOD_REGISTRY = MethodRegistry.getMethodRegistry(ProtocolVersion.v0_91);
- private static final ProtocolVersionMethodConverter
- PROTOCOL_CONVERTER = METHOD_REGISTRY.getProtocolVersionMethodConverter();
-
public static Factory getInstanceFactory()
{
@@ -121,15 +117,11 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
int maxBodySize = (int) getProtocolSession().getMaxFrameSize() - AMQFrame.getFrameOverhead();
- final int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
- java.nio.ByteBuffer buf = java.nio.ByteBuffer.allocate(capacity);
+ int capacity = bodySize > maxBodySize ? maxBodySize : bodySize;
- int writtenSize = 0;
+ int writtenSize = capacity;
-
- writtenSize += message.getContent(buf, writtenSize);
- buf.flip();
- AMQBody firstContentBody = PROTOCOL_CONVERTER.convertToBody(buf);
+ AMQBody firstContentBody = new MessageContentSourceBody(message,0,capacity);
CompositeAMQBodyBlock
compositeBlock = new CompositeAMQBodyBlock(channelId, deliverBody, contentHeaderBody, firstContentBody);
@@ -137,15 +129,54 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
while(writtenSize < bodySize)
{
- buf = java.nio.ByteBuffer.allocate(capacity);
+ capacity = bodySize - writtenSize > maxBodySize ? maxBodySize : bodySize - writtenSize;
+ MessageContentSourceBody body = new MessageContentSourceBody(message, writtenSize, capacity);
+ writtenSize += capacity;
- writtenSize += message.getContent(buf, writtenSize);
- buf.flip();
- writeFrame(new AMQFrame(channelId, PROTOCOL_CONVERTER.convertToBody(buf)));
+ writeFrame(new AMQFrame(channelId, body));
}
}
}
+ private class MessageContentSourceBody implements AMQBody
+ {
+ public static final byte TYPE = 3;
+ private int _length;
+ private MessageContentSource _message;
+ private int _offset;
+
+ public MessageContentSourceBody(MessageContentSource message, int offset, int length)
+ {
+ _message = message;
+ _offset = offset;
+ _length = length;
+ }
+
+ public byte getFrameType()
+ {
+ return TYPE;
+ }
+
+ public int getSize()
+ {
+ return _length;
+ }
+
+ public void writePayload(DataOutputStream buffer) throws IOException
+ {
+ byte[] data = new byte[_length];
+
+ _message.getContent(java.nio.ByteBuffer.wrap(data), _offset);
+
+ buffer.write(data);
+ }
+
+ public void handle(int channelId, AMQVersionAwareProtocolSession amqProtocolSession) throws AMQException
+ {
+ throw new UnsupportedOperationException();
+ }
+ }
+
private AMQDataBlock createContentHeaderBlock(final int channelId, final ContentHeaderBody contentHeaderBody)
{
@@ -221,7 +252,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return _underlyingBody.getSize();
}
- public void writePayload(ByteBuffer buffer)
+ public void writePayload(DataOutputStream buffer) throws IOException
{
if(_underlyingBody == null)
{
@@ -346,7 +377,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() + _contentBody.getSize();
}
- public void writePayload(ByteBuffer buffer)
+ public void writePayload(DataOutputStream buffer) throws IOException
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody, _contentBody);
}
@@ -374,7 +405,7 @@ public class ProtocolOutputConverterImpl implements ProtocolOutputConverter
return OVERHEAD + _methodBody.getSize() + _headerBody.getSize() ;
}
- public void writePayload(ByteBuffer buffer)
+ public void writePayload(DataOutputStream buffer) throws IOException
{
AMQFrame.writeFrames(buffer, _channel, _methodBody, _headerBody);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.java
new file mode 100644
index 0000000000..644f714c8c
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackageUtil.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.plugins;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.osgi.framework.Version;
+
+/**
+ * Utility class to convert a map of package name to version numbers into the string
+ * with the format expected of a OSGi system package declaration:
+ *
+ * <code>
+ * org.xyz; version=1.0.0, org.xyz.xyz; version=1.0.0,...
+ * </code>
+ *
+ * Additionally, if the caller has provided a qpidPackageReleaseNumber and the package
+ * begins org.apache.qpid, this release number will be used, in preference to the one
+ * found in the Map.
+ *
+ * @see org.osgi.framework.Constants#FRAMEWORK_SYSTEMPACKAGES
+ *
+ */
+public class OsgiSystemPackageUtil
+{
+ private static final String APACHE_QPID_PKG_PREFIX = "org.apache.qpid";
+
+ private final Map<String, String> _packageNameVersionMap;
+ private final Version _qpidPackageReleaseNumber;
+
+ public OsgiSystemPackageUtil(final Version qpidPackageReleaseNumber, final Map<String, String> packageNameVersionMap)
+ {
+ _qpidPackageReleaseNumber = qpidPackageReleaseNumber;
+ _packageNameVersionMap = packageNameVersionMap;
+ }
+
+ public String getFormattedSystemPackageString()
+ {
+ if (_packageNameVersionMap == null || _packageNameVersionMap.size() == 0)
+ {
+ return null;
+ }
+
+ final StringBuilder packages = new StringBuilder();
+
+ for(Iterator<String> itr = _packageNameVersionMap.keySet().iterator(); itr.hasNext();)
+ {
+ final String packageName = itr.next();
+ final String packageVersion;
+
+ if (_qpidPackageReleaseNumber != null && packageName.startsWith(APACHE_QPID_PKG_PREFIX))
+ {
+ packageVersion = _qpidPackageReleaseNumber.toString();
+ }
+ else
+ {
+ packageVersion = _packageNameVersionMap.get(packageName);
+ }
+
+ packages.append(packageName);
+ packages.append("; ");
+ packages.append("version=");
+ packages.append(packageVersion);
+
+ if (itr.hasNext())
+ {
+ packages.append(", ");
+ }
+ }
+
+ return packages.toString();
+ }
+
+}
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
new file mode 100644
index 0000000000..aaab4f76cc
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/plugins/OsgiSystemPackages.properties
@@ -0,0 +1,93 @@
+#
+# 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.
+#
+
+#
+# OSGi framework system package list
+#
+# PluginManager uses these properties to construct the FRAMEWORK_SYSTEMPACKAGES list
+#
+
+# Format is:
+# <package>=<version>
+# and PluginManager will convert this into:
+# <package>; version=<version>
+# e.g. org.osgi.framework; version=1.3.0
+
+javax.management.openmbean=1.0.0
+javax.management=1.0.0
+
+javax.security.auth=1.0.0
+javax.security.auth.callback=1.0.0
+javax.security.sasl=1.0.0
+javax.security=1.0.0
+
+org.xml.sax=1.0.0
+org.xml.sax.helpers=1.0.0
+
+org.osgi.framework=1.3.0
+org.osgi.service.packageadmin=1.2.0
+org.osgi.service.startlevel=1.0.0
+org.osgi.service.url=1.0.0
+org.osgi.util.tracker=1.0.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.logging=1.0.0
+
+org.apache.log4j=1.2.12
+
+org.slf4j=1.6.1
+
+# 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.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.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.exchange=0.0.0
+org.apache.qpid.server.logging=0.0.0
+org.apache.qpid.server.logging.actors=0.0.0
+org.apache.qpid.server.logging.subjects=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.registry=0.0.0
+org.apache.qpid.server.security=0.0.0
+org.apache.qpid.server.security.access=0.0.0
+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.virtualhost=0.0.0
+org.apache.qpid.server.virtualhost.plugins=0.0.0
+org.apache.qpid.util=0.0.0
+
diff --git a/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java b/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java
index e7f9983fff..804a9d5027 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/plugins/Plugin.java
@@ -27,5 +27,5 @@ public interface Plugin
/**
* Provide Configuration to this plugin
*/
- public void configure(ConfigurationPlugin config);
+ public void configure(ConfigurationPlugin config) throws ConfigurationException;
}
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 a6bab017a1..dab6c3b231 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,39 +18,56 @@
*/
package org.apache.qpid.server.plugins;
-import static org.apache.felix.framework.util.FelixConstants.*;
-import static org.apache.felix.main.AutoProcessor.*;
+import static org.apache.felix.framework.util.FelixConstants.SYSTEMBUNDLE_ACTIVATORS_PROP;
+import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_ACTION_PROPERY;
+import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_DIR_PROPERY;
+import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_INSTALL_VALUE;
+import static org.apache.felix.main.AutoProcessor.AUTO_DEPLOY_START_VALUE;
+import static org.apache.felix.main.AutoProcessor.process;
+import static org.osgi.framework.Constants.FRAMEWORK_STORAGE;
+import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN;
+import static org.osgi.framework.Constants.FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
+import static org.osgi.framework.Constants.FRAMEWORK_SYSTEMPACKAGES;
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.apache.qpid.common.Closeable;
+import org.apache.qpid.common.QpidProperties;
import org.apache.qpid.server.configuration.TopicConfiguration;
+import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionConfiguration.SlowConsumerDetectionConfigurationFactory;
import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionPolicyConfiguration.SlowConsumerDetectionPolicyConfigurationFactory;
import org.apache.qpid.server.configuration.plugins.SlowConsumerDetectionQueueConfiguration.SlowConsumerDetectionQueueConfigurationFactory;
-import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
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.AllowAll;
import org.apache.qpid.server.security.access.plugins.DenyAll;
import org.apache.qpid.server.security.access.plugins.LegacyAccess;
-import org.apache.qpid.server.virtualhost.plugins.VirtualHostPluginFactory;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory;
+import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
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 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;
@@ -63,7 +80,6 @@ public class PluginManager implements Closeable
private static final Logger _logger = Logger.getLogger(PluginManager.class);
private static final int FELIX_STOP_TIMEOUT = 30000;
- private static final String QPID_VER_SUFFIX = "version=0.9,";
private Framework _felix;
@@ -72,15 +88,61 @@ public class PluginManager implements Closeable
private ServiceTracker _configTracker = null;
private ServiceTracker _virtualHostTracker = null;
private ServiceTracker _policyTracker = null;
+ private ServiceTracker _authenticationManagerTracker = null;
private Activator _activator;
+ private final List<ServiceTracker> _trackers = new ArrayList<ServiceTracker>();
private Map<String, SecurityPluginFactory> _securityPlugins = new HashMap<String, SecurityPluginFactory>();
private Map<List<String>, ConfigurationPluginFactory> _configPlugins = new IdentityHashMap<List<String>, ConfigurationPluginFactory>();
private Map<String, VirtualHostPluginFactory> _vhostPlugins = new HashMap<String, VirtualHostPluginFactory>();
private Map<String, SlowConsumerPolicyPluginFactory> _policyPlugins = new HashMap<String, SlowConsumerPolicyPluginFactory>();
+ private Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> _authenticationManagerPlugins = new HashMap<String, AuthenticationManagerPluginFactory<? extends Plugin>>();
- public PluginManager(String pluginPath, String cachePath) throws Exception
+ /** 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
+ {
+ final String filename = System.getProperty(FILE_PROPERTY);
+ final InputStream is = FileUtils.openFileOrDefaultResource(filename, DEFAULT_RESOURCE_NAME,
+ PluginManager.class.getClassLoader());
+
+ try
+ {
+ Version qpidReleaseVersion;
+ try
+ {
+ qpidReleaseVersion = Version.parseVersion(QpidProperties.getReleaseVersion());
+ }
+ catch (IllegalArgumentException iae)
+ {
+ 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)
+ {
+ _logger.error("Error reading OSGI system package list", e);
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+
+ public PluginManager(String pluginPath, String cachePath, BundleContext bundleContext) throws Exception
{
// Store all non-OSGi plugins
// A little gross that we have to add them here, but not all the plugins are OSGIfied
@@ -97,7 +159,8 @@ public class PluginManager implements Closeable
LegacyAccess.LegacyAccessConfiguration.FACTORY,
new SlowConsumerDetectionConfigurationFactory(),
new SlowConsumerDetectionPolicyConfigurationFactory(),
- new SlowConsumerDetectionQueueConfigurationFactory()))
+ new SlowConsumerDetectionQueueConfigurationFactory(),
+ PrincipalDatabaseAuthenticationManager.PrincipalDatabaseAuthenticationManagerConfiguration.FACTORY))
{
_configPlugins.put(configFactory.getParentPaths(), configFactory);
}
@@ -112,125 +175,109 @@ public class PluginManager implements Closeable
_vhostPlugins.put(pluginFactory.getClass().getName(), pluginFactory);
}
- // Check the plugin directory path is set and exist
- if (pluginPath == null)
+ for (AuthenticationManagerPluginFactory<? extends Plugin> pluginFactory : Arrays.asList(
+ PrincipalDatabaseAuthenticationManager.FACTORY))
{
- return;
+ _authenticationManagerPlugins.put(pluginFactory.getPluginName(), pluginFactory);
}
- File pluginDir = new File(pluginPath);
- if (!pluginDir.exists())
- {
- return;
- }
-
- // Setup OSGi configuration propery map
- StringMap configMap = new StringMap(false);
-
- // Add the bundle provided service interface package and the core OSGi
- // packages to be exported from the class path via the system bundle.
- configMap.put(FRAMEWORK_SYSTEMPACKAGES,
- "org.osgi.framework; version=1.3.0," +
- "org.osgi.service.packageadmin; version=1.2.0," +
- "org.osgi.service.startlevel; version=1.0.0," +
- "org.osgi.service.url; version=1.0.0," +
- "org.osgi.util.tracker; version=1.0.0," +
- "org.apache.qpid.junit.extensions.util; " + QPID_VER_SUFFIX +
- "org.apache.qpid; " + QPID_VER_SUFFIX +
- "org.apache.qpid.common; " + QPID_VER_SUFFIX +
- "org.apache.qpid.exchange; " + QPID_VER_SUFFIX +
- "org.apache.qpid.framing; " + QPID_VER_SUFFIX +
- "org.apache.qpid.management.common.mbeans.annotations; " + QPID_VER_SUFFIX +
- "org.apache.qpid.protocol; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.binding; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.configuration; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.configuration.plugins; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.configuration.management; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.exchange; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.logging; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.logging.actors; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.logging.subjects; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.management; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.persistent; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.plugins; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.protocol; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.queue; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.registry; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.security; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.security.access; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.security.access.plugins; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.virtualhost; " + QPID_VER_SUFFIX +
- "org.apache.qpid.server.virtualhost.plugins; " + QPID_VER_SUFFIX +
- "org.apache.qpid.util; " + QPID_VER_SUFFIX +
- "org.apache.commons.configuration; version=1.0.0," +
- "org.apache.commons.lang; version=1.0.0," +
- "org.apache.commons.lang.builder; version=1.0.0," +
- "org.apache.commons.logging; version=1.0.0," +
- "org.apache.log4j; version=1.2.12," +
- "javax.management.openmbean; version=1.0.0," +
- "javax.management; version=1.0.0"
- );
-
- // No automatic shutdown hook
- configMap.put("felix.shutdown.hook", "false");
-
- // Add system activator
- List<BundleActivator> activators = new ArrayList<BundleActivator>();
- _activator = new Activator();
- activators.add(_activator);
- configMap.put(SYSTEMBUNDLE_ACTIVATORS_PROP, activators);
- if (cachePath != null)
+ if(bundleContext == null)
{
- File cacheDir = new File(cachePath);
- if (!cacheDir.exists() && cacheDir.canWrite())
+ // Check the plugin directory path is set and exist
+ if (pluginPath == null)
{
- _logger.info("Creating plugin cache directory: " + cachePath);
- cacheDir.mkdir();
+ _logger.info("No plugin path specified, no plugins will be loaded.");
+ return;
}
-
- // Set plugin cache directory and empty it
- _logger.info("Cache bundles in directory " + cachePath);
- configMap.put(FRAMEWORK_STORAGE, cachePath);
- }
- configMap.put(FRAMEWORK_STORAGE_CLEAN, FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
-
- // Set directory with plugins to auto-deploy
- _logger.info("Auto deploying bundles from directory " + pluginPath);
- configMap.put(AUTO_DEPLOY_DIR_PROPERY, pluginPath);
- configMap.put(AUTO_DEPLOY_ACTION_PROPERY, AUTO_DEPLOY_INSTALL_VALUE + "," + AUTO_DEPLOY_START_VALUE);
-
- // Start plugin manager and trackers
- _felix = new Felix(configMap);
- try
- {
- _logger.info("Starting plugin manager...");
- _felix.init();
- process(configMap, _felix.getBundleContext());
- _felix.start();
- _logger.info("Started plugin manager");
+ File pluginDir = new File(pluginPath);
+ if (!pluginDir.exists())
+ {
+ _logger.warn("Plugin dir : " + pluginDir + " does not exist.");
+ return;
+ }
+
+ // Add the bundle provided service interface package and the core OSGi
+ // packages to be exported from the class path via the system bundle.
+
+ // Setup OSGi configuration property map
+ final StringMap configMap = new StringMap(false);
+ configMap.put(FRAMEWORK_SYSTEMPACKAGES, OSGI_SYSTEM_PACKAGES);
+
+ // No automatic shutdown hook
+ configMap.put("felix.shutdown.hook", "false");
+
+ // Add system activator
+ List<BundleActivator> activators = new ArrayList<BundleActivator>();
+ _activator = new Activator();
+ activators.add(_activator);
+ configMap.put(SYSTEMBUNDLE_ACTIVATORS_PROP, activators);
+
+ if (cachePath != null)
+ {
+ File cacheDir = new File(cachePath);
+ if (!cacheDir.exists() && cacheDir.canWrite())
+ {
+ _logger.info("Creating plugin cache directory: " + cachePath);
+ cacheDir.mkdir();
+ }
+
+ // Set plugin cache directory and empty it
+ _logger.info("Cache bundles in directory " + cachePath);
+ configMap.put(FRAMEWORK_STORAGE, cachePath);
+ }
+ configMap.put(FRAMEWORK_STORAGE_CLEAN, FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT);
+
+ // Set directory with plugins to auto-deploy
+ _logger.info("Auto deploying bundles from directory " + pluginPath);
+ configMap.put(AUTO_DEPLOY_DIR_PROPERY, pluginPath);
+ configMap.put(AUTO_DEPLOY_ACTION_PROPERY, AUTO_DEPLOY_INSTALL_VALUE + "," + AUTO_DEPLOY_START_VALUE);
+
+ // Start plugin manager
+ _felix = new Felix(configMap);
+ try
+ {
+ _logger.info("Starting plugin manager framework");
+ _felix.init();
+ process(configMap, _felix.getBundleContext());
+ _felix.start();
+ _logger.info("Started plugin manager framework");
+ }
+ catch (BundleException e)
+ {
+ throw new ConfigurationException("Could not start plugin manager: " + e.getMessage(), e);
+ }
+
+ bundleContext = _activator.getContext();
}
- catch (BundleException e)
+ else
{
- throw new ConfigurationException("Could not start plugin manager: " + e.getMessage(), e);
+ _logger.info("Using the specified external BundleContext");
}
-
- // TODO save trackers in a map, keyed by class name
-
- _exchangeTracker = new ServiceTracker(_activator.getContext(), ExchangeType.class.getName(), null);
+
+ _exchangeTracker = new ServiceTracker(bundleContext, ExchangeType.class.getName(), null);
_exchangeTracker.open();
+ _trackers.add(_exchangeTracker);
- _securityTracker = new ServiceTracker(_activator.getContext(), SecurityPluginFactory.class.getName(), null);
+ _securityTracker = new ServiceTracker(bundleContext, SecurityPluginFactory.class.getName(), null);
_securityTracker.open();
+ _trackers.add(_securityTracker);
- _configTracker = new ServiceTracker(_activator.getContext(), ConfigurationPluginFactory.class.getName(), null);
+ _configTracker = new ServiceTracker(bundleContext, ConfigurationPluginFactory.class.getName(), null);
_configTracker.open();
+ _trackers.add(_configTracker);
- _virtualHostTracker = new ServiceTracker(_activator.getContext(), VirtualHostPluginFactory.class.getName(), null);
+ _virtualHostTracker = new ServiceTracker(bundleContext, VirtualHostPluginFactory.class.getName(), null);
_virtualHostTracker.open();
+ _trackers.add(_virtualHostTracker);
- _policyTracker = new ServiceTracker(_activator.getContext(), SlowConsumerPolicyPluginFactory.class.getName(), null);
+ _policyTracker = new ServiceTracker(bundleContext, SlowConsumerPolicyPluginFactory.class.getName(), null);
_policyTracker.open();
-
+ _trackers.add(_policyTracker);
+
+ _authenticationManagerTracker = new ServiceTracker(bundleContext, AuthenticationManagerPluginFactory.class.getName(), null);
+ _authenticationManagerTracker.open();
+ _trackers.add(_authenticationManagerTracker);
+
_logger.info("Opened service trackers");
}
@@ -301,22 +348,26 @@ public class PluginManager implements Closeable
return getServices(_securityTracker, _securityPlugins);
}
+ public Map<String, AuthenticationManagerPluginFactory<? extends Plugin>> getAuthenticationManagerPlugins()
+ {
+ return getServices(_authenticationManagerTracker, _authenticationManagerPlugins);
+ }
+
public void close()
{
- if (_felix != null)
+ try
{
- try
+ // Close all bundle trackers
+ for(ServiceTracker tracker : _trackers)
{
- // Close all bundle trackers
- _exchangeTracker.close();
- _securityTracker.close();
- _configTracker.close();
- _virtualHostTracker.close();
- _policyTracker.close();
+ tracker.close();
}
- finally
+ }
+ finally
+ {
+ if (_felix != null)
{
- _logger.info("Stopping plugin manager");
+ _logger.info("Stopping plugin manager framework");
try
{
// FIXME should be stopAndWait() but hangs VM, need upgrade in felix
@@ -335,7 +386,12 @@ public class PluginManager implements Closeable
{
// Ignore
}
- _logger.info("Stopped plugin manager");
+ _logger.info("Stopped plugin manager framework");
+ }
+ else
+ {
+ _logger.info("Plugin manager was started with an external BundleContext, " +
+ "skipping remaining shutdown tasks");
}
}
}
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 bcda385f64..b51e6aff1a 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
@@ -20,14 +20,35 @@
*/
package org.apache.qpid.server.protocol;
-import org.apache.qpid.protocol.AMQConstant;
+import java.util.List;
+import java.util.UUID;
+
import org.apache.qpid.AMQException;
+import org.apache.qpid.protocol.AMQConstant;
+import org.apache.qpid.server.logging.LogSubject;
+import org.apache.qpid.server.stats.StatisticsGatherer;
-public interface AMQConnectionModel
+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;
/**
* Close the given requested Session
+ *
* @param session
* @param cause
* @param message
@@ -36,4 +57,20 @@ public interface AMQConnectionModel
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();
+
+ /**
+ * Return a {@link LogSubject} for the connection.
+ */
+ public LogSubject getLogSubject();
+
+ public String getUserName();
+
+ public boolean isSessionNameUnique(String name);
}
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 a1ffe272fd..bff0a79de1 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,7 +20,9 @@
*/
package org.apache.qpid.server.protocol;
+import java.io.DataOutputStream;
import java.io.IOException;
+import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
@@ -30,18 +32,16 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
-import java.util.Map.Entry;
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.atomic.AtomicLong;
import javax.management.JMException;
+import javax.security.auth.Subject;
import javax.security.sasl.SaslServer;
import org.apache.log4j.Logger;
-import org.apache.mina.transport.vmpipe.VmPipeAddress;
import org.apache.qpid.AMQChannelException;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.AMQException;
@@ -66,12 +66,10 @@ import org.apache.qpid.framing.MethodDispatcher;
import org.apache.qpid.framing.MethodRegistry;
import org.apache.qpid.framing.ProtocolInitiation;
import org.apache.qpid.framing.ProtocolVersion;
-import org.apache.qpid.pool.Job;
-import org.apache.qpid.pool.ReferenceCountingExecutorService;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.protocol.AMQMethodEvent;
import org.apache.qpid.protocol.AMQMethodListener;
-import org.apache.qpid.protocol.ProtocolEngine;
+import org.apache.qpid.protocol.ServerProtocolEngine;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.configuration.ConfigStore;
import org.apache.qpid.server.configuration.ConfiguredObject;
@@ -90,21 +88,22 @@ 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.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;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.qpid.transport.NetworkDriver;
import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.transport.network.NetworkConnection;
-public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig
+public class AMQProtocolEngine implements ServerProtocolEngine, Managable, AMQProtocolSession, ConnectionConfig
{
private static final Logger _logger = Logger.getLogger(AMQProtocolEngine.class);
private static final String CLIENT_PROPERTIES_INSTANCE = ClientProperties.instance.toString();
- private static final AtomicLong idGenerator = new AtomicLong(0);
-
// to save boxing the channelId and looking up in a map... cache in an array the low numbered
// channels. This value must be of the form 2^x - 1.
private static final int CHANNEL_CACHE_SIZE = 0xff;
@@ -134,7 +133,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
private Object _lastSent;
protected volatile boolean _closed;
-
+
// maximum number of channels this session should have
private long _maxNoOfChannels = ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount();
@@ -146,47 +145,46 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
private Map<Integer, Long> _closingChannelsList = new ConcurrentHashMap<Integer, Long>();
private ProtocolOutputConverter _protocolOutputConverter;
- private Principal _authorizedID;
+ private Subject _authorizedSubject;
private MethodDispatcher _dispatcher;
private ProtocolSessionIdentifier _sessionIdentifier;
- // Create a simple ID that increments for ever new Session
- private final long _sessionID = idGenerator.getAndIncrement();
+ private final long _sessionID;
private AMQPConnectionActor _actor;
private LogSubject _logSubject;
- private NetworkDriver _networkDriver;
-
private long _lastIoTime;
private long _writtenBytes;
private long _readBytes;
- private Job _readJob;
- private Job _writeJob;
- private ReferenceCountingExecutorService _poolReference = ReferenceCountingExecutorService.getInstance();
private long _maxFrameSize;
private final AtomicBoolean _closing = new AtomicBoolean(false);
private final UUID _id;
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;
+ private Sender<ByteBuffer> _sender;
+
public ManagedObject getManagedObject()
{
return _managedObject;
}
- public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkDriver driver)
+ public AMQProtocolEngine(VirtualHostRegistry virtualHostRegistry, NetworkConnection network, final long connectionId)
{
_stateManager = new AMQStateManager(virtualHostRegistry, this);
- _networkDriver = driver;
-
_codecFactory = new AMQCodecFactory(true, this);
- _poolReference.acquireExecutorService();
- _readJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, true);
- _writeJob = new Job(_poolReference, Job.MAX_JOB_EVENTS, false);
+
+ setNetworkConnection(network);
+ _sessionID = connectionId;
_actor = new AMQPConnectionActor(this, virtualHostRegistry.getApplicationRegistry().getRootMessageLogger());
@@ -195,9 +193,21 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
_configStore = virtualHostRegistry.getConfigStore();
_id = _configStore.createId();
-
_actor.message(ConnectionMessages.OPEN(null, null, false, false));
+ _registry = virtualHostRegistry.getApplicationRegistry();
+ initialiseStatistics();
+ }
+
+ public void setNetworkConnection(NetworkConnection network)
+ {
+ setNetworkConnection(network, network.getSender());
+ }
+
+ public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+ {
+ _network = network;
+ _sender = sender;
}
private AMQProtocolSessionMBean createMBean() throws JMException
@@ -236,26 +246,18 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
try
{
final ArrayList<AMQDataBlock> dataBlocks = _codecFactory.getDecoder().decodeBuffer(msg);
- Job.fireAsynchEvent(_poolReference.getPool(), _readJob, new Runnable()
+ for (AMQDataBlock dataBlock : dataBlocks)
{
- public void run()
+ try
{
- // Decode buffer
-
- for (AMQDataBlock dataBlock : dataBlocks)
- {
- try
- {
- dataBlockReceived(dataBlock);
- }
- catch (Exception e)
- {
- _logger.error("Unexpected exception when processing datablock", e);
- closeProtocolSession();
- }
- }
+ dataBlockReceived(dataBlock);
}
- });
+ catch (Exception e)
+ {
+ _logger.error("Unexpected exception when processing datablock", e);
+ closeProtocolSession();
+ }
+ }
}
catch (Exception e)
{
@@ -333,6 +335,11 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
closeChannel(channelId);
throw e;
}
+ catch (TransportException e)
+ {
+ closeChannel(channelId);
+ throw e;
+ }
}
finally
{
@@ -343,7 +350,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
private void protocolInitiationReceived(ProtocolInitiation pi)
{
// this ensures the codec never checks for a PI message again
- ((AMQDecoder) _codecFactory.getDecoder()).setExpectProtocolInitiation(false);
+ (_codecFactory.getDecoder()).setExpectProtocolInitiation(false);
try
{
// Log incomming protocol negotiation request
@@ -363,15 +370,49 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
null,
mechanisms.getBytes(),
locales.getBytes());
- _networkDriver.send(responseBody.generateFrame(0).toNioByteBuffer());
+ _sender.send(asByteBuffer(responseBody.generateFrame(0)));
+ _sender.flush();
}
catch (AMQException e)
{
_logger.info("Received unsupported protocol initiation for protocol version: " + getProtocolVersion());
- _networkDriver.send(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()).toNioByteBuffer());
+ _sender.send(asByteBuffer(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion())));
+ _sender.flush();
+ }
+ }
+
+ private ByteBuffer asByteBuffer(AMQDataBlock block)
+ {
+ final ByteBuffer buf = ByteBuffer.allocate((int) block.getSize());
+
+ try
+ {
+ block.writePayload(new DataOutputStream(new OutputStream()
+ {
+
+
+ @Override
+ public void write(int b) throws IOException
+ {
+ buf.put((byte) b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException
+ {
+ buf.put(b, off, len);
+ }
+ }));
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException(e);
}
+
+ buf.flip();
+ return buf;
}
public void methodFrameReceived(int channelId, AMQMethodBody methodBody)
@@ -426,19 +467,19 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
AMQConstant.CHANNEL_ERROR.getName().toString());
_logger.info(e.getMessage() + " whilst processing:" + methodBody);
- closeConnection(channelId, ce, false);
+ closeConnection(channelId, ce);
}
}
catch (AMQConnectionException e)
{
_logger.info(e.getMessage() + " whilst processing:" + methodBody);
- closeConnection(channelId, e, false);
+ closeConnection(channelId, e);
}
catch (AMQSecurityException e)
{
AMQConnectionException ce = evt.getMethod().getConnectionException(AMQConstant.ACCESS_REFUSED, e.getMessage());
_logger.info(e.getMessage() + " whilst processing:" + methodBody);
- closeConnection(channelId, ce, false);
+ closeConnection(channelId, ce);
}
}
catch (Exception e)
@@ -481,19 +522,14 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
*
* @param frame the frame to write
*/
- public void writeFrame(AMQDataBlock frame)
+ public synchronized void writeFrame(AMQDataBlock frame)
{
_lastSent = frame;
- final ByteBuffer buf = frame.toNioByteBuffer();
+ final ByteBuffer buf = asByteBuffer(frame);
_lastIoTime = System.currentTimeMillis();
_writtenBytes += buf.remaining();
- Job.fireAsynchEvent(_poolReference.getPool(), _writeJob, new Runnable()
- {
- public void run()
- {
- _networkDriver.send(buf);
- }
- });
+ _sender.send(buf);
+ _sender.flush();
}
public AMQShortString getContextKey()
@@ -683,8 +719,8 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
if (delay > 0)
{
- _networkDriver.setMaxWriteIdle(delay);
- _networkDriver.setMaxReadIdle((int) (ApplicationRegistry.getInstance().getConfiguration().getHeartBeatTimeout() * delay));
+ _network.setMaxWriteIdle(delay);
+ _network.setMaxReadIdle((int) (ApplicationRegistry.getInstance().getConfiguration().getHeartBeatTimeout() * delay));
}
}
@@ -725,7 +761,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
}
closeAllChannels();
-
+
getConfigStore().removeConfiguredObject(this);
if (_managedObject != null)
@@ -745,7 +781,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
_closed = true;
notifyAll();
}
- _poolReference.releaseExecutorService();
CurrentActor.get().message(_logSubject, ConnectionMessages.CLOSE());
}
}
@@ -768,27 +803,32 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
}
}
- public void closeConnection(int channelId, AMQConnectionException e, boolean closeProtocolSession) throws AMQException
+ public void closeConnection(int channelId, AMQConnectionException e) throws AMQException
{
- if (_logger.isInfoEnabled())
+ try
{
- _logger.info("Closing connection due to: " + e);
- }
-
- markChannelAwaitingCloseOk(channelId);
- closeSession();
- _stateManager.changeState(AMQState.CONNECTION_CLOSING);
- writeFrame(e.getCloseFrame(channelId));
+ if (_logger.isInfoEnabled())
+ {
+ _logger.info("Closing connection due to: " + e);
+ }
- if (closeProtocolSession)
+ markChannelAwaitingCloseOk(channelId);
+ closeSession();
+ _stateManager.changeState(AMQState.CONNECTION_CLOSING);
+ writeFrame(e.getCloseFrame(channelId));
+ }
+ finally
{
closeProtocolSession();
}
+
+
}
public void closeProtocolSession()
{
- _networkDriver.close();
+ _network.close();
+
try
{
_stateManager.changeState(AMQState.CONNECTION_CLOSED);
@@ -797,11 +837,15 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
_logger.info(e.getMessage());
}
+ catch (TransportException e)
+ {
+ _logger.info(e.getMessage());
+ }
}
public String toString()
{
- return getRemoteAddress() + "(" + (getAuthorizedID() == null ? "?" : getAuthorizedID().getName() + ")");
+ return getRemoteAddress() + "(" + (getAuthorizedPrincipal() == null ? "?" : getAuthorizedPrincipal().getName() + ")");
}
public String dump()
@@ -823,17 +867,11 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
*/
public String getLocalFQDN()
{
- SocketAddress address = _networkDriver.getLocalAddress();
- // we use the vmpipe address in some tests hence the need for this rather ugly test. The host
- // information is used by SASL primary.
+ SocketAddress address = _network.getLocalAddress();
if (address instanceof InetSocketAddress)
{
return ((InetSocketAddress) address).getHostName();
}
- else if (address instanceof VmPipeAddress)
- {
- return "vmpipe:" + ((VmPipeAddress) address).getPort();
- }
else
{
throw new IllegalArgumentException("Unsupported socket address class: " + address);
@@ -912,7 +950,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
public Object getClientIdentifier()
{
- return (_networkDriver != null) ? _networkDriver.getRemoteAddress() : null;
+ return _network.getRemoteAddress();
}
public VirtualHost getVirtualHost()
@@ -925,7 +963,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
_virtualHost = virtualHost;
_virtualHost.getConnectionRegistry().registerConnection(this);
-
+
_configStore.addConfiguredObject(this);
try
@@ -954,29 +992,33 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
return _protocolOutputConverter;
}
- public void setAuthorizedID(Principal authorizedID)
+ public void setAuthorizedSubject(final Subject authorizedSubject)
{
- _authorizedID = authorizedID;
+ if (authorizedSubject == null)
+ {
+ throw new IllegalArgumentException("authorizedSubject cannot be null");
+ }
+ _authorizedSubject = authorizedSubject;
}
- public Principal getAuthorizedID()
+ public Subject getAuthorizedSubject()
{
- return _authorizedID;
+ return _authorizedSubject;
}
- public Principal getPrincipal()
+ public Principal getAuthorizedPrincipal()
{
- return _authorizedID;
+ return _authorizedSubject == null ? null : UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
}
public SocketAddress getRemoteAddress()
{
- return _networkDriver.getRemoteAddress();
+ return _network.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _networkDriver.getLocalAddress();
+ return _network.getLocalAddress();
}
public MethodRegistry getMethodRegistry()
@@ -999,6 +1041,10 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
_logger.error("Could not close protocol engine", e);
}
+ catch (TransportException e)
+ {
+ _logger.error("Could not close protocol engine", e);
+ }
}
public void readerIdle()
@@ -1006,14 +1052,9 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
// Nothing
}
- public void setNetworkDriver(NetworkDriver driver)
- {
- _networkDriver = driver;
- }
-
public void writerIdle()
{
- _networkDriver.send(HeartbeatBody.FRAME.toNioByteBuffer());
+ _sender.send(asByteBuffer(HeartbeatBody.FRAME));
}
public void exception(Throwable throwable)
@@ -1021,7 +1062,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
if (throwable instanceof AMQProtocolHeaderException)
{
writeFrame(new ProtocolInitiation(ProtocolVersion.getLatestSupportedVersion()));
- _networkDriver.close();
+ _sender.close();
_logger.error("Error in protocol initiation " + this + ":" + getRemoteAddress() + " :" + throwable.getMessage(), throwable);
}
@@ -1039,7 +1080,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
writeFrame(closeBody.generateFrame(0));
- _networkDriver.close();
+ _sender.close();
}
}
@@ -1078,19 +1119,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
return (_clientVersion == null) ? null : _clientVersion.toString();
}
- public void closeIfLingeringClosedChannels()
- {
- for (Entry<Integer, Long>id : _closingChannelsList.entrySet())
- {
- if (id.getValue() + 30000 > System.currentTimeMillis())
- {
- // We have a channel that we closed 30 seconds ago. Client's dead, kill the connection
- _logger.error("Closing connection as channel was closed more than 30 seconds ago and no ChannelCloseOk has been processed");
- closeProtocolSession();
- }
- }
- }
-
public Boolean isIncoming()
{
return true;
@@ -1108,7 +1136,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
public String getAuthId()
{
- return getAuthorizedID().getName();
+ return getAuthorizedPrincipal().getName();
}
public Integer getRemotePID()
@@ -1170,7 +1198,7 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
{
return false;
}
-
+
public void mgmtClose()
{
MethodRegistry methodRegistry = getMethodRegistry();
@@ -1263,7 +1291,6 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
public void closeSession(AMQSessionModel session, AMQConstant cause, String message) throws AMQException
{
-
closeChannel((Integer)session.getID());
MethodRegistry methodRegistry = getMethodRegistry();
@@ -1273,6 +1300,110 @@ public class AMQProtocolEngine implements ProtocolEngine, Managable, AMQProtocol
new AMQShortString(message),
0,0);
- writeFrame(responseBody.generateFrame((Integer)session.getID()));
- }
+ writeFrame(responseBody.generateFrame((Integer)session.getID()));
+ }
+
+ public void close(AMQConstant cause, String message) throws AMQException
+ {
+ closeConnection(0, new AMQConnectionException(cause, message, 0, 0,
+ getProtocolOutputConverter().getProtocolMajorVersion(),
+ getProtocolOutputConverter().getProtocolMinorVersion(),
+ (Throwable) null));
+ }
+
+ public List<AMQSessionModel> getSessionModels()
+ {
+ List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
+ for (AMQChannel channel : getChannels())
+ {
+ sessions.add((AMQSessionModel) channel);
+ }
+ return sessions;
+ }
+
+ public LogSubject getLogSubject()
+ {
+ return _logSubject;
+ }
+
+ public void registerMessageDelivered(long messageSize)
+ {
+ if (isStatisticsEnabled())
+ {
+ _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);
+ }
+ _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();
+ _dataDelivered.reset();
+ _messagesReceived.reset();
+ _dataReceived.reset();
+ }
+
+ 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()
+ {
+ return _statisticsEnabled;
+ }
+
+ public void setStatisticsEnabled(boolean enabled)
+ {
+ _statisticsEnabled = enabled;
+ }
+
+ @Override
+ public boolean isSessionNameUnique(String name)
+ {
+ return true;
+ }
+
+ @Override
+ public String getUserName()
+ {
+ return getAuthorizedPrincipal().getName();
+ }
}
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 f48a214933..c1b5b02f8f 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,6 +20,7 @@
*/
package org.apache.qpid.server.protocol;
+import javax.security.auth.Subject;
import javax.security.sasl.SaslServer;
import org.apache.qpid.AMQException;
@@ -28,16 +29,15 @@ import org.apache.qpid.framing.*;
import org.apache.qpid.AMQConnectionException;
import org.apache.qpid.protocol.AMQVersionAwareProtocolSession;
import org.apache.qpid.server.AMQChannel;
-import org.apache.qpid.server.security.PrincipalHolder;
+import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.output.ProtocolOutputConverter;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import java.security.Principal;
import java.util.List;
-public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, PrincipalHolder, AMQConnectionModel
+public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, AuthorizationHolder, AMQConnectionModel
{
long getSessionID();
@@ -163,8 +163,10 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Prin
/** This must be called when the session is _closed in order to free up any resources managed by the session. */
void closeSession() throws AMQException;
+ 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, boolean closeProtocolSession) throws AMQException;
+ void closeConnection(int channelId, AMQConnectionException e) throws AMQException;
/** @return a key that uniquely identifies this session */
@@ -205,7 +207,7 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Prin
public ProtocolOutputConverter getProtocolOutputConverter();
- void setAuthorizedID(Principal authorizedID);
+ void setAuthorizedSubject(Subject authorizedSubject);
public java.net.SocketAddress getRemoteAddress();
@@ -231,7 +233,5 @@ public interface AMQProtocolSession extends AMQVersionAwareProtocolSession, Prin
List<AMQChannel> getChannels();
- void closeIfLingeringClosedChannels();
-
void mgmtCloseChannel(int channelId);
}
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
index f4f2cab2c2..16d99de492 100644
--- 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
@@ -37,25 +37,15 @@
*/
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.ManagedConnection;
-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.AMQManagedObject;
-import org.apache.qpid.server.management.ManagedObject;
+import java.util.Date;
+import java.util.List;
import javax.management.JMException;
import javax.management.MBeanException;
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.CompositeData;
import javax.management.openmbean.CompositeDataSupport;
@@ -66,8 +56,20 @@ import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
-import java.util.Date;
-import java.util.List;
+
+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.ManagedConnection;
+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.AMQManagedObject;
+import org.apache.qpid.server.management.ManagedObject;
/**
* This MBean class implements the management interface. In order to make more attributes, operations and notifications
@@ -94,8 +96,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
super(ManagedConnection.class, ManagedConnection.TYPE);
_protocolSession = amqProtocolSession;
String remote = getRemoteAddress();
- remote = "anonymous".equals(remote) ? (remote + hashCode()) : remote;
- _name = jmxEncode(new StringBuffer(remote), 0).toString();
+ _name = "anonymous".equals(remote) ? (remote + hashCode()) : remote;
init();
}
@@ -130,7 +131,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
public String getAuthorizedId()
{
- return (_protocolSession.getPrincipal() != null ) ? _protocolSession.getPrincipal().getName() : null;
+ return (_protocolSession.getAuthorizedPrincipal() != null ) ? _protocolSession.getAuthorizedPrincipal().getName() : null;
}
public String getVersion()
@@ -175,7 +176,7 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
public String getObjectInstanceName()
{
- return _name;
+ return ObjectName.quote(_name);
}
/**
@@ -339,4 +340,78 @@ public class AMQProtocolSessionMBean extends AMQManagedObject implements Managed
_broadcaster.sendNotification(n);
}
-} // End of MBean class
+ 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 a9b2354d75..bc63403a86 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
@@ -20,15 +20,35 @@
*/
package org.apache.qpid.server.protocol;
+import org.apache.qpid.AMQException;
import org.apache.qpid.server.logging.LogSubject;
public interface AMQSessionModel
{
- Object getID();
+ public Object getID();
- AMQConnectionModel getConnectionModel();
+ public AMQConnectionModel getConnectionModel();
- String getClientID();
+ public String getClientID();
+
+ public void close() throws AMQException;
- LogSubject getLogSubject();
+ 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.
+ *
+ * @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
+ * @param idleClose time in milliseconds before closing connection with idle transaction
+ */
+ public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java
index 7e93623cab..e925d7a1ec 100755..100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/PrincipalHolder.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AmqpProtocolVersion.java
@@ -18,12 +18,6 @@
* under the License.
*
*/
-package org.apache.qpid.server.security;
+package org.apache.qpid.server.protocol;
-import java.security.Principal;
-
-public interface PrincipalHolder
-{
- /** @return a Principal that was used to authorized this session */
- Principal getPrincipal();
-}
+public enum AmqpProtocolVersion { v0_8, v0_9, v0_9_1, v0_10 } \ No newline at end of file
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 eb957ee33c..7033bf755d 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
@@ -22,45 +22,54 @@ package org.apache.qpid.server.protocol;
import org.apache.log4j.Logger;
-import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory.VERSION;
+import org.apache.qpid.protocol.ServerProtocolEngine;
import org.apache.qpid.server.registry.IApplicationRegistry;
import org.apache.qpid.server.transport.ServerConnection;
import org.apache.qpid.transport.ConnectionDelegate;
-import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.Sender;
+import org.apache.qpid.transport.network.NetworkConnection;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.util.Set;
-public class MultiVersionProtocolEngine implements ProtocolEngine
+public class MultiVersionProtocolEngine implements ServerProtocolEngine
{
private static final Logger _logger = Logger.getLogger(MultiVersionProtocolEngine.class);
+ private final long _id;
-
- private NetworkDriver _networkDriver;
- private Set<VERSION> _supported;
+ private Set<AmqpProtocolVersion> _supported;
private String _fqdn;
private IApplicationRegistry _appRegistry;
+ private NetworkConnection _network;
+ private Sender<ByteBuffer> _sender;
+
+ private volatile ServerProtocolEngine _delegate = new SelfDelegateProtocolEngine();
- private volatile ProtocolEngine _delegate = new SelfDelegateProtocolEngine();
+ public MultiVersionProtocolEngine(IApplicationRegistry appRegistry,
+ String fqdn,
+ Set<AmqpProtocolVersion> supported,
+ NetworkConnection network,
+ long id)
+ {
+ this(appRegistry,fqdn,supported,id);
+ setNetworkConnection(network);
+ }
public MultiVersionProtocolEngine(IApplicationRegistry appRegistry,
String fqdn,
- Set<VERSION> supported, NetworkDriver networkDriver)
+ Set<AmqpProtocolVersion> supported,
+ long id)
{
+ _id = id;
_appRegistry = appRegistry;
_fqdn = fqdn;
_supported = supported;
- _networkDriver = networkDriver;
- }
- public void setNetworkDriver(NetworkDriver driver)
- {
- _delegate.setNetworkDriver(driver);
}
+
public SocketAddress getRemoteAddress()
{
return _delegate.getRemoteAddress();
@@ -96,6 +105,7 @@ public class MultiVersionProtocolEngine implements ProtocolEngine
_delegate.readerIdle();
}
+
public void received(ByteBuffer msg)
{
_delegate.received(msg);
@@ -106,6 +116,11 @@ public class MultiVersionProtocolEngine implements ProtocolEngine
_delegate.exception(t);
}
+ public long getConnectionId()
+ {
+ return _delegate.getConnectionId();
+ }
+
private static final int MINIMUM_REQUIRED_HEADER_BYTES = 8;
private static final byte[] AMQP_0_8_HEADER =
@@ -130,7 +145,7 @@ public class MultiVersionProtocolEngine implements ProtocolEngine
(byte) 9
};
-private static final byte[] AMQP_0_9_1_HEADER =
+ private static final byte[] AMQP_0_9_1_HEADER =
new byte[] { (byte) 'A',
(byte) 'M',
(byte) 'Q',
@@ -153,19 +168,31 @@ private static final byte[] AMQP_0_9_1_HEADER =
(byte) 10
};
+ public void setNetworkConnection(NetworkConnection networkConnection)
+ {
+ setNetworkConnection(networkConnection, networkConnection.getSender());
+ }
+
+ public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+ {
+ _network = network;
+ _sender = sender;
+ }
+
+
private static interface DelegateCreator
{
- VERSION getVersion();
+ AmqpProtocolVersion getVersion();
byte[] getHeaderIdentifier();
- ProtocolEngine getProtocolEngine();
+ ServerProtocolEngine getProtocolEngine();
}
private DelegateCreator creator_0_8 = new DelegateCreator()
{
- public VERSION getVersion()
+ public AmqpProtocolVersion getVersion()
{
- return VERSION.v0_8;
+ return AmqpProtocolVersion.v0_8;
}
public byte[] getHeaderIdentifier()
@@ -173,18 +200,18 @@ private static final byte[] AMQP_0_9_1_HEADER =
return AMQP_0_8_HEADER;
}
- public ProtocolEngine getProtocolEngine()
+ public ServerProtocolEngine getProtocolEngine()
{
- return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id);
}
};
private DelegateCreator creator_0_9 = new DelegateCreator()
{
- public VERSION getVersion()
+ public AmqpProtocolVersion getVersion()
{
- return VERSION.v0_9;
+ return AmqpProtocolVersion.v0_9;
}
@@ -193,18 +220,18 @@ private static final byte[] AMQP_0_9_1_HEADER =
return AMQP_0_9_HEADER;
}
- public ProtocolEngine getProtocolEngine()
+ public ServerProtocolEngine getProtocolEngine()
{
- return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id);
}
};
private DelegateCreator creator_0_9_1 = new DelegateCreator()
{
- public VERSION getVersion()
+ public AmqpProtocolVersion getVersion()
{
- return VERSION.v0_9_1;
+ return AmqpProtocolVersion.v0_9_1;
}
@@ -213,9 +240,9 @@ private static final byte[] AMQP_0_9_1_HEADER =
return AMQP_0_9_1_HEADER;
}
- public ProtocolEngine getProtocolEngine()
+ public ServerProtocolEngine getProtocolEngine()
{
- return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _networkDriver);
+ return new AMQProtocolEngine(_appRegistry.getVirtualHostRegistry(), _network, _id);
}
};
@@ -223,9 +250,9 @@ private static final byte[] AMQP_0_9_1_HEADER =
private DelegateCreator creator_0_10 = new DelegateCreator()
{
- public VERSION getVersion()
+ public AmqpProtocolVersion getVersion()
{
- return VERSION.v0_10;
+ return AmqpProtocolVersion.v0_10;
}
@@ -234,15 +261,15 @@ private static final byte[] AMQP_0_9_1_HEADER =
return AMQP_0_10_HEADER;
}
- public ProtocolEngine getProtocolEngine()
+ public ServerProtocolEngine getProtocolEngine()
{
final ConnectionDelegate connDelegate =
new org.apache.qpid.server.transport.ServerConnectionDelegate(_appRegistry, _fqdn);
- ServerConnection conn = new ServerConnection();
+ ServerConnection conn = new ServerConnection(_id);
conn.setConnectionDelegate(connDelegate);
- return new ProtocolEngine_0_10( conn, _networkDriver, _appRegistry);
+ return new ProtocolEngine_0_10( conn, _network, _appRegistry);
}
};
@@ -250,21 +277,16 @@ private static final byte[] AMQP_0_9_1_HEADER =
new DelegateCreator[] { creator_0_8, creator_0_9, creator_0_9_1, creator_0_10 };
- private class ClosedDelegateProtocolEngine implements ProtocolEngine
+ private class ClosedDelegateProtocolEngine implements ServerProtocolEngine
{
- public void setNetworkDriver(NetworkDriver driver)
- {
- _networkDriver = driver;
- }
-
public SocketAddress getRemoteAddress()
{
- return _networkDriver.getRemoteAddress();
+ return _network.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _networkDriver.getLocalAddress();
+ return _network.getLocalAddress();
}
public long getWrittenBytes()
@@ -301,26 +323,30 @@ private static final byte[] AMQP_0_9_1_HEADER =
{
}
- }
- private class SelfDelegateProtocolEngine implements ProtocolEngine
- {
+ public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+ {
- private final ByteBuffer _header = ByteBuffer.allocate(MINIMUM_REQUIRED_HEADER_BYTES);
+ }
- public void setNetworkDriver(NetworkDriver driver)
+ public long getConnectionId()
{
- _networkDriver = driver;
+ return _id;
}
+ }
+
+ private class SelfDelegateProtocolEngine implements ServerProtocolEngine
+ {
+ private final ByteBuffer _header = ByteBuffer.allocate(MINIMUM_REQUIRED_HEADER_BYTES);
public SocketAddress getRemoteAddress()
{
- return _networkDriver.getRemoteAddress();
+ return _network.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _networkDriver.getLocalAddress();
+ return _network.getLocalAddress();
}
public long getWrittenBytes()
@@ -355,7 +381,7 @@ private static final byte[] AMQP_0_9_1_HEADER =
_header.get(headerBytes);
- ProtocolEngine newDelegate = null;
+ ServerProtocolEngine newDelegate = null;
byte[] newestSupported = null;
for(int i = 0; newDelegate == null && i < _creators.length; i++)
@@ -380,17 +406,20 @@ private static final byte[] AMQP_0_9_1_HEADER =
// If no delegate is found then send back the most recent support protocol version id
if(newDelegate == null)
{
- _networkDriver.send(ByteBuffer.wrap(newestSupported));
+ _sender.send(ByteBuffer.wrap(newestSupported));
+ _sender.flush();
_delegate = new ClosedDelegateProtocolEngine();
+
+ _network.close();
+
}
else
{
- newDelegate.setNetworkDriver(_networkDriver);
-
_delegate = newDelegate;
_header.flip();
+ _delegate.setNetworkConnection(_network, _sender);
_delegate.received(_header);
if(msg.hasRemaining())
{
@@ -402,6 +431,11 @@ private static final byte[] AMQP_0_9_1_HEADER =
}
+ public long getConnectionId()
+ {
+ return _id;
+ }
+
public void exception(Throwable t)
{
_logger.error("Error establishing session", t);
@@ -421,5 +455,10 @@ private static final byte[] AMQP_0_9_1_HEADER =
{
}
+
+ public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+ {
+
+ }
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
index 75358c42d9..7e327b221f 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactory.java
@@ -20,56 +20,38 @@
*/
package org.apache.qpid.server.protocol;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
+
import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.protocol.ServerProtocolEngine;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.registry.IApplicationRegistry;
-
-import java.util.Set;
-import java.util.Arrays;
-import java.util.HashSet;
+import org.apache.qpid.transport.network.NetworkConnection;
public class MultiVersionProtocolEngineFactory implements ProtocolEngineFactory
{
- ;
-
-
- public enum VERSION { v0_8, v0_9, v0_9_1, v0_10 };
-
- private static final Set<VERSION> ALL_VERSIONS = new HashSet<VERSION>(Arrays.asList(VERSION.values()));
+ private static final AtomicLong ID_GENERATOR = new AtomicLong(0);
private final IApplicationRegistry _appRegistry;
private final String _fqdn;
- private final Set<VERSION> _supported;
-
+ private final Set<AmqpProtocolVersion> _supported;
- public MultiVersionProtocolEngineFactory()
+ public MultiVersionProtocolEngineFactory(String fqdn, Set<AmqpProtocolVersion> supportedVersions)
{
- this(1, "localhost", ALL_VERSIONS);
- }
-
- public MultiVersionProtocolEngineFactory(String fqdn, Set<VERSION> versions)
- {
- this(1, fqdn, versions);
+ _appRegistry = ApplicationRegistry.getInstance();
+ _fqdn = fqdn;
+ _supported = supportedVersions;
}
-
- public MultiVersionProtocolEngineFactory(String fqdn)
+ public ServerProtocolEngine newProtocolEngine(NetworkConnection network)
{
- this(1, fqdn, ALL_VERSIONS);
+ return new MultiVersionProtocolEngine(_appRegistry, _fqdn, _supported, network, ID_GENERATOR.getAndIncrement());
}
- public MultiVersionProtocolEngineFactory(int instance, String fqdn, Set<VERSION> supportedVersions)
+ public ServerProtocolEngine newProtocolEngine()
{
- _appRegistry = ApplicationRegistry.getInstance(instance);
- _fqdn = fqdn;
- _supported = supportedVersions;
+ return new MultiVersionProtocolEngine(_appRegistry, _fqdn, _supported, ID_GENERATOR.getAndIncrement());
}
-
- public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver)
- {
- return new MultiVersionProtocolEngine(_appRegistry, _fqdn, _supported, networkDriver);
- }
}
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 30d506a89b..48a8a1bf42 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
@@ -20,25 +20,26 @@
*/
package org.apache.qpid.server.protocol;
-import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.protocol.ServerProtocolEngine;
+import org.apache.qpid.transport.Sender;
import org.apache.qpid.transport.network.InputHandler;
import org.apache.qpid.transport.network.Assembler;
import org.apache.qpid.transport.network.Disassembler;
+import org.apache.qpid.transport.network.NetworkConnection;
import org.apache.qpid.server.configuration.*;
import org.apache.qpid.server.transport.ServerConnection;
-import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
import org.apache.qpid.server.registry.IApplicationRegistry;
import java.net.SocketAddress;
+import java.nio.ByteBuffer;
import java.util.UUID;
-public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine, ConnectionConfig
+public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocolEngine, ConnectionConfig
{
public static final int MAX_FRAME_SIZE = 64 * 1024 - 1;
- private NetworkDriver _networkDriver;
+ private NetworkConnection _network;
private long _readBytes;
private long _writtenBytes;
private ServerConnection _connection;
@@ -47,26 +48,22 @@ public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine
private long _createTime = System.currentTimeMillis();
public ProtocolEngine_0_10(ServerConnection conn,
- NetworkDriver networkDriver,
+ NetworkConnection network,
final IApplicationRegistry appRegistry)
{
super(new Assembler(conn));
_connection = conn;
_connection.setConnectionConfig(this);
- _networkDriver = networkDriver;
+
_id = appRegistry.getConfigStore().createId();
_appRegistry = appRegistry;
- // FIXME Two log messages to maintain compatinbility with earlier protocol versions
- _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, false, false));
- _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", false, true));
- }
+ if(network != null)
+ {
+ setNetworkConnection(network);
+ }
+
- public void setNetworkDriver(NetworkDriver driver)
- {
- _networkDriver = driver;
- Disassembler dis = new Disassembler(driver, MAX_FRAME_SIZE);
- _connection.setSender(dis);
_connection.onOpen(new Runnable()
{
public void run()
@@ -77,14 +74,30 @@ public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine
}
+ public void setNetworkConnection(NetworkConnection network)
+ {
+ setNetworkConnection(network, network.getSender());
+ }
+
+ public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender)
+ {
+ _network = network;
+
+ _connection.setSender(new Disassembler(sender, MAX_FRAME_SIZE));
+
+ // FIXME Two log messages to maintain compatibility with earlier protocol versions
+ _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, false, false));
+ _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", false, true));
+ }
+
public SocketAddress getRemoteAddress()
{
- return _networkDriver.getRemoteAddress();
+ return _network.getRemoteAddress();
}
public SocketAddress getLocalAddress()
{
- return _networkDriver.getLocalAddress();
+ return _network.getLocalAddress();
}
public long getReadBytes()
@@ -134,7 +147,7 @@ public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine
public String getAuthId()
{
- return _connection.getAuthorizationID();
+ return _connection.getAuthorizedPrincipal() == null ? null : _connection.getAuthorizedPrincipal().getName();
}
public String getRemoteProcessName()
@@ -193,9 +206,14 @@ public class ProtocolEngine_0_10 extends InputHandler implements ProtocolEngine
{
return false;
}
-
+
public void mgmtClose()
{
_connection.mgmtClose();
}
+
+ public long getConnectionId()
+ {
+ return _connection.getConnectionId();
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
index b6e97e08fb..371ae0de50 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQPriorityQueue.java
@@ -60,7 +60,7 @@ public class AMQPriorityQueue extends SimpleAMQQueue
{
// check that all subscriptions are not in advance of the entry
SubscriptionList.SubscriptionNodeIterator subIter = _subscriptionList.iterator();
- while(subIter.advance() && !entry.isAcquired())
+ while(subIter.advance() && entry.isAvailable())
{
final Subscription subscription = subIter.getNode().getSubscription();
if(!subscription.isClosed())
@@ -70,7 +70,7 @@ public class AMQPriorityQueue extends SimpleAMQQueue
{
QueueEntry subnode = context._lastSeenEntry;
QueueEntry released = context._releasedEntry;
- while(subnode != null && entry.compareTo(subnode) < 0 && !entry.isAcquired() && (released == null || released.compareTo(entry) < 0))
+ while(subnode != null && entry.compareTo(subnode) < 0 && entry.isAvailable() && (released == null || released.compareTo(entry) < 0))
{
if(QueueContext._releasedUpdater.compareAndSet(context,released,entry))
{
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 de9dc42de8..9140a13625 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
@@ -21,21 +21,18 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQSecurityException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
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.binding.Binding;
import org.apache.qpid.server.configuration.QueueConfig;
-import org.apache.qpid.server.configuration.QueueConfiguration;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.exchange.ExchangeReferrer;
import org.apache.qpid.server.management.Managable;
import org.apache.qpid.server.management.ManagedObject;
-import org.apache.qpid.server.security.PrincipalHolder;
+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.txn.ServerTransaction;
@@ -72,8 +69,8 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
boolean isAutoDelete();
AMQShortString getOwner();
- PrincipalHolder getPrincipalHolder();
- void setPrincipalHolder(PrincipalHolder principalHolder);
+ AuthorizationHolder getAuthorizationHolder();
+ void setAuthorizationHolder(AuthorizationHolder principalHolder);
void setExclusiveOwningSession(AMQSessionModel owner);
AMQSessionModel getExclusiveOwningSession();
@@ -108,23 +105,16 @@ public interface AMQQueue extends Managable, Comparable<AMQQueue>, ExchangeRefer
boolean isDeleted();
-
int delete() throws AMQException;
-
void requeue(QueueEntry entry);
- void requeue(QueueEntryImpl storeContext, Subscription subscription);
-
void dequeue(QueueEntry entry, Subscription sub);
void decrementUnackedMsgCount();
-
boolean resend(final QueueEntry entry, final Subscription subscription) throws AMQException;
-
-
void addQueueDeleteTask(final Task task);
void removeQueueDeleteTask(final Task task);
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
index b5294b6d2f..c8eb118b11 100644
--- 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
@@ -43,6 +43,7 @@ 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;
@@ -97,7 +98,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
{
super(ManagedQueue.class, ManagedQueue.TYPE);
_queue = queue;
- _queueName = jmxEncode(new StringBuffer(queue.getNameShortString()), 0).toString();
+ _queueName = queue.getName();
}
public ManagedObject getParentObject()
@@ -147,7 +148,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
public String getObjectInstanceName()
{
- return _queueName;
+ return ObjectName.quote(_queueName);
}
public String getName()
@@ -506,7 +507,7 @@ public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue, Que
private String[] getMessageHeaderProperties(ContentHeaderBody headerBody)
{
List<String> list = new ArrayList<String>();
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.properties;
+ BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.getProperties();
list.add("reply-to = " + headerProperties.getReplyToAsString());
list.add("propertyFlags = " + headerProperties.getPropertyFlags());
list.add("ApplicationID = " + headerProperties.getAppIdAsString());
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
index 2d2fb3a214..a56f5685b8 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/IncomingMessage.java
@@ -96,9 +96,9 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
public void setExpiration()
{
long expiration =
- ((BasicContentHeaderProperties) _contentHeaderBody.properties).getExpiration();
+ ((BasicContentHeaderProperties) _contentHeaderBody.getProperties()).getExpiration();
long timestamp =
- ((BasicContentHeaderProperties) _contentHeaderBody.properties).getTimestamp();
+ ((BasicContentHeaderProperties) _contentHeaderBody.getProperties()).getTimestamp();
if (SYNCHED_CLOCKS)
{
@@ -139,7 +139,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
public int addContentBodyFrame(final ContentChunk contentChunk)
throws AMQException
{
- _storedMessageHandle.addContent((int)_bodyLengthReceived, contentChunk.getData().buf());
+ _storedMessageHandle.addContent((int)_bodyLengthReceived, ByteBuffer.wrap(contentChunk.getData()));
_bodyLengthReceived += contentChunk.getSize();
_contentChunks.add(contentChunk);
@@ -193,8 +193,8 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
public boolean isPersistent()
{
- return getContentHeader().properties instanceof BasicContentHeaderProperties &&
- ((BasicContentHeaderProperties) getContentHeader().properties).getDeliveryMode() ==
+ return getContentHeader().getProperties() instanceof BasicContentHeaderProperties &&
+ ((BasicContentHeaderProperties) getContentHeader().getProperties()).getDeliveryMode() ==
BasicContentHeaderProperties.PERSISTENT;
}
@@ -263,7 +263,7 @@ public class IncomingMessage implements Filterable, InboundMessage, EnqueableMes
int written = 0;
for(ContentChunk cb : _contentChunks)
{
- ByteBuffer data = cb.getData().buf();
+ ByteBuffer data = ByteBuffer.wrap(cb.getData());
if(offset+written >= pos && offset < pos + data.limit())
{
ByteBuffer src = data.duplicate();
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 edd1e0bdc3..be29245901 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
@@ -52,6 +52,17 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable
}
public abstract State getState();
+
+ /**
+ * Returns true if state is either DEQUEUED or DELETED.
+ *
+ * @return true if state is either DEQUEUED or DELETED.
+ */
+ public boolean isDispensed()
+ {
+ State currentState = getState();
+ return currentState == State.DEQUEUED || currentState == State.DELETED;
+ }
}
@@ -191,11 +202,7 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable
void reject();
- void reject(Subscription subscription);
-
- boolean isRejectedBy(Subscription subscription);
-
- void requeue(Subscription subscription);
+ boolean isRejectedBy(long subscriptionId);
void dequeue();
@@ -209,4 +216,18 @@ public interface QueueEntry extends Comparable<QueueEntry>, Filterable
void addStateChangeListener(StateChangeListener listener);
boolean removeStateChangeListener(StateChangeListener listener);
+
+ /**
+ * Returns true if entry is in DEQUEUED state, otherwise returns false.
+ *
+ * @return true if entry is in DEQUEUED state, otherwise returns false
+ */
+ boolean isDequeued();
+
+ /**
+ * Returns true if entry is either DEQUED or DELETED state.
+ *
+ * @return true if entry is either DEQUED or DELETED state
+ */
+ boolean isDispensed();
}
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 1ba4f4d89b..5b57e40a82 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
@@ -51,7 +51,7 @@ public class QueueEntryImpl implements QueueEntry
private MessageReference _message;
- private Set<Subscription> _rejectedBy = null;
+ private Set<Long> _rejectedBy = null;
private volatile EntryState _state = AVAILABLE_STATE;
@@ -325,19 +325,16 @@ public class QueueEntryImpl implements QueueEntry
public void reject()
{
- reject(getDeliveredSubscription());
- }
+ Subscription subscription = getDeliveredSubscription();
- public void reject(Subscription subscription)
- {
if (subscription != null)
{
if (_rejectedBy == null)
{
- _rejectedBy = new HashSet<Subscription>();
+ _rejectedBy = new HashSet<Long>();
}
- _rejectedBy.add(subscription);
+ _rejectedBy.add(subscription.getSubscriptionID());
}
else
{
@@ -345,12 +342,12 @@ public class QueueEntryImpl implements QueueEntry
}
}
- public boolean isRejectedBy(Subscription subscription)
+ public boolean isRejectedBy(long subscriptionId)
{
if (_rejectedBy != null) // We have subscriptions that rejected this message
{
- return _rejectedBy.contains(subscription);
+ return _rejectedBy.contains(subscriptionId);
}
else // This messasge hasn't been rejected yet.
{
@@ -358,15 +355,6 @@ public class QueueEntryImpl implements QueueEntry
}
}
- public void requeue(Subscription subscription)
- {
- getQueue().requeue(this, subscription);
- if(_stateChangeListeners != null)
- {
- notifyStateChange(QueueEntry.State.ACQUIRED, QueueEntry.State.AVAILABLE);
- }
- }
-
public void dequeue()
{
EntryState state = _state;
@@ -508,7 +496,7 @@ public class QueueEntryImpl implements QueueEntry
{
QueueEntryImpl next = nextNode();
- while(next != null && next.isDeleted())
+ while(next != null && next.isDispensed() )
{
final QueueEntryImpl newNext = next.nextNode();
@@ -556,4 +544,14 @@ public class QueueEntryImpl implements QueueEntry
return _queueEntryList;
}
+ public boolean isDequeued()
+ {
+ return _state == DEQUEUED_STATE;
+ }
+
+ public boolean isDispensed()
+ {
+ return _state.isDispensed();
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java
new file mode 100644
index 0000000000..7e1d57e205
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/QueueRunner.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.pool.ReadWriteRunnable;
+import org.apache.qpid.server.logging.actors.CurrentActor;
+import org.apache.qpid.server.queue.QueueRunner;
+import org.apache.qpid.server.queue.SimpleAMQQueue;
+
+/**
+ * QueueRunners are Runnables used to process a queue when requiring
+ * asynchronous message delivery to subscriptions, which is necessary
+ * when straight-through delivery of a message to a subscription isn't
+ * possible during the enqueue operation.
+ */
+public class QueueRunner implements ReadWriteRunnable
+{
+ private static final Logger _logger = Logger.getLogger(QueueRunner.class);
+
+ private final String _name;
+ private final SimpleAMQQueue _queue;
+
+ public QueueRunner(SimpleAMQQueue queue, long count)
+ {
+ _queue = queue;
+ _name = "QueueRunner-" + count + "-" + queue.getLogActor();
+ }
+
+ public void run()
+ {
+ String originalName = Thread.currentThread().getName();
+ try
+ {
+ Thread.currentThread().setName(_name);
+ CurrentActor.set(_queue.getLogActor());
+
+ _queue.processQueue(this);
+ }
+ catch (AMQException e)
+ {
+ _logger.error("Exception during asynchronous delivery by " + _name, e);
+ }
+ finally
+ {
+ CurrentActor.remove();
+ Thread.currentThread().setName(originalName);
+ }
+ }
+
+ public boolean isRead()
+ {
+ return false;
+ }
+
+ public boolean isWrite()
+ {
+ return true;
+ }
+
+ public String toString()
+ {
+ return _name;
+ }
+} \ No newline at end of file
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 b003152db6..a095ef47ea 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
@@ -44,7 +44,7 @@ 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.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.PrincipalHolder;
+import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.subscription.Subscription;
import org.apache.qpid.server.subscription.SubscriptionList;
import org.apache.qpid.server.txn.AutoCommitTransaction;
@@ -83,7 +83,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
/** null means shared */
private final AMQShortString _owner;
- private PrincipalHolder _prinicpalHolder;
+ private AuthorizationHolder _authorizationHolder;
private boolean _exclusive = false;
private AMQSessionModel _exclusiveOwner;
@@ -102,9 +102,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
protected final QueueEntryList _entries;
- protected final SubscriptionList _subscriptionList = new SubscriptionList(this);
-
- private final AtomicReference<SubscriptionList.SubscriptionNode> _lastSubscriptionNode = new AtomicReference<SubscriptionList.SubscriptionNode>(_subscriptionList.getHead());
+ protected final SubscriptionList _subscriptionList = new SubscriptionList();
private volatile Subscription _exclusiveSubscriber;
@@ -373,14 +371,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
return _owner;
}
- public PrincipalHolder getPrincipalHolder()
+ public AuthorizationHolder getAuthorizationHolder()
{
- return _prinicpalHolder;
+ return _authorizationHolder;
}
- public void setPrincipalHolder(PrincipalHolder prinicpalHolder)
+ public void setAuthorizationHolder(final AuthorizationHolder authorizationHolder)
{
- _prinicpalHolder = prinicpalHolder;
+ _authorizationHolder = authorizationHolder;
}
@@ -602,25 +600,25 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
iterate over subscriptions and if any is at the end of the queue and can deliver this message, then deliver the message
*/
- SubscriptionList.SubscriptionNode node = _lastSubscriptionNode.get();
- SubscriptionList.SubscriptionNode nextNode = node.getNext();
+ SubscriptionList.SubscriptionNode node = _subscriptionList.getMarkedNode();
+ SubscriptionList.SubscriptionNode nextNode = node.findNext();
if (nextNode == null)
{
- nextNode = _subscriptionList.getHead().getNext();
+ nextNode = _subscriptionList.getHead().findNext();
}
while (nextNode != null)
{
- if (_lastSubscriptionNode.compareAndSet(node, nextNode))
+ if (_subscriptionList.updateMarkedNode(node, nextNode))
{
break;
}
else
{
- node = _lastSubscriptionNode.get();
- nextNode = node.getNext();
+ node = _subscriptionList.getMarkedNode();
+ nextNode = node.findNext();
if (nextNode == null)
{
- nextNode = _subscriptionList.getHead().getNext();
+ nextNode = _subscriptionList.getHead().findNext();
}
}
}
@@ -629,7 +627,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
// this catches the case where we *just* miss an update
int loops = 2;
- while (!(entry.isAcquired() || entry.isDeleted()) && loops != 0)
+ while (entry.isAvailable() && loops != 0)
{
if (nextNode == null)
{
@@ -642,13 +640,13 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
Subscription sub = nextNode.getSubscription();
deliverToSubscription(sub, entry);
}
- nextNode = nextNode.getNext();
+ nextNode = nextNode.findNext();
}
}
- if (!(entry.isAcquired() || entry.isDeleted()))
+ if (entry.isAvailable())
{
checkSubscriptionsNotAheadOfDelivery(entry);
@@ -805,24 +803,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
- public void requeue(QueueEntryImpl entry, Subscription subscription)
- {
- SubscriptionList.SubscriptionNodeIterator subscriberIter = _subscriptionList.iterator();
- // iterate over all the subscribers, and if they are in advance of this queue entry then move them backwards
- while (subscriberIter.advance())
- {
- Subscription sub = subscriberIter.getNode().getSubscription();
-
- // we don't make browsers send the same stuff twice
- if (sub.seesRequeues() && (!sub.acquires() && sub == subscription))
- {
- updateSubRequeueEntry(sub, entry);
- }
- }
-
- deliverAsync();
- }
-
public void dequeue(QueueEntry entry, Subscription sub)
{
decrementQueueCount();
@@ -960,7 +940,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- if (node != null && !node.isDeleted())
+ if (node != null && !node.isDispensed())
{
entryList.add(node);
}
@@ -1064,7 +1044,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance() && !filter.filterComplete())
{
QueueEntry node = queueListIterator.getNode();
- if (!node.isDeleted() && filter.accept(node))
+ if (!node.isDispensed() && filter.accept(node))
{
entryList.add(node);
}
@@ -1258,7 +1238,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
if ((messageId >= fromMessageId)
&& (messageId <= toMessageId)
- && !node.isDeleted()
&& node.acquire())
{
dequeueEntry(node);
@@ -1288,7 +1267,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (noDeletes && queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- if (!node.isDeleted() && node.acquire())
+ if (node.acquire())
{
dequeueEntry(node);
noDeletes = false;
@@ -1318,7 +1297,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- if (!node.isDeleted() && node.acquire())
+ if (node.acquire())
{
dequeueEntry(node, txn);
if(++count == request)
@@ -1585,7 +1564,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
public void deliverAsync()
{
- Runner runner = new Runner(_stateChangeCount.incrementAndGet());
+ QueueRunner runner = new QueueRunner(this, _stateChangeCount.incrementAndGet());
if (_asynchronousRunner.compareAndSet(null, runner))
{
@@ -1604,52 +1583,6 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
_asyncDelivery.execute(flusher);
}
-
- private class Runner implements ReadWriteRunnable
- {
- String _name;
- public Runner(long count)
- {
- _name = "QueueRunner-" + count + "-" + _logActor;
- }
-
- public void run()
- {
- String originalName = Thread.currentThread().getName();
- try
- {
- Thread.currentThread().setName(_name);
- CurrentActor.set(_logActor);
-
- processQueue(this);
- }
- catch (AMQException e)
- {
- _logger.error(e);
- }
- finally
- {
- CurrentActor.remove();
- Thread.currentThread().setName(originalName);
- }
- }
-
- public boolean isRead()
- {
- return false;
- }
-
- public boolean isWrite()
- {
- return true;
- }
-
- public String toString()
- {
- return _name;
- }
- }
-
public void flushSubscription(Subscription sub) throws AMQException
{
// Access control
@@ -1718,7 +1651,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
QueueEntry node = getNextAvailableEntry(sub);
- if (node != null && !(node.isAcquired() || node.isDeleted()))
+ if (node != null && node.isAvailable())
{
if (sub.hasInterest(node))
{
@@ -1779,7 +1712,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
QueueEntry node = (releasedNode != null && lastSeen.compareTo(releasedNode)>=0) ? releasedNode : _entries.next(lastSeen);
boolean expired = false;
- while (node != null && (node.isAcquired() || node.isDeleted() || (expired = node.expired()) || !sub.hasInterest(node)))
+ while (node != null && (!node.isAvailable() || (expired = node.expired()) || !sub.hasInterest(node)))
{
if (expired)
{
@@ -1808,14 +1741,40 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
- private void processQueue(Runnable runner) throws AMQException
+ /**
+ * Used by queue Runners to asynchronously deliver messages to consumers.
+ *
+ * A queue Runner is started whenever a state change occurs, e.g when a new
+ * message arrives on the queue and cannot be immediately delivered to a
+ * subscription (i.e. asynchronous delivery is required). Unless there are
+ * SubFlushRunners operating (due to subscriptions unsuspending) which are
+ * capable of accepting/delivering all messages then these messages would
+ * otherwise remain on the queue.
+ *
+ * processQueue should be running while there are messages on the queue AND
+ * there are subscriptions that can deliver them. If there are no
+ * subscriptions capable of delivering the remaining messages on the queue
+ * then processQueue should stop to prevent spinning.
+ *
+ * Since processQueue is runs in a fixed size Executor, it should not run
+ * indefinitely to prevent starving other tasks of CPU (e.g jobs to process
+ * incoming messages may not be able to be scheduled in the thread pool
+ * because all threads are working on clearing down large queues). To solve
+ * this problem, after an arbitrary number of message deliveries the
+ * processQueue job stops iterating, resubmits itself to the executor, and
+ * ends the current instance
+ *
+ * @param runner the Runner to schedule
+ * @throws AMQException
+ */
+ public void processQueue(QueueRunner runner) throws AMQException
{
long stateChangeCount;
long previousStateChangeCount = Long.MIN_VALUE;
boolean deliveryIncomplete = true;
- int extraLoops = 1;
- long iterations = MAX_ASYNC_DELIVERIES;
+ boolean lastLoop = false;
+ int iterations = MAX_ASYNC_DELIVERIES;
_asynchronousRunner.compareAndSet(runner, null);
@@ -1832,12 +1791,14 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
if (previousStateChangeCount != stateChangeCount)
{
- extraLoops = 1;
+ //further asynchronous delivery is required since the
+ //previous loop. keep going if iteration slicing allows.
+ lastLoop = false;
}
previousStateChangeCount = stateChangeCount;
- deliveryIncomplete = _subscriptionList.size() != 0;
- boolean done;
+ boolean allSubscriptionsDone = true;
+ boolean subscriptionDone;
SubscriptionList.SubscriptionNodeIterator subscriptionIter = _subscriptionList.iterator();
//iterate over the subscribers and try to advance their pointer
@@ -1847,30 +1808,25 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
sub.getSendLock();
try
{
-
- done = attemptDelivery(sub);
-
- if (done)
+ //attempt delivery. returns true if no further delivery currently possible to this sub
+ subscriptionDone = attemptDelivery(sub);
+ if (subscriptionDone)
{
- if (extraLoops == 0)
+ //close autoClose subscriptions if we are not currently intent on continuing
+ if (lastLoop && sub.isAutoClose())
{
- deliveryIncomplete = false;
- if (sub.isAutoClose())
- {
- unregisterSubscription(sub);
+ unregisterSubscription(sub);
- sub.confirmAutoClose();
- }
- }
- else
- {
- extraLoops--;
+ sub.confirmAutoClose();
}
}
else
{
+ //this subscription can accept additional deliveries, so we must
+ //keep going after this (if iteration slicing allows it)
+ allSubscriptionsDone = false;
+ lastLoop = false;
iterations--;
- extraLoops = 1;
}
}
finally
@@ -1878,10 +1834,34 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
sub.releaseSendLock();
}
}
+
+ if(allSubscriptionsDone && lastLoop)
+ {
+ //We have done an extra loop already and there are again
+ //again no further delivery attempts possible, only
+ //keep going if state change demands it.
+ deliveryIncomplete = false;
+ }
+ else if(allSubscriptionsDone)
+ {
+ //All subscriptions reported being done, but we have to do
+ //an extra loop if the iterations are not exhausted and
+ //there is still any work to be done
+ deliveryIncomplete = _subscriptionList.size() != 0;
+ lastLoop = true;
+ }
+ else
+ {
+ //some subscriptions can still accept more messages,
+ //keep going if iteration count allows.
+ lastLoop = false;
+ deliveryIncomplete = true;
+ }
+
_asynchronousRunner.set(null);
}
- // If deliveries == 0 then the limitting factor was the time-slicing rather than available messages or credit
+ // If iterations == 0 then the limiting factor was the time-slicing rather than available messages or credit
// therefore we should schedule this runner again (unless someone beats us to it :-) ).
if (iterations == 0 && _asynchronousRunner.compareAndSet(null, runner))
{
@@ -1901,8 +1881,8 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
while (queueListIterator.advance())
{
QueueEntry node = queueListIterator.getNode();
- // Only process nodes that are not currently deleted
- if (!node.isDeleted())
+ // Only process nodes that are not currently deleted and not dequeued
+ if (!node.isDispensed())
{
// If the node has exired then aquire it
if (node.expired() && node.acquire())
@@ -2242,4 +2222,9 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener
}
}
}
+
+ public LogActor getLogActor()
+ {
+ return _logActor;
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
index b97c2c55c5..46baab8c85 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SimpleQueueEntryList.java
@@ -1,6 +1,5 @@
package org.apache.qpid.server.queue;
-import org.apache.qpid.server.message.InboundMessage;
import org.apache.qpid.server.message.ServerMessage;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
@@ -156,7 +155,7 @@ public class SimpleQueueEntryList implements QueueEntryList
if(!atTail())
{
QueueEntryImpl nextNode = _lastNode.nextNode();
- while(nextNode.isDeleted() && nextNode.nextNode() != null)
+ while(nextNode.isDispensed() && nextNode.nextNode() != null)
{
nextNode = nextNode.nextNode();
}
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 78a642f22f..c07074f69c 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
@@ -21,9 +21,14 @@
package org.apache.qpid.server.registry;
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.util.concurrent.atomic.AtomicReference;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -41,23 +46,27 @@ 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.RootMessageLogger;
-import org.apache.qpid.server.logging.AbstractRootMessageLogger;
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.plugins.PluginManager;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.database.ConfigurationFilePrincipalDatabaseManager;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
+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.PrincipalDatabaseAuthenticationManager;
+import org.apache.qpid.server.security.auth.manager.AuthenticationManagerPluginFactory;
+import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.transport.QpidAcceptor;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.server.virtualhost.VirtualHostImpl;
import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
+import org.osgi.framework.BundleContext;
+
/**
* An abstract application registry that provides access to configuration information and handles the
@@ -69,12 +78,10 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
protected static final Logger _logger = Logger.getLogger(ApplicationRegistry.class);
- private static Map<Integer, IApplicationRegistry> _instanceMap = new HashMap<Integer, IApplicationRegistry>();
+ private static AtomicReference<IApplicationRegistry> _instance = new AtomicReference<IApplicationRegistry>(null);
protected final ServerConfiguration _configuration;
- public static final int DEFAULT_INSTANCE = 1;
-
protected final Map<InetSocketAddress, QpidAcceptor> _acceptors = new HashMap<InetSocketAddress, QpidAcceptor>();
protected ManagedObjectRegistry _managedObjectRegistry;
@@ -85,8 +92,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
protected SecurityManager _securityManager;
- protected PrincipalDatabaseManager _databaseManager;
-
protected PluginManager _pluginManager;
protected ConfigurationManager _configurationManager;
@@ -102,8 +107,12 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
private BrokerConfig _broker;
private ConfigStore _configStore;
+
+ private Timer _reportingTimer;
+ private boolean _statisticsEnabled = false;
+ private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
- protected String _registryName;
+ private BundleContext _bundleContext;
static
{
@@ -114,53 +123,54 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
public void run()
{
- removeAll();
+ remove();
}
}
public static void initialise(IApplicationRegistry instance) throws Exception
{
- initialise(instance, DEFAULT_INSTANCE);
- }
+ if(instance == null)
+ {
+ throw new IllegalArgumentException("ApplicationRegistry instance must not be null");
+ }
- @SuppressWarnings("finally")
- public static void initialise(IApplicationRegistry instance, int instanceID) throws Exception
- {
- if (instance != null)
+ if(!_instance.compareAndSet(null, instance))
{
- _logger.info("Initialising Application Registry(" + instance + "):" + instanceID);
- _instanceMap.put(instanceID, instance);
+ throw new IllegalStateException("An ApplicationRegistry is already initialised");
+ }
+
+ _logger.info("Initialising Application Registry(" + instance + ")");
+
+
+ final ConfigStore store = ConfigStore.newInstance();
+ store.setRoot(new SystemConfigImpl(store));
+ instance.setConfigStore(store);
- final ConfigStore store = ConfigStore.newInstance();
- store.setRoot(new SystemConfigImpl(store));
- instance.setConfigStore(store);
+ BrokerConfig broker = new BrokerConfigAdapter(instance);
- BrokerConfig broker = new BrokerConfigAdapter(instance);
+ SystemConfig system = (SystemConfig) store.getRoot();
+ system.addBroker(broker);
+ instance.setBroker(broker);
- SystemConfig system = (SystemConfig) store.getRoot();
- system.addBroker(broker);
- instance.setBroker(broker);
+ try
+ {
+ instance.initialise();
+ }
+ catch (Exception e)
+ {
+ _instance.set(null);
+ //remove the Broker instance, then re-throw
try
{
- instance.initialise(instanceID);
+ system.removeBroker(broker);
}
- catch (Exception e)
+ catch(Throwable t)
{
- _instanceMap.remove(instanceID);
- try
- {
- system.removeBroker(broker);
- }
- finally
- {
- throw e;
- }
+ //ignore
}
- }
- else
- {
- remove(instanceID);
+
+ throw e;
}
}
@@ -176,35 +186,19 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public static boolean isConfigured()
{
- return isConfigured(DEFAULT_INSTANCE);
- }
-
- public static boolean isConfigured(int instanceID)
- {
- return _instanceMap.containsKey(instanceID);
+ return _instance.get() != null;
}
- /** Method to cleanly shutdown the default registry running in this JVM */
public static void remove()
{
- remove(DEFAULT_INSTANCE);
- }
-
- /**
- * Method to cleanly shutdown specified registry running in this JVM
- *
- * @param instanceID the instance to shutdown
- */
- public static void remove(int instanceID)
- {
+ IApplicationRegistry instance = _instance.getAndSet(null);
try
{
- IApplicationRegistry instance = _instanceMap.get(instanceID);
if (instance != null)
{
if (_logger.isInfoEnabled())
{
- _logger.info("Shutting down ApplicationRegistry(" + instanceID + "):" + instance);
+ _logger.info("Shutting down ApplicationRegistry(" + instance + ")");
}
instance.close();
instance.getBroker().getSystem().removeBroker(instance.getBroker());
@@ -212,27 +206,19 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
catch (Exception e)
{
- _logger.error("Error shutting down Application Registry(" + instanceID + "): " + e, e);
- }
- finally
- {
- _instanceMap.remove(instanceID);
+ _logger.error("Error shutting down Application Registry(" + instance + "): " + e, e);
}
}
- /** Method to cleanly shutdown all registries currently running in this JVM */
- public static void removeAll()
+ protected ApplicationRegistry(ServerConfiguration configuration)
{
- Object[] keys = _instanceMap.keySet().toArray();
- for (Object k : keys)
- {
- remove((Integer) k);
- }
+ this(configuration, null);
}
- protected ApplicationRegistry(ServerConfiguration configuration)
+ protected ApplicationRegistry(ServerConfiguration configuration, BundleContext bundleContext)
{
_configuration = configuration;
+ _bundleContext = bundleContext;
}
public void configure() throws ConfigurationException
@@ -241,7 +227,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
- _pluginManager = new PluginManager(_configuration.getPluginDirectory(), _configuration.getCacheDirectory());
+ _pluginManager = new PluginManager(_configuration.getPluginDirectory(), _configuration.getCacheDirectory(), _bundleContext);
}
catch (Exception e)
{
@@ -251,11 +237,10 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_configuration.initialise();
}
- public void initialise(int instanceID) throws Exception
+ public void initialise() throws Exception
{
//Create the RootLogger to be used during broker operation
_rootMessageLogger = new Log4jMessageLogger(_configuration);
- _registryName = String.valueOf(instanceID);
//Create the composite (log4j+SystemOut MessageLogger to be used during startup
RootMessageLogger[] messageLoggers = {new SystemOutMessageLogger(), _rootMessageLogger};
@@ -277,11 +262,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
_securityManager = new SecurityManager(_configuration, _pluginManager);
- createDatabaseManager(_configuration);
-
- _authenticationManager = new PrincipalDatabaseAuthenticationManager(null, null);
-
- _databaseManager.initialiseManagement(_configuration);
+ _authenticationManager = createAuthenticationManager();
_managedObjectRegistry.start();
}
@@ -294,6 +275,8 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
initialiseVirtualHosts();
+ initialiseStatistics();
+ initialiseStatisticsReporting();
}
finally
{
@@ -302,9 +285,51 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
}
}
- protected void createDatabaseManager(ServerConfiguration configuration) throws Exception
+ /**
+ * 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
{
- _databaseManager = new ConfigurationFilePrincipalDatabaseManager(_configuration);
+ 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;
}
protected void initialiseVirtualHosts() throws Exception
@@ -320,26 +345,88 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
_managedObjectRegistry = new NoopManagedObjectRegistry();
}
-
- public static IApplicationRegistry getInstance()
+
+ public void initialiseStatisticsReporting()
{
- return getInstance(DEFAULT_INSTANCE);
+ 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);
+
+ class StatisticsReportingTask extends TimerTask
+ {
+ private final int DELIVERED = 0;
+ private final int RECEIVED = 1;
+
+ public void run()
+ {
+ CurrentActor.set(new AbstractActor(ApplicationRegistry.getInstance().getRootMessageLogger()) {
+ public String getLogMessage()
+ {
+ return "[" + Thread.currentThread().getName() + "] ";
+ }
+ });
+
+ if (broker)
+ {
+ CurrentActor.get().message(BrokerMessages.STATS_DATA(DELIVERED, _dataDelivered.getPeak() / 1024.0, _dataDelivered.getTotal()));
+ CurrentActor.get().message(BrokerMessages.STATS_MSGS(DELIVERED, _messagesDelivered.getPeak(), _messagesDelivered.getTotal()));
+ CurrentActor.get().message(BrokerMessages.STATS_DATA(RECEIVED, _dataReceived.getPeak() / 1024.0, _dataReceived.getTotal()));
+ CurrentActor.get().message(BrokerMessages.STATS_MSGS(RECEIVED, _messagesReceived.getPeak(), _messagesReceived.getTotal()));
+ }
+
+ if (virtualhost)
+ {
+ for (VirtualHost vhost : getVirtualHostRegistry().getVirtualHosts())
+ {
+ String name = vhost.getName();
+ StatisticsCounter dataDelivered = vhost.getDataDeliveryStatistics();
+ StatisticsCounter messagesDelivered = vhost.getMessageDeliveryStatistics();
+ StatisticsCounter dataReceived = vhost.getDataReceiptStatistics();
+ StatisticsCounter messagesReceived = vhost.getMessageReceiptStatistics();
+
+ CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, DELIVERED, dataDelivered.getPeak() / 1024.0, dataDelivered.getTotal()));
+ CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, DELIVERED, messagesDelivered.getPeak(), messagesDelivered.getTotal()));
+ CurrentActor.get().message(VirtualHostMessages.STATS_DATA(name, RECEIVED, dataReceived.getPeak() / 1024.0, dataReceived.getTotal()));
+ CurrentActor.get().message(VirtualHostMessages.STATS_MSGS(name, RECEIVED, messagesReceived.getPeak(), messagesReceived.getTotal()));
+ }
+ }
+
+ if (reset)
+ {
+ resetStatistics();
+ }
+
+ CurrentActor.remove();
+ }
+ }
+
+ _reportingTimer.scheduleAtFixedRate(new StatisticsReportingTask(),
+ report / 2,
+ report);
+ }
}
- public static IApplicationRegistry getInstance(int instanceID)
+ /**
+ * Get the ApplicationRegistry
+ * @return the IApplicationRegistry instance
+ * @throws IllegalStateException if no registry instance has been initialised.
+ */
+ public static IApplicationRegistry getInstance() throws IllegalStateException
{
- synchronized (IApplicationRegistry.class)
+ IApplicationRegistry iApplicationRegistry = _instance.get();
+ if (iApplicationRegistry == null)
{
- IApplicationRegistry instance = _instanceMap.get(instanceID);
-
- if (instance == null)
- {
- throw new IllegalStateException("Application Registry (" + instanceID + ") not created");
- }
- else
- {
- return instance;
- }
+ throw new IllegalStateException("No ApplicationRegistry has been initialised");
+ }
+ else
+ {
+ return iApplicationRegistry;
}
}
@@ -369,6 +456,12 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
{
_logger.info("Shutting down ApplicationRegistry:" + this);
}
+
+ //Stop Statistics Reporting
+ if (_reportingTimer != null)
+ {
+ _reportingTimer.cancel();
+ }
//Stop incoming connections
unbind();
@@ -376,10 +469,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
//Shutdown virtualhosts
close(_virtualHostRegistry);
-// close(_accessManager);
-//
-// close(_databaseManager);
-
close(_authenticationManager);
close(_managedObjectRegistry);
@@ -401,7 +490,7 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
try
{
- acceptor.getNetworkDriver().close();
+ acceptor.getNetworkTransport().close();
}
catch (Throwable e)
{
@@ -441,11 +530,6 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
return _managedObjectRegistry;
}
- public PrincipalDatabaseManager getDatabaseManager()
- {
- return _databaseManager;
- }
-
public AuthenticationManager getAuthenticationManager()
{
return _authenticationManager;
@@ -493,9 +577,81 @@ public abstract class ApplicationRegistry implements IApplicationRegistry
public VirtualHost createVirtualHost(final VirtualHostConfiguration vhostConfig) throws Exception
{
- VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig);
+ VirtualHostImpl virtualHost = new VirtualHostImpl(this, vhostConfig, null);
_virtualHostRegistry.registerVirtualHost(virtualHost);
getBroker().addVirtualHost(virtualHost);
return virtualHost;
}
+
+ public void registerMessageDelivered(long messageSize)
+ {
+ if (isStatisticsEnabled())
+ {
+ _messagesDelivered.registerEvent(1L);
+ _dataDelivered.registerEvent(messageSize);
+ }
+ }
+
+ public void registerMessageReceived(long messageSize, long timestamp)
+ {
+ if (isStatisticsEnabled())
+ {
+ _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();
+ }
+ }
+
+ 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;
+ }
}
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 4a4253153c..108533ef96 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
@@ -71,7 +71,7 @@ public class BrokerConfigAdapter implements BrokerConfig
public Integer getWorkerThreads()
{
- return _instance.getConfiguration().getProcessors();
+ return _instance.getConfiguration().getConnectorProcessors();
}
public Integer getMaxConnections()
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 ff2a8c959b..9121f8f927 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
@@ -29,12 +29,18 @@ import org.apache.qpid.server.logging.actors.BrokerActor;
import org.apache.qpid.server.logging.actors.CurrentActor;
import org.apache.qpid.server.management.JMXManagedObjectRegistry;
import org.apache.qpid.server.management.NoopManagedObjectRegistry;
+import org.osgi.framework.BundleContext;
public class ConfigurationFileApplicationRegistry extends ApplicationRegistry
{
public ConfigurationFileApplicationRegistry(File configurationURL) throws ConfigurationException
{
- super(new ServerConfiguration(configurationURL));
+ this(configurationURL, null);
+ }
+
+ public ConfigurationFileApplicationRegistry(File configurationURL, BundleContext bundleContext) throws ConfigurationException
+ {
+ super(new ServerConfiguration(configurationURL), bundleContext);
}
@Override
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 228c3b9112..c27e0d19ec 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
@@ -33,21 +33,20 @@ import org.apache.qpid.server.logging.RootMessageLogger;
import org.apache.qpid.server.management.ManagedObjectRegistry;
import org.apache.qpid.server.plugins.PluginManager;
import org.apache.qpid.server.security.SecurityManager;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+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;
-public interface IApplicationRegistry
+public interface IApplicationRegistry extends StatisticsGatherer
{
/**
* Initialise the application registry. All initialisation must be done in this method so that any components
* that need access to the application registry itself for initialisation are able to use it. Attempting to
* initialise in the constructor will lead to failures since the registry reference will not have been set.
- * @param instanceID the instanceID that we can use to identify this AR.
*/
- void initialise(int instanceID) throws Exception;
+ void initialise() throws Exception;
/**
* Shutdown this Registry
@@ -63,8 +62,6 @@ public interface IApplicationRegistry
ManagedObjectRegistry getManagedObjectRegistry();
- PrincipalDatabaseManager getDatabaseManager();
-
AuthenticationManager getAuthenticationManager();
VirtualHostRegistry getVirtualHostRegistry();
@@ -97,4 +94,6 @@ public interface IApplicationRegistry
ConfigStore getConfigStore();
void setConfigStore(ConfigStore store);
+
+ void initialiseStatisticsReporting();
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java b/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java
new file mode 100755
index 0000000000..3d8c77a86f
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/AuthorizationHolder.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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;
+
+import java.security.Principal;
+
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.security.auth.sasl.GroupPrincipal;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+
+/**
+ * Represents the authorization of the logged on user.
+ *
+ */
+public interface AuthorizationHolder
+{
+ /**
+ * Returns the {@link Subject} of the authorized user. This is guaranteed to
+ * contain at least one {@link UsernamePrincipal}, representing the the identity
+ * used when the user logged on to the application, and zero or more {@link GroupPrincipal}
+ * representing the group(s) to which the user belongs.
+ *
+ * @return the Subject
+ */
+ Subject getAuthorizedSubject();
+
+ /**
+ * Returns the {@link Principal} representing the the identity
+ * used when the user logged on to the application.
+ *
+ * @return a Principal
+ */
+ Principal getAuthorizedPrincipal();
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
index f18c327692..f582fed6a0 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/SecurityManager.java
@@ -18,8 +18,19 @@
*/
package org.apache.qpid.server.security;
-import static org.apache.qpid.server.security.access.ObjectType.*;
-import static org.apache.qpid.server.security.access.Operation.*;
+import static org.apache.qpid.server.security.access.ObjectType.EXCHANGE;
+import static org.apache.qpid.server.security.access.ObjectType.METHOD;
+import static org.apache.qpid.server.security.access.ObjectType.OBJECT;
+import static org.apache.qpid.server.security.access.ObjectType.QUEUE;
+import static org.apache.qpid.server.security.access.ObjectType.VIRTUALHOST;
+import static org.apache.qpid.server.security.access.Operation.ACCESS;
+import static org.apache.qpid.server.security.access.Operation.BIND;
+import static org.apache.qpid.server.security.access.Operation.CONSUME;
+import static org.apache.qpid.server.security.access.Operation.CREATE;
+import static org.apache.qpid.server.security.access.Operation.DELETE;
+import static org.apache.qpid.server.security.access.Operation.PUBLISH;
+import static org.apache.qpid.server.security.access.Operation.PURGE;
+import static org.apache.qpid.server.security.access.Operation.UNBIND;
import java.net.SocketAddress;
import java.security.Principal;
@@ -29,6 +40,8 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import javax.security.auth.Subject;
+
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
@@ -37,11 +50,9 @@ import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin;
import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.plugins.PluginManager;
-import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.security.access.ObjectProperties;
import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
/**
* The security manager contains references to all loaded {@link SecurityPlugin}s and delegates security decisions to them based
@@ -55,7 +66,7 @@ public class SecurityManager
private static final Logger _logger = Logger.getLogger(SecurityManager.class);
/** Container for the {@link Principal} that is using to this thread. */
- private static final ThreadLocal<Principal> _principal = new ThreadLocal<Principal>();
+ private static final ThreadLocal<Subject> _subject = new ThreadLocal<Subject>();
private PluginManager _pluginManager;
private Map<String, SecurityPluginFactory> _pluginFactories = new HashMap<String, SecurityPluginFactory>();
@@ -126,19 +137,14 @@ public class SecurityManager
configureHostPlugins(configuration);
}
- public static Principal getThreadPrincipal()
- {
- return _principal.get();
- }
-
- public static void setThreadPrincipal(Principal principal)
+ public static Subject getThreadSubject()
{
- _principal.set(principal);
+ return _subject.get();
}
- public static void setThreadPrincipal(String authId)
+ public static void setThreadSubject(final Subject subject)
{
- setThreadPrincipal(new UsernamePrincipal(authId));
+ _subject.set(subject);
}
public void configureHostPlugins(ConfigurationPlugin hostConfig) throws ConfigurationException
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
index 70a9ea5356..e4bf8df340 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java
@@ -149,9 +149,9 @@ public class ObjectProperties extends HashMap<ObjectProperties.Property, String>
{
put(Property.OWNER, queue.getOwner());
}
- else if (queue.getPrincipalHolder() != null)
+ else if (queue.getAuthorizationHolder() != null)
{
- put(Property.OWNER, queue.getPrincipalHolder().getPrincipal().getName());
+ put(Property.OWNER, queue.getAuthorizationHolder().getAuthorizedPrincipal().getName());
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
index 62967ef7eb..8c2d60a660 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/AuthenticationResult.java
@@ -20,42 +20,93 @@
*/
package org.apache.qpid.server.security.auth;
+import javax.security.auth.Subject;
+
+/**
+ * Encapsulates the result of an attempt to authenticate.
+ * <p>
+ * The authentication status describes the overall outcome.
+ * <p>
+ * <ol>
+ * <li>If authentication status is SUCCESS, the subject will be populated.
+ * </li>
+ * <li>If authentication status is CONTINUE, the authentication has failed because the user
+ * supplied incorrect credentials (etc). If the authentication requires it, the next challenge
+ * is made available.
+ * </li>
+ * <li>If authentication status is ERROR , the authentication decision could not be made due
+ * to a failure (such as an external system), the {@link AuthenticationResult#getCause()}
+ * will provide the underlying exception.
+ * </li>
+ * </ol>
+ *
+ */
public class AuthenticationResult
{
public enum AuthenticationStatus
{
- SUCCESS, CONTINUE, ERROR
+ /** Authentication successful */
+ SUCCESS,
+ /** Authentication not successful due to credentials problem etc */
+ CONTINUE,
+ /** Problem prevented the authentication from being made e.g. failure of an external system */
+ ERROR
}
- public AuthenticationStatus status;
- public byte[] challenge;
-
- private Exception cause;
+ public final AuthenticationStatus _status;
+ public final byte[] _challenge;
+ private final Exception _cause;
+ private final Subject _subject;
- public AuthenticationResult(AuthenticationStatus status)
+ public AuthenticationResult(final AuthenticationStatus status)
{
this(null, status, null);
}
- public AuthenticationResult(byte[] challenge, AuthenticationStatus status)
+ public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status)
{
this(challenge, status, null);
}
- public AuthenticationResult(AuthenticationStatus error, Exception cause)
+ public AuthenticationResult(final AuthenticationStatus error, final Exception cause)
{
this(null, error, cause);
}
- public AuthenticationResult(byte[] challenge, AuthenticationStatus status, Exception cause)
+ public AuthenticationResult(final byte[] challenge, final AuthenticationStatus status, final Exception cause)
+ {
+ this._status = status;
+ this._challenge = challenge;
+ this._cause = cause;
+ this._subject = null;
+ }
+
+ public AuthenticationResult(final Subject subject)
{
- this.status = status;
- this.challenge = challenge;
- this.cause = cause;
+ this._status = AuthenticationStatus.SUCCESS;
+ this._challenge = null;
+ this._cause = null;
+ this._subject = subject;
}
public Exception getCause()
{
- return cause;
+ return _cause;
+ }
+
+ public AuthenticationStatus getStatus()
+ {
+ return _status;
+ }
+
+ public byte[] getChallenge()
+ {
+ return _challenge;
}
+
+ public Subject getSubject()
+ {
+ return _subject;
+ }
+
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
deleted file mode 100644
index 5cebb7d2d8..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/ConfigurationFilePrincipalDatabaseManager.java
+++ /dev/null
@@ -1,221 +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.database;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-
-import org.apache.log4j.Logger;
-
-import org.apache.qpid.configuration.PropertyUtils;
-import org.apache.qpid.configuration.PropertyException;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabaseManager;
-import org.apache.qpid.server.security.auth.management.AMQUserManagementMBean;
-import org.apache.qpid.AMQException;
-
-import javax.management.JMException;
-
-public class ConfigurationFilePrincipalDatabaseManager implements PrincipalDatabaseManager
-{
- private static final Logger _logger = Logger.getLogger(ConfigurationFilePrincipalDatabaseManager.class);
-
- Map<String, PrincipalDatabase> _databases;
-
- public ConfigurationFilePrincipalDatabaseManager(ServerConfiguration _configuration) throws Exception
- {
- _logger.info("Initialising PrincipalDatabase authentication manager");
- _databases = initialisePrincipalDatabases(_configuration);
- }
-
- private Map<String, PrincipalDatabase> initialisePrincipalDatabases(ServerConfiguration _configuration) throws Exception
- {
- List<String> databaseNames = _configuration.getPrincipalDatabaseNames();
- List<String> databaseClasses = _configuration.getPrincipalDatabaseClass();
- Map<String, PrincipalDatabase> databases = new HashMap<String, PrincipalDatabase>();
-
- if (databaseNames.size() == 0)
- {
- _logger.warn("No Principal databases specified. Broker running with NO AUTHENTICATION");
- }
-
- for (int i = 0; i < databaseNames.size(); i++)
- {
- Object o;
- try
- {
- o = Class.forName(databaseClasses.get(i)).newInstance();
- }
- catch (Exception e)
- {
- throw new Exception("Error initialising principal database: " + e, e);
- }
-
- if (!(o instanceof PrincipalDatabase))
- {
- throw new Exception("Principal databases must implement the PrincipalDatabase interface");
- }
-
- initialisePrincipalDatabase((PrincipalDatabase) o, _configuration, i);
-
- String name = databaseNames.get(i);
- if ((name == null) || (name.length() == 0))
- {
- throw new Exception("Principal database names must have length greater than or equal to one character");
- }
-
- PrincipalDatabase pd = databases.get(name);
- if (pd != null)
- {
- throw new Exception("Duplicate principal database name not permitted");
- }
-
- _logger.info("Initialised principal database '" + name + "' successfully");
- databases.put(name, (PrincipalDatabase) o);
- }
-
- return databases;
- }
-
- private void initialisePrincipalDatabase(PrincipalDatabase principalDatabase, ServerConfiguration _configuration, int index)
- throws FileNotFoundException, ConfigurationException
- {
- List<String> argumentNames = _configuration.getPrincipalDatabaseAttributeNames(index);
- List<String> argumentValues = _configuration.getPrincipalDatabaseAttributeValues(index);
- for (int i = 0; i < argumentNames.size(); i++)
- {
- String argName = argumentNames.get(i);
- if ((argName == null) || (argName.length() == 0))
- {
- throw new ConfigurationException("Argument names must have length >= 1 character");
- }
-
- if (Character.isLowerCase(argName.charAt(0)))
- {
- argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1);
- }
-
- String methodName = "set" + argName;
- Method method = null;
- try
- {
- method = principalDatabase.getClass().getMethod(methodName, String.class);
- }
- catch (Exception e)
- {
- // do nothing.. as on error method will be null
- }
-
- if (method == null)
- {
- throw new ConfigurationException("No method " + methodName + " found in class "
- + principalDatabase.getClass()
- + " hence unable to configure principal database. The method must be public and "
- + "have a single String argument with a void return type");
- }
-
- try
- {
- method.invoke(principalDatabase, PropertyUtils.replaceProperties(argumentValues.get(i)));
- }
- catch (Exception ite)
- {
- if (ite instanceof ConfigurationException)
- {
- throw(ConfigurationException) ite;
- }
- else
- {
- throw new ConfigurationException(ite.getMessage(), ite);
- }
- }
- }
- }
-
- public Map<String, PrincipalDatabase> getDatabases()
- {
- return _databases;
- }
-
- public void initialiseManagement(ServerConfiguration config) throws ConfigurationException
- {
- try
- {
- AMQUserManagementMBean _mbean = new AMQUserManagementMBean();
-
- List<String> principalDBs = config.getManagementPrincipalDBs();
- if (principalDBs.isEmpty())
- {
- throw new ConfigurationException("No principal-database specified for jmx security");
- }
-
- String databaseName = principalDBs.get(0);
- PrincipalDatabase database = getDatabases().get(databaseName);
- if (database == null)
- {
- throw new ConfigurationException("Principal-database '" + databaseName + "' not found");
- }
-
- _mbean.setPrincipalDatabase(database);
-
- List<String> jmxaccesslist = config.getManagementAccessList();
- if (jmxaccesslist.isEmpty())
- {
- throw new ConfigurationException("No access control files specified for jmx security");
- }
-
- String jmxaccesssFile = null;
-
- try
- {
- jmxaccesssFile = PropertyUtils.replaceProperties(jmxaccesslist.get(0));
- }
- catch (PropertyException e)
- {
- throw new ConfigurationException("Unable to parse access control filename '" + jmxaccesssFile + "'");
- }
-
- try
- {
- _mbean.setAccessFile(jmxaccesssFile);
- }
- catch (IOException e)
- {
- _logger.warn("Unable to load access file:" + jmxaccesssFile);
- }
-
- _mbean.register();
- }
- catch (JMException e)
- {
- _logger.warn("User management disabled as unable to create MBean:" + e);
- }
- }
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java
deleted file mode 100644
index f9882f8810..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PrincipalDatabaseManager.java
+++ /dev/null
@@ -1,35 +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.database;
-
-import org.apache.qpid.server.configuration.ServerConfiguration;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.commons.configuration.Configuration;
-import org.apache.commons.configuration.ConfigurationException;
-
-import java.util.Map;
-
-public interface PrincipalDatabaseManager
-{
- public Map<String, PrincipalDatabase> getDatabases();
-
- public void initialiseManagement(ServerConfiguration _configuration) throws ConfigurationException;
-}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.java
deleted file mode 100644
index 8658101cd8..0000000000
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/database/PropertiesPrincipalDatabaseManager.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.security.auth.database;
-
-import org.apache.commons.configuration.ConfigurationException;
-import org.apache.qpid.server.configuration.ServerConfiguration;
-
-import java.util.Map;
-import java.util.Properties;
-import java.util.HashMap;
-
-public class PropertiesPrincipalDatabaseManager implements PrincipalDatabaseManager
-{
-
- Map<String, PrincipalDatabase> _databases = new HashMap<String, PrincipalDatabase>();
-
- public PropertiesPrincipalDatabaseManager(String name, Properties users)
- {
- _databases.put(name, new PropertiesPrincipalDatabase(users));
- }
-
- public Map<String, PrincipalDatabase> getDatabases()
- {
- return _databases;
- }
-
- public void initialiseManagement(ServerConfiguration _configuration) throws ConfigurationException
- {
- //todo
- }
-}
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
index ee4336055b..208130379e 100644
--- 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
@@ -20,19 +20,9 @@
*/
package org.apache.qpid.server.security.auth.management;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.security.AccessControlContext;
-import java.security.AccessController;
import java.security.Principal;
-import java.util.Enumeration;
import java.util.List;
-import java.util.Properties;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.locks.ReentrantLock;
import javax.management.JMException;
import javax.management.openmbean.CompositeData;
@@ -44,17 +34,13 @@ import javax.management.openmbean.SimpleType;
import javax.management.openmbean.TabularData;
import javax.management.openmbean.TabularDataSupport;
import javax.management.openmbean.TabularType;
-import javax.management.remote.JMXPrincipal;
-import javax.security.auth.Subject;
import javax.security.auth.login.AccountNotFoundException;
-import org.apache.commons.configuration.ConfigurationException;
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.management.MBeanInvocationHandlerImpl;
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
@@ -65,22 +51,18 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
private static final Logger _logger = Logger.getLogger(AMQUserManagementMBean.class);
private PrincipalDatabase _principalDatabase;
- private Properties _accessRights;
- private File _accessFile;
-
- private ReentrantLock _accessRightsUpdate = new ReentrantLock();
// Setup for the TabularType
- static TabularType _userlistDataType; // Datatype for representing User Lists
- static CompositeType _userDataType; // Composite type for representing User
+ 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
- userItemTypes[2] = SimpleType.BOOLEAN; // For Rights - Write
- userItemTypes[3] = SimpleType.BOOLEAN; // For Rights - Admin
+ 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
{
@@ -92,12 +74,11 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
}
catch (OpenDataException e)
{
- _logger.error("Tabular data setup for viewing users incorrect.");
- _userlistDataType = null;
+ _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);
@@ -110,121 +91,23 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
public boolean setPassword(String username, String password)
{
- return setPassword(username, password.toCharArray());
- }
-
- public boolean setPassword(String username, char[] password)
- {
try
{
//delegate password changes to the Principal Database
- return _principalDatabase.updatePassword(new UsernamePrincipal(username), password);
+ return _principalDatabase.updatePassword(new UsernamePrincipal(username), password.toCharArray());
}
catch (AccountNotFoundException e)
{
- _logger.warn("Attempt to set password of non-existant user'" + username + "'");
+ _logger.warn("Attempt to set password of non-existent user'" + username + "'");
return false;
}
}
- public boolean setRights(String username, boolean read, boolean write, boolean admin)
- {
-
- Object oldRights = null;
- if ((oldRights =_accessRights.get(username)) == null)
- {
- // If the user doesn't exist in the access rights file check that they at least have an account.
- if (_principalDatabase.getUser(username) == null)
- {
- return false;
- }
- }
-
- try
- {
- _accessRightsUpdate.lock();
-
- // Update the access rights
- if (admin)
- {
- _accessRights.put(username, MBeanInvocationHandlerImpl.ADMIN);
- }
- else
- {
- if (read | write)
- {
- if (read)
- {
- _accessRights.put(username, MBeanInvocationHandlerImpl.READONLY);
- }
- if (write)
- {
- _accessRights.put(username, MBeanInvocationHandlerImpl.READWRITE);
- }
- }
- else
- {
- _accessRights.remove(username);
- }
- }
-
- //save the rights file
- try
- {
- saveAccessFile();
- }
- catch (IOException e)
- {
- _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e);
-
- //the rights file was not successfully saved, restore user rights to previous value
- _logger.warn("Reverting attempted rights update for user'" + username + "'");
- if (oldRights != null)
- {
- _accessRights.put(username, oldRights);
- }
- else
- {
- _accessRights.remove(username);
- }
-
- return false;
- }
- }
- finally
- {
- _accessRightsUpdate.unlock();
- }
-
- return true;
- }
-
- public boolean createUser(String username, String password, boolean read, boolean write, boolean admin)
- {
- return createUser(username, password.toCharArray(), read, write, admin);
- }
-
- public boolean createUser(String username, char[] password, boolean read, boolean write, boolean admin)
+ public boolean createUser(String username, String password)
{
- if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password))
+ if (_principalDatabase.createPrincipal(new UsernamePrincipal(username), password.toCharArray()))
{
- if (!setRights(username, read, write, admin))
- {
- //unable to set rights for user, remove account
- try
- {
- _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
- }
- catch (AccountNotFoundException e)
- {
- //ignore
- }
- return false;
- }
- else
- {
- return true;
- }
+ return true;
}
return false;
@@ -234,29 +117,7 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
{
try
{
- if (_principalDatabase.deletePrincipal(new UsernamePrincipal(username)))
- {
- try
- {
- _accessRightsUpdate.lock();
-
- _accessRights.remove(username);
-
- try
- {
- saveAccessFile();
- }
- catch (IOException e)
- {
- _logger.warn("Problem occured saving '" + _accessFile + "', the access right changes will not be preserved: " + e);
- return false;
- }
- }
- finally
- {
- _accessRightsUpdate.unlock();
- }
- }
+ _principalDatabase.deletePrincipal(new UsernamePrincipal(username));
}
catch (AccountNotFoundException e)
{
@@ -269,38 +130,23 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
public boolean reloadData()
{
- try
- {
- loadAccessFile();
- _principalDatabase.reload();
- }
- catch (ConfigurationException e)
- {
- _logger.warn("Reload failed due to:" + e);
- return false;
- }
- catch (IOException e)
- {
- _logger.warn("Reload failed due to:" + e);
- return false;
- }
- // Reload successful
- return true;
+ 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 with access rights to the system.")
+ @MBeanOperation(name = "viewUsers", description = "All users that are currently available to the system.")
public TabularData viewUsers()
{
- // Table of users
- // Username(string), Access rights Read,Write,Admin(bool,bool,bool)
-
- if (_userlistDataType == null)
- {
- _logger.warn("TabluarData not setup correctly");
- return null;
- }
-
List<Principal> users = _principalDatabase.getUsers();
TabularDataSupport userList = new TabularDataSupport(_userlistDataType);
@@ -311,29 +157,15 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
for (Principal user : users)
{
// Create header attributes list
-
- String rights = (String) _accessRights.get(user.getName());
-
- Boolean read = false;
- Boolean write = false;
- Boolean admin = false;
-
- if (rights != null)
- {
- read = rights.equals(MBeanInvocationHandlerImpl.READONLY)
- || rights.equals(MBeanInvocationHandlerImpl.READWRITE);
- write = rights.equals(MBeanInvocationHandlerImpl.READWRITE);
- admin = rights.equals(MBeanInvocationHandlerImpl.ADMIN);
- }
-
- Object[] itemData = {user.getName(), read, write, admin};
+ // 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);
+ _logger.warn("Unable to create user list due to :", e);
return null;
}
@@ -351,187 +183,4 @@ public class AMQUserManagementMBean extends AMQManagedObject implements UserMana
{
_principalDatabase = database;
}
-
- /**
- * setAccessFile
- *
- * @param accessFile the file to use for updating.
- *
- * @throws java.io.IOException If the file cannot be accessed
- * @throws org.apache.commons.configuration.ConfigurationException
- * if checks on the file fail.
- */
- public void setAccessFile(String accessFile) throws IOException, ConfigurationException
- {
- if (accessFile != null)
- {
- _accessFile = new File(accessFile);
- if (!_accessFile.exists())
- {
- throw new ConfigurationException("'" + _accessFile + "' does not exist");
- }
-
- if (!_accessFile.canRead())
- {
- throw new ConfigurationException("Cannot read '" + _accessFile + "'.");
- }
-
- if (!_accessFile.canWrite())
- {
- _logger.warn("Unable to write to access rights file '" + _accessFile + "', changes will not be preserved.");
- }
-
- loadAccessFile();
- }
- else
- {
- _logger.warn("Access rights file specified is null. Access rights not changed.");
- }
- }
-
- private void loadAccessFile() throws IOException, ConfigurationException
- {
- if(_accessFile == null)
- {
- _logger.error("No jmx access rights file has been specified.");
- return;
- }
-
- if(_accessFile.exists())
- {
- try
- {
- _accessRightsUpdate.lock();
-
- Properties accessRights = new Properties();
- FileInputStream inStream = new FileInputStream(_accessFile);
- try
- {
- accessRights.load(inStream);
- }
- finally
- {
- inStream.close();
- }
-
- checkAccessRights(accessRights);
- setAccessRights(accessRights);
- }
- finally
- {
- _accessRightsUpdate.unlock();
- }
- }
- else
- {
- _logger.error("Specified jmxaccess rights file '" + _accessFile + "' does not exist.");
- }
- }
-
- private void checkAccessRights(Properties accessRights)
- {
- Enumeration values = accessRights.propertyNames();
-
- while (values.hasMoreElements())
- {
- String user = (String) values.nextElement();
-
- if (_principalDatabase.getUser(user) == null)
- {
- _logger.warn("Access rights contains user '" + user + "' but there is no authentication data for that user");
- }
- }
- }
-
- private void saveAccessFile() throws IOException
- {
- try
- {
- _accessRightsUpdate.lock();
-
- // Create temporary file
- Random r = new Random();
- File tmp;
- do
- {
- tmp = new File(_accessFile.getPath() + r.nextInt() + ".tmp");
- }
- while(tmp.exists());
-
- tmp.deleteOnExit();
-
- FileOutputStream output = new FileOutputStream(tmp);
- _accessRights.store(output, "Generated by AMQUserManagementMBean Console : Last edited by user:" + getCurrentJMXUser());
- output.close();
-
- // Swap temp file to main rights file.
- File old = new File(_accessFile.getAbsoluteFile() + ".old");
- if (old.exists())
- {
- old.delete();
- }
-
- if(!_accessFile.renameTo(old))
- {
- //unable to rename the existing file to the backup name
- _logger.error("Could not backup the existing management rights file");
- throw new IOException("Could not backup the existing management rights file");
- }
-
- if(!tmp.renameTo(_accessFile))
- {
- //failed to rename the new file to the required filename
-
- if(!old.renameTo(_accessFile))
- {
- //unable to return the backup to required filename
- _logger.error("Could not rename the new management rights file into place, and unable to restore original file");
- throw new IOException("Could not rename the new management rights file into place, and unable to restore original file");
- }
-
- _logger.error("Could not rename the new management rights file into place");
- throw new IOException("Could not rename the new management rights file into place");
- }
- }
- finally
- {
- _accessRightsUpdate.unlock();
- }
-
- }
-
- private String getCurrentJMXUser()
- {
- AccessControlContext acc = AccessController.getContext();
-
- Subject subject = Subject.getSubject(acc);
- if (subject == null)
- {
- return "Unknown user, authentication Subject was null";
- }
-
- // Retrieve JMXPrincipal from Subject
- Set<JMXPrincipal> principals = subject.getPrincipals(JMXPrincipal.class);
- if (principals == null || principals.isEmpty())
- {
- return "Unknown user principals were null";
- }
-
- Principal principal = principals.iterator().next();
- return principal.getName();
- }
-
- /**
- * user=read user=write user=readwrite user=admin
- *
- * @param accessRights The properties list of access rights to process
- */
- private void setAccessRights(Properties accessRights)
- {
- _logger.debug("Setting Access Rights:" + accessRights);
- _accessRights = accessRights;
-
- // TODO check where this is used
- // MBeanInvocationHandlerImpl.setAccessRights(_accessRights);
- }
}
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 bc771162fd..4c59c25d84 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
@@ -20,17 +20,73 @@
*/
package org.apache.qpid.server.security.auth.manager;
+import javax.security.auth.Subject;
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;
-public interface AuthenticationManager extends Closeable
+/**
+ * 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 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
{
+ /** The name for the required SASL Server mechanisms */
+ public static final String PROVIDER_NAME= "AMQSASLProvider-Server";
+
+ /**
+ * Initialise the authentication plugin.
+ *
+ */
+ void initialise();
+
+ /**
+ * Gets the SASL mechanisms known to this manager.
+ *
+ * @return SASL mechanism names, space separated.
+ */
String getMechanisms();
+ /**
+ * Creates a SASL server for the specified mechanism name for the given
+ * fully qualified domain name.
+ *
+ * @param mechanism mechanism name
+ * @param localFQDN domain name
+ *
+ * @return SASL server
+ * @throws SaslException
+ */
SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException;
+ /**
+ * Authenticates a user using SASL negotiation.
+ *
+ * @param server SASL server
+ * @param response SASL response to process
+ *
+ * @return authentication result
+ */
AuthenticationResult authenticate(SaslServer server, byte[] response);
+
+ /**
+ * Authenticates a user using their username and password.
+ *
+ * @param username username
+ * @param password password
+ *
+ * @return authentication result
+ */
+ AuthenticationResult authenticate(String username, String password);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java
new file mode 100644
index 0000000000..a51f195761
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/manager/AuthenticationManagerPluginFactory.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.security.auth.manager;
+
+import org.apache.qpid.server.plugins.PluginFactory;
+
+/**
+ * Factory producing authentication producing configured, initialised authentication
+ * managers.
+ */
+public interface AuthenticationManagerPluginFactory<S extends AuthenticationManager> extends PluginFactory<S>
+{
+
+}
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 2a967f02af..1945c2e15f 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
@@ -20,27 +20,65 @@
*/
package org.apache.qpid.server.security.auth.manager;
-import org.apache.log4j.Logger;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.Security;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.login.AccountNotFoundException;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
+import javax.security.sasl.SaslServer;
+import javax.security.sasl.SaslServerFactory;
+
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
-import org.apache.qpid.server.configuration.VirtualHostConfiguration;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.security.auth.manager.AuthenticationManager;
+import org.apache.log4j.Logger;
+import org.apache.qpid.configuration.PropertyException;
+import org.apache.qpid.configuration.PropertyUtils;
+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.AuthenticationResult.AuthenticationStatus;
import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-import org.apache.qpid.server.security.auth.sasl.JCAProvider;
+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.AuthenticationResult;
+import org.apache.qpid.server.security.auth.sasl.JCAProvider;
+import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.sasl.SaslServerFactory;
-import javax.security.sasl.SaslServer;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.Sasl;
-import java.util.Map;
-import java.util.HashMap;
-import java.util.TreeMap;
-import java.security.Security;
+/**
+ * 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>
+ * &lt;pd-auth-manager&gt;
+ * &lt;principal-database&gt;
+ * &lt;class&gt;org.apache.qpid.server.security.auth.database.PlainPasswordFilePrincipalDatabase&lt;/class&gt;
+ * &lt;attributes&gt;
+ * &lt;attribute&gt;
+ * &lt;name>passwordFile&lt;/name&gt;
+ * &lt;value>${conf}/passwd&lt;/value&gt;
+ * &lt;/attribute&gt;
+ * &lt;/attributes&gt;
+ * &lt;/principal-database&gt;
+ * &lt;/pd-auth-manager&gt;
+ * </pre>
+ */
public class PrincipalDatabaseAuthenticationManager implements AuthenticationManager
{
private static final Logger _logger = Logger.getLogger(PrincipalDatabaseAuthenticationManager.class);
@@ -49,55 +87,109 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
private String _mechanisms;
/** Maps from the mechanism to the callback handler to use for handling those requests */
- private Map<String, CallbackHandler> _callbackHandlerMap = new HashMap<String, CallbackHandler>();
+ private final Map<String, CallbackHandler> _callbackHandlerMap = new HashMap<String, CallbackHandler>();
/**
* Maps from the mechanism to the properties used to initialise the server. See the method Sasl.createSaslServer for
* details of the use of these properties. This map is populated during initialisation of each provider.
*/
- private Map<String, Map<String, ?>> _serverCreationProperties = new HashMap<String, Map<String, ?>>();
+ private final Map<String, Map<String, ?>> _serverCreationProperties = new HashMap<String, Map<String, ?>>();
- private AuthenticationManager _default = null;
- /** The name for the required SASL Server mechanisms */
- public static final String PROVIDER_NAME= "AMQSASLProvider-Server";
+ protected PrincipalDatabase _principalDatabase = null;
- public PrincipalDatabaseAuthenticationManager(String name, VirtualHostConfiguration hostConfig) throws Exception
- {
- _logger.info("Initialising " + (name == null ? "Default" : "'" + name + "'")
- + " PrincipalDatabase authentication manager.");
+ protected AMQUserManagementMBean _mbean = null;
- // Fixme This should be done per Vhost but allowing global hack isn't right but ...
- // required as authentication is done before Vhost selection
+ 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());
- Map<String, Class<? extends SaslServerFactory>> providerMap = new TreeMap<String, Class<? extends SaslServerFactory>>();
+ // If there is no configuration for this plugin then don't load it.
+ if (configuration == null)
+ {
+ _logger.info("No authentication-manager configuration found for PrincipalDatabaseAuthenticationManager");
+ return null;
+ }
+ final PrincipalDatabaseAuthenticationManager pdam = new PrincipalDatabaseAuthenticationManager();
+ pdam.configure(configuration);
+ pdam.initialise();
+ return pdam;
+ }
- if (name == null || hostConfig == null)
+ public Class<PrincipalDatabaseAuthenticationManager> getPluginClass()
{
- initialiseAuthenticationMechanisms(providerMap, ApplicationRegistry.getInstance().getDatabaseManager().getDatabases());
+ return PrincipalDatabaseAuthenticationManager.class;
}
- else
+
+ public String getPluginName()
{
- String databaseName = hostConfig.getAuthenticationDatabase();
+ return PrincipalDatabaseAuthenticationManager.class.getName();
+ }
+ };
- if (databaseName == null)
+ public static class PrincipalDatabaseAuthenticationManagerConfiguration extends ConfigurationPlugin {
+
+ public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+ {
+ public List<String> getParentPaths()
{
-
- _default = ApplicationRegistry.getInstance().getAuthenticationManager();
- return;
+ return Arrays.asList("security.pd-auth-manager");
}
- else
+
+ public ConfigurationPlugin newInstance(final String path, final Configuration config) throws ConfigurationException
{
- PrincipalDatabase database = ApplicationRegistry.getInstance().getDatabaseManager().getDatabases().get(databaseName);
+ final ConfigurationPlugin instance = new PrincipalDatabaseAuthenticationManagerConfiguration();
+
+ instance.setConfiguration(path, config);
+ return instance;
+ }
+ };
- if (database == null)
- {
- throw new ConfigurationException("Requested database:" + databaseName + " was not found");
- }
+ public String[] getElementsProcessed()
+ {
+ return new String[] {"principal-database.class",
+ "principal-database.attributes.attribute.name",
+ "principal-database.attributes.attribute.value"};
+ }
- initialiseAuthenticationMechanisms(providerMap, database);
+ public void validateConfiguration() throws ConfigurationException
+ {
+ }
+
+ public String getPrincipalDatabaseClass()
+ {
+ return _configuration.getString("principal-database.class");
+ }
+
+ public Map<String,String> getPdClassAttributeMap() throws ConfigurationException
+ {
+ final List<String> argumentNames = _configuration.getList("principal-database.attributes.attribute.name");
+ final List<String> argumentValues = _configuration.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++)
+ {
+ final String argName = argumentNames.get(i);
+ final String argValue = argumentValues.get(i);
+
+ attributes.put(argName, argValue);
}
+
+ return Collections.unmodifiableMap(attributes);
}
+ }
+
+ protected PrincipalDatabaseAuthenticationManager()
+ {
+ }
+
+ public void initialise()
+ {
+ final Map<String, Class<? extends SaslServerFactory>> providerMap = new TreeMap<String, Class<? extends SaslServerFactory>>();
+
+ initialiseAuthenticationMechanisms(providerMap, _principalDatabase);
if (providerMap.size() > 0)
{
@@ -110,33 +202,16 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
{
_logger.info("Additional SASL providers successfully registered.");
}
-
}
else
{
_logger.warn("No additional SASL providers registered.");
}
+ registerManagement();
}
-
- private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, Map<String, PrincipalDatabase> databases) throws Exception
- {
- if (databases.size() > 1)
- {
- _logger.warn("More than one principle database provided currently authentication mechanism will override each other.");
- }
-
- for (Map.Entry<String, PrincipalDatabase> entry : databases.entrySet())
- {
- // fixme As the database now provide the mechanisms they support, they will ...
- // overwrite each other in the map. There should only be one database per vhost.
- // But currently we must have authentication before vhost definition.
- initialiseAuthenticationMechanisms(providerMap, entry.getValue());
- }
- }
-
- private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database) throws Exception
+ private void initialiseAuthenticationMechanisms(Map<String, Class<? extends SaslServerFactory>> providerMap, PrincipalDatabase database)
{
if (database == null || database.getMechanisms().size() == 0)
{
@@ -152,7 +227,6 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
private void initialiseAuthenticationMechanism(String mechanism, AuthenticationProviderInitialiser initialiser,
Map<String, Class<? extends SaslServerFactory>> providerMap)
- throws Exception
{
if (_mechanisms == null)
{
@@ -173,43 +247,37 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
_logger.info("Initialised " + mechanism + " SASL provider successfully");
}
+ /**
+ * @see org.apache.qpid.server.plugins.Plugin#configure(org.apache.qpid.server.configuration.plugins.ConfigurationPlugin)
+ */
+ public void configure(final ConfigurationPlugin config) throws ConfigurationException
+ {
+ final PrincipalDatabaseAuthenticationManagerConfiguration pdamConfig = (PrincipalDatabaseAuthenticationManagerConfiguration) config;
+ final String pdClazz = pdamConfig.getPrincipalDatabaseClass();
+
+ _logger.info("PrincipalDatabase concrete implementation : " + pdClazz);
+
+ _principalDatabase = createPrincipalDatabaseImpl(pdClazz);
+
+ configPrincipalDatabase(_principalDatabase, pdamConfig);
+ }
+
public String getMechanisms()
{
- if (_default != null)
- {
- // Use the default AuthenticationManager if present
- return _default.getMechanisms();
- }
- else
- {
- return _mechanisms;
- }
+ return _mechanisms;
}
public SaslServer createSaslServer(String mechanism, String localFQDN) throws SaslException
{
- if (_default != null)
- {
- // Use the default AuthenticationManager if present
- return _default.createSaslServer(mechanism, localFQDN);
- }
- else
- {
- return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
- _callbackHandlerMap.get(mechanism));
- }
-
+ return Sasl.createSaslServer(mechanism, "AMQP", localFQDN, _serverCreationProperties.get(mechanism),
+ _callbackHandlerMap.get(mechanism));
}
+ /**
+ * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(SaslServer, byte[])
+ */
public AuthenticationResult authenticate(SaslServer server, byte[] response)
{
- // Use the default AuthenticationManager if present
- if (_default != null)
- {
- return _default.authenticate(server, response);
- }
-
-
try
{
// Process response from the client
@@ -217,7 +285,9 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
if (server.isComplete())
{
- return new AuthenticationResult(challenge, AuthenticationResult.AuthenticationStatus.SUCCESS);
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new UsernamePrincipal(server.getAuthorizationID()));
+ return new AuthenticationResult(subject);
}
else
{
@@ -230,8 +300,164 @@ public class PrincipalDatabaseAuthenticationManager implements AuthenticationMan
}
}
+ /**
+ * @see org.apache.qpid.server.security.auth.manager.AuthenticationManager#authenticate(String, String)
+ */
+ public AuthenticationResult authenticate(final String username, final String password)
+ {
+ try
+ {
+ if (_principalDatabase.verifyPassword(username, password.toCharArray()))
+ {
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new UsernamePrincipal(username));
+ return new AuthenticationResult(subject);
+ }
+ else
+ {
+ return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+ }
+ }
+ catch (AccountNotFoundException e)
+ {
+ return new AuthenticationResult(AuthenticationStatus.CONTINUE);
+ }
+ }
+
public void close()
{
+ _mechanisms = null;
Security.removeProvider(PROVIDER_NAME);
+
+ unregisterManagement();
+ }
+
+ private PrincipalDatabase createPrincipalDatabaseImpl(final String pdClazz) throws ConfigurationException
+ {
+ try
+ {
+ return (PrincipalDatabase) Class.forName(pdClazz).newInstance();
+ }
+ catch (InstantiationException ie)
+ {
+ throw new ConfigurationException("Cannot instantiate " + pdClazz, ie);
+ }
+ catch (IllegalAccessException iae)
+ {
+ throw new ConfigurationException("Cannot access " + pdClazz, iae);
+ }
+ catch (ClassNotFoundException cnfe)
+ {
+ throw new ConfigurationException("Cannot load " + pdClazz + " implementation", cnfe);
+ }
+ catch (ClassCastException cce)
+ {
+ throw new ConfigurationException("Expecting a " + PrincipalDatabase.class + " implementation", cce);
+ }
+ }
+
+ private void configPrincipalDatabase(final PrincipalDatabase principalDatabase, final PrincipalDatabaseAuthenticationManagerConfiguration config)
+ throws ConfigurationException
+ {
+
+ final Map<String,String> attributes = config.getPdClassAttributeMap();
+
+ for (Iterator<Entry<String, String>> iterator = attributes.entrySet().iterator(); iterator.hasNext();)
+ {
+ final Entry<String, String> nameValuePair = iterator.next();
+ final String methodName = generateSetterName(nameValuePair.getKey());
+ final Method method;
+ try
+ {
+ method = principalDatabase.getClass().getMethod(methodName, String.class);
+ }
+ catch (Exception e)
+ {
+ throw new ConfigurationException("No method " + methodName + " found in class "
+ + principalDatabase.getClass()
+ + " hence unable to configure principal database. The method must be public and "
+ + "have a single String argument with a void return type", e);
+ }
+ try
+ {
+ method.invoke(principalDatabase, PropertyUtils.replaceProperties(nameValuePair.getValue()));
+ }
+ catch (IllegalArgumentException e)
+ {
+ throw new ConfigurationException(e.getMessage(), e);
+ }
+ catch (PropertyException e)
+ {
+ throw new ConfigurationException(e.getMessage(), e);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ConfigurationException(e.getMessage(), e);
+ }
+ catch (InvocationTargetException e)
+ {
+ // QPID-1347.. InvocationTargetException wraps the checked exception thrown from the reflective
+ // method call. Pull out the underlying message and cause to make these more apparent to the user.
+ throw new ConfigurationException(e.getCause().getMessage(), e.getCause());
+ }
+ }
+ }
+
+ private String generateSetterName(String argName) throws ConfigurationException
+ {
+ if ((argName == null) || (argName.length() == 0))
+ {
+ throw new ConfigurationException("Argument names must have length >= 1 character");
+ }
+
+ if (Character.isLowerCase(argName.charAt(0)))
+ {
+ argName = Character.toUpperCase(argName.charAt(0)) + argName.substring(1);
+ }
+
+ final String methodName = "set" + argName;
+ return methodName;
+ }
+
+ protected void setPrincipalDatabase(final PrincipalDatabase principalDatabase)
+ {
+ _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/rmi/RMIPasswordAuthenticator.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/rmi/RMIPasswordAuthenticator.java
index 0cbbccb3b8..b7985ad972 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,14 +20,13 @@
*/
package org.apache.qpid.server.security.auth.rmi;
-import java.util.Collections;
-
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;
-import javax.security.auth.login.AccountNotFoundException;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
+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;
public class RMIPasswordAuthenticator implements JMXAuthenticator
{
@@ -39,15 +38,15 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
static final String CREDENTIALS_REQUIRED = "User details are required. " +
"Please ensure you are using an up to date management console to connect.";
- private PrincipalDatabase _db = null;
+ private AuthenticationManager _authenticationManager = null;
public RMIPasswordAuthenticator()
{
}
-
- public void setPrincipalDatabase(PrincipalDatabase pd)
+
+ public void setAuthenticationManager(final AuthenticationManager authenticationManager)
{
- this._db = pd;
+ _authenticationManager = authenticationManager;
}
public Subject authenticate(Object credentials) throws SecurityException
@@ -65,50 +64,39 @@ public class RMIPasswordAuthenticator implements JMXAuthenticator
}
}
- // Verify that required number of credential's.
+ // Verify that required number of credentials.
final String[] userCredentials = (String[]) credentials;
if (userCredentials.length != 2)
{
throw new SecurityException(SHOULD_HAVE_2_ELEMENTS);
}
- String username = (String) userCredentials[0];
- String password = (String) userCredentials[1];
+ final String username = (String) userCredentials[0];
+ final String password = (String) userCredentials[1];
- // Verify that all required credential's are actually present.
+ // Verify that all required credentials are actually present.
if (username == null || password == null)
{
throw new SecurityException(SHOULD_BE_NON_NULL);
}
- // Verify that a PD has been set.
- if (_db == null)
+ // Verify that an AuthenticationManager has been set.
+ if (_authenticationManager == null)
{
throw new SecurityException(UNABLE_TO_LOOKUP);
}
-
- boolean authenticated = false;
+ final AuthenticationResult result = _authenticationManager.authenticate(username, password);
- // Perform authentication
- try
+ if (AuthenticationStatus.ERROR.equals(result.getStatus()))
{
- if (_db.verifyPassword(username, password.toCharArray()))
- {
- authenticated = true;
- }
- }
- catch (AccountNotFoundException e)
- {
- throw new SecurityException(INVALID_CREDENTIALS); // XXX
+ throw new SecurityException("Authentication manager failed", result.getCause());
}
-
- if (authenticated)
+ else if (AuthenticationStatus.SUCCESS.equals(result.getStatus()))
{
- //credential's check out, return the appropriate JAAS Subject
- return new Subject(true,
- Collections.singleton(new JMXPrincipal(username)),
- Collections.EMPTY_SET,
- Collections.EMPTY_SET);
+ final Subject subject = result.getSubject();
+ subject.getPrincipals().add(new JMXPrincipal(username));
+ subject.setReadOnly();
+ return subject;
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java
index 89e545d6f5..bc5d8a4f2b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/AuthenticationProviderInitialiser.java
@@ -25,9 +25,6 @@ import java.util.Map;
import javax.security.auth.callback.CallbackHandler;
import javax.security.sasl.SaslServerFactory;
-import org.apache.commons.configuration.Configuration;
-import org.apache.qpid.server.security.auth.database.PrincipalDatabase;
-
public interface AuthenticationProviderInitialiser
{
/**
@@ -37,24 +34,6 @@ public interface AuthenticationProviderInitialiser
String getMechanismName();
/**
- * Initialise the authentication provider.
- * @param baseConfigPath the path in the config file that points to any config options for this provider. Each
- * provider can have its own set of configuration options
- * @param configuration the Apache Commons Configuration instance used to configure this provider
- * @param principalDatabases the set of principal databases that are available
- * @throws Exception needs refined Exception is too broad.
- */
- void initialise(String baseConfigPath, Configuration configuration,
- Map<String, PrincipalDatabase> principalDatabases) throws Exception;
-
- /**
- * Initialise the authentication provider.
- * @param db The principal database to initialise with
- */
- void initialise(PrincipalDatabase db);
-
-
- /**
* @return the callback handler that should be used to process authentication requests for this mechanism. This will
* be called after initialise and will be stored by the authentication manager. The callback handler <b>must</b> be
* fully threadsafe.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java
new file mode 100644
index 0000000000..30a503c769
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/GroupPrincipal.java
@@ -0,0 +1,99 @@
+/*
+ *
+ * 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;
+
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+
+/**
+ * Immutable representation of a user group. In Qpid, groups do <b>not</b> know
+ * about their membership, and therefore the {@link #addMember(Principal)}
+ * methods etc throw {@link UnsupportedOperationException}.
+ *
+ */
+public class GroupPrincipal implements Group
+{
+ /** Name of the group */
+ private final String _groupName;
+
+ public GroupPrincipal(final String groupName)
+ {
+ _groupName = groupName;
+ }
+
+ public String getName()
+ {
+ return _groupName;
+ }
+
+ public boolean addMember(Principal user)
+ {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ public boolean removeMember(Principal user)
+ {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ public boolean isMember(Principal member)
+ {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ public Enumeration<? extends Principal> members()
+ {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode()
+ {
+ final int prime = 37;
+ return prime * _groupName.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ else
+ {
+ if (obj instanceof GroupPrincipal)
+ {
+ GroupPrincipal other = (GroupPrincipal) obj;
+ return _groupName.equals(other._groupName);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
index d6a09d8217..d6f6c714e2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/JCAProvider.java
@@ -21,12 +21,11 @@
package org.apache.qpid.server.security.auth.sasl;
import java.security.Provider;
-import java.security.Security;
import java.util.Map;
import javax.security.sasl.SaslServerFactory;
-public final class JCAProvider extends Provider
+public class JCAProvider extends Provider
{
public JCAProvider(String name, Map<String, Class<? extends SaslServerFactory>> providerMap)
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
index d7c8383690..b4ee13fe6b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/UsernamePrincipal.java
@@ -21,14 +21,21 @@
package org.apache.qpid.server.security.auth.sasl;
import java.security.Principal;
+import java.util.Set;
+
+import javax.security.auth.Subject;
/** A principal that is just a wrapper for a simple username. */
public class UsernamePrincipal implements Principal
{
- private String _name;
+ private final String _name;
public UsernamePrincipal(String name)
{
+ if (name == null)
+ {
+ throw new IllegalArgumentException("name cannot be null");
+ }
_name = name;
}
@@ -41,4 +48,53 @@ public class UsernamePrincipal implements Principal
{
return _name;
}
+
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode()
+ {
+ final int prime = 31;
+ return prime * _name.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (this == obj)
+ {
+ return true;
+ }
+ else
+ {
+ if (obj instanceof UsernamePrincipal)
+ {
+ UsernamePrincipal other = (UsernamePrincipal) obj;
+ return _name.equals(other._name);
+ }
+ else
+ {
+ return false;
+ }
+ }
+ }
+
+ public static UsernamePrincipal getUsernamePrincipalFromSubject(final Subject authSubject)
+ {
+ if (authSubject == null)
+ {
+ throw new IllegalArgumentException("No authenticated subject.");
+ }
+
+ final Set<UsernamePrincipal> principals = authSubject.getPrincipals(UsernamePrincipal.class);
+ if (principals.size() != 1)
+ {
+ throw new IllegalArgumentException("Can't find single UsernamePrincipal in authenticated subject");
+ }
+ return principals.iterator().next();
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
index 9f56b8521a..dee40e7069 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServer.java
@@ -20,6 +20,8 @@
*/
package org.apache.qpid.server.security.auth.sasl.amqplain;
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
import java.io.IOException;
import javax.security.auth.callback.Callback;
@@ -31,7 +33,6 @@ import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
-import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.AMQFrameDecodingException;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
@@ -60,7 +61,7 @@ public class AmqPlainSaslServer implements SaslServer
{
try
{
- final FieldTable ft = FieldTableFactory.newFieldTable(ByteBuffer.wrap(response), response.length);
+ final FieldTable ft = FieldTableFactory.newFieldTable(new DataInputStream(new ByteArrayInputStream(response)), response.length);
String username = (String) ft.getString("LOGIN");
// we do not care about the prompt but it throws if null
NameCallback nameCb = new NameCallback("prompt", username);
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java
index 67d20136bf..17d123eb0d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/amqplain/AmqPlainSaslServerFactory.java
@@ -45,9 +45,10 @@ public class AmqPlainSaslServerFactory implements SaslServerFactory
public String[] getMechanismNames(Map props)
{
- if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
- props.containsKey(Sasl.POLICY_NODICTIONARY) ||
- props.containsKey(Sasl.POLICY_NOACTIVE))
+ if (props != null &&
+ (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE)))
{
// returned array must be non null according to interface documentation
return new String[0];
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java
index b4cce15d88..52d36023c2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServer.java
@@ -20,21 +20,9 @@
*/
package org.apache.qpid.server.security.auth.sasl.anonymous;
-import java.io.IOException;
-
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.sasl.AuthorizeCallback;
import javax.security.sasl.SaslException;
import javax.security.sasl.SaslServer;
-import org.apache.mina.common.ByteBuffer;
-import org.apache.qpid.framing.AMQFrameDecodingException;
-import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.FieldTableFactory;
public class AnonymousSaslServer implements SaslServer
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
index 6032255870..8a5ff7df2d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/anonymous/AnonymousSaslServerFactory.java
@@ -47,10 +47,11 @@ public class AnonymousSaslServerFactory implements SaslServerFactory
public String[] getMechanismNames(Map props)
{
- if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
- props.containsKey(Sasl.POLICY_NODICTIONARY) ||
- props.containsKey(Sasl.POLICY_NOACTIVE) ||
- props.containsKey(Sasl.POLICY_NOANONYMOUS))
+ if (props != null &&
+ (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE) ||
+ props.containsKey(Sasl.POLICY_NOANONYMOUS)))
{
// returned array must be non null according to interface documentation
return new String[0];
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
index 8020d97364..139818735f 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/crammd5/CRAMMD5HexInitialiser.java
@@ -70,7 +70,7 @@ public class CRAMMD5HexInitialiser extends UsernamePasswordInitialiser
for (char c : password)
{
//toHexString does not prepend 0 so we have to
- if (((byte) c > -1) && (byte) c < 10)
+ if (((byte) c > -1) && (byte) c < 0x10 )
{
sb.append(0);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
index f0dd9eeb6d..3144bfbce6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/sasl/plain/PlainSaslServerFactory.java
@@ -45,9 +45,10 @@ public class PlainSaslServerFactory implements SaslServerFactory
public String[] getMechanismNames(Map props)
{
- if (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
- props.containsKey(Sasl.POLICY_NODICTIONARY) ||
- props.containsKey(Sasl.POLICY_NOACTIVE))
+ if (props != null &&
+ (props.containsKey(Sasl.POLICY_NOPLAINTEXT) ||
+ props.containsKey(Sasl.POLICY_NODICTIONARY) ||
+ props.containsKey(Sasl.POLICY_NOACTIVE)))
{
// returned array must be non null according to interface documentation
return new String[0];
diff --git a/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java b/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java
new file mode 100644
index 0000000000..4e3fae1dbd
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/signal/SignalHandlerTask.java
@@ -0,0 +1,89 @@
+/*
+ *
+ * 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.signal;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+
+import org.apache.log4j.Logger;
+
+public abstract class SignalHandlerTask
+{
+ private static final Logger LOGGER = Logger.getLogger(SignalHandlerTask.class);
+
+ private static final String HANDLE_METHOD = "handle";
+ private static final String SUN_MISC_SIGNAL_CLASS = "sun.misc.Signal";
+ private static final String SUN_MISC_SIGNAL_HANDLER_CLASS = "sun.misc.SignalHandler";
+
+ public boolean register(final String signalName)
+ {
+ try
+ {
+ //try to load the signal handling classes
+ Class<?> signalClazz = Class.forName(SUN_MISC_SIGNAL_CLASS);
+ Class<?> handlerClazz = Class.forName(SUN_MISC_SIGNAL_HANDLER_CLASS);
+
+ //create an InvocationHandler that just executes the SignalHandlerTask
+ InvocationHandler invoker = new InvocationHandler()
+ {
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
+ {
+ handle();
+
+ return null;
+ }
+ };
+
+ //create a dynamic proxy implementing SignalHandler
+ Object handler = Proxy.newProxyInstance(handlerClazz.getClassLoader(), new Class[]{handlerClazz}, invoker);
+
+ //create the Signal to handle
+ Constructor<?> signalConstructor = signalClazz.getConstructor(String.class);
+ Object signal = signalConstructor.newInstance(signalName);
+
+ //invoke the Signal.handle(signal, handler) method
+ Method handleMethod = signalClazz.getMethod(HANDLE_METHOD, signalClazz, handlerClazz);
+ handleMethod.invoke(null, signal, handler);
+ }
+ catch (Exception e)
+ {
+ LOGGER.debug("Unable to register handler for Signal " + signalName + " due to exception: " + e, e);
+ return false;
+ }
+
+ return true;
+ }
+
+ public abstract void handle();
+
+ public static String getPlatformDescription()
+ {
+ String name = System.getProperty("os.name");
+ String osVer = System.getProperty("os.version");
+ String jvmVendor = System.getProperty("java.vm.vendor");
+ String jvmName = System.getProperty("java.vm.name");
+ String javaRuntimeVer = System.getProperty("java.runtime.version");
+
+ return "OS: " + name + " " + osVer + ", JVM:" + jvmVendor + " " + jvmName + " " + javaRuntimeVer;
+ }
+}
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 6cc5e7b019..33aebffcfb 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
@@ -259,7 +259,7 @@ public class AMQStateManager implements AMQMethodListener
public AMQProtocolSession getProtocolSession()
{
- SecurityManager.setThreadPrincipal(_protocolSession.getPrincipal());
+ SecurityManager.setThreadSubject(_protocolSession.getAuthorizedSubject());
return _protocolSession;
}
}
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
new file mode 100644
index 0000000000..b732121180
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsCounter.java
@@ -0,0 +1,163 @@
+/*
+ * 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.stats;
+
+import java.util.Date;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class collects statistics and counts the total, rate per second and
+ * peak rate per second values for the events that are registered with it.
+ */
+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);
+
+ private long _peak = 0L;
+ private long _total = 0L;
+ private long _temp = 0L;
+ private long _last = 0L;
+ private long _rate = 0L;
+
+ private long _start;
+
+ private final long _period;
+ private final String _name;
+
+ public StatisticsCounter()
+ {
+ this(COUNTER);
+ }
+
+ public StatisticsCounter(String name)
+ {
+ this(name, DEFAULT_SAMPLE_PERIOD);
+ }
+
+ public StatisticsCounter(String name, long period)
+ {
+ _period = period;
+ _name = name + "-" + + _counterIds.incrementAndGet();
+ reset();
+ }
+
+ public void registerEvent()
+ {
+ registerEvent(1L);
+ }
+
+ public void registerEvent(long value)
+ {
+ registerEvent(value, System.currentTimeMillis());
+ }
+
+ public void registerEvent(long value, long timestamp)
+ {
+ if (DISABLE_STATISTICS)
+ {
+ return;
+ }
+
+ long thisSample = (timestamp / _period);
+ synchronized (this)
+ {
+ if (thisSample > _last)
+ {
+ _last = thisSample;
+ _rate = _temp;
+ _temp = 0L;
+ if (_rate > _peak)
+ {
+ _peak = _rate;
+ }
+ }
+
+ _total += value;
+ _temp += value;
+ }
+ }
+
+ /**
+ * Update the current rate and peak - may reset rate to zero if a new
+ * sample period has started.
+ */
+ private void update()
+ {
+ registerEvent(0L, System.currentTimeMillis());
+ }
+
+ /**
+ * Reset
+ */
+ public void reset()
+ {
+ _log.info("Resetting statistics for counter: " + _name);
+ _peak = 0L;
+ _rate = 0L;
+ _total = 0L;
+ _start = System.currentTimeMillis();
+ _last = _start / _period;
+ }
+
+ public double getPeak()
+ {
+ update();
+ return (double) _peak / ((double) _period / 1000.0d);
+ }
+
+ public double getRate()
+ {
+ update();
+ return (double) _rate / ((double) _period / 1000.0d);
+ }
+
+ public long getTotal()
+ {
+ return _total;
+ }
+
+ public long getStart()
+ {
+ return _start;
+ }
+
+ public Date getStartTime()
+ {
+ return new Date(_start);
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public long getPeriod()
+ {
+ return _period;
+ }
+}
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
new file mode 100644
index 0000000000..36fec4025a
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/stats/StatisticsGatherer.java
@@ -0,0 +1,118 @@
+/*
+ * 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.stats;
+
+/**
+ * This interface is to be implemented by any broker business object that
+ * wishes to gather statistics about messages delivered through it.
+ *
+ * These statistics are exposed using a separate JMX Mbean interface, which
+ * calls these methods to retrieve the underlying {@link StatisticsCounter}s
+ * and return their attributes. This interface gives a standard way for
+ * parts of the broker to set up and configure statistics generation.
+ * <p>
+ * When creating these objects, there should be a parent/child relationship
+ * between them, such that the lowest level gatherer can record staticics if
+ * enabled, and pass on the notification to the parent object to allow higher
+ * level aggregation. When resetting statistics, this works in the opposite
+ * direction, with higher level gatherers also resetting all of their children.
+ */
+public interface StatisticsGatherer
+{
+ /**
+ * Initialise the statistics gathering for this object.
+ *
+ * This method is responsible for creating any {@link StatisticsCounter}
+ * objects and for determining whether statistics generation should be
+ * enabled, by checking broker and system configuration.
+ *
+ * @see StatisticsCounter#DISABLE_STATISTICS
+ */
+ void initialiseStatistics();
+
+ /**
+ * This method is responsible for registering the receipt of a message
+ * with the counters, and also for passing this notification to any parent
+ * {@link StatisticsGatherer}s. If statistics generation is not enabled,
+ * then this method should simple delegate to the parent gatherer.
+ *
+ * @param messageSize the size in bytes of the delivered message
+ * @param timestamp the time the message was delivered
+ */
+ void registerMessageReceived(long messageSize, long timestamp);
+
+ /**
+ * This method is responsible for registering the delivery of a message
+ * with the counters. Message delivery is recorded by the counter using
+ * the current system time, as opposed to the message timestamp.
+ *
+ * @param messageSize the size in bytes of the delivered message
+ * @see #registerMessageReceived(long, long)
+ */
+ void registerMessageDelivered(long messageSize);
+
+ /**
+ * Gives access to the {@link StatisticsCounter} that is used to count
+ * delivered message statistics.
+ *
+ * @return the {@link StatisticsCounter} that counts delivered messages
+ */
+ StatisticsCounter getMessageDeliveryStatistics();
+
+ /**
+ * Gives access to the {@link StatisticsCounter} that is used to count
+ * received message statistics.
+ *
+ * @return the {@link StatisticsCounter} that counts received messages
+ */
+ StatisticsCounter getMessageReceiptStatistics();
+
+ /**
+ * Gives access to the {@link StatisticsCounter} that is used to count
+ * delivered message size statistics.
+ *
+ * @return the {@link StatisticsCounter} that counts delivered bytes
+ */
+ StatisticsCounter getDataDeliveryStatistics();
+
+ /**
+ * Gives access to the {@link StatisticsCounter} that is used to count
+ * received message size statistics.
+ *
+ * @return the {@link StatisticsCounter} that counts received bytes
+ */
+ StatisticsCounter getDataReceiptStatistics();
+
+ /**
+ * 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/DerbyMessageStore.java b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
index 2e694b24ea..8b099b62ce 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/store/DerbyMessageStore.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.store;
import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.lang.ref.SoftReference;
@@ -479,9 +480,15 @@ public class DerbyMessageStore implements MessageStore
FieldTable arguments;
if(dataAsBytes.length > 0)
{
- org.apache.mina.common.ByteBuffer buffer = org.apache.mina.common.ByteBuffer.wrap(dataAsBytes);
- arguments = new FieldTable(buffer,buffer.limit());
+ try
+ {
+ arguments = new FieldTable(new DataInputStream(new ByteArrayInputStream(dataAsBytes)),dataAsBytes.length);
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("IO Exception should not be thrown",e);
+ }
}
else
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
index ce0362d73f..0fd7fdffe5 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactory.java
@@ -20,13 +20,21 @@
*/
package org.apache.qpid.server.subscription;
+import java.util.Map;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager_0_10;
import org.apache.qpid.server.subscription.Subscription;
+import org.apache.qpid.server.transport.ServerSession;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageFlowMode;
/**
* Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This factory
@@ -56,4 +64,23 @@ public interface SubscriptionFactory
RecordDeliveryMethod recordMethod
)
throws AMQException;
+
+
+ SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(AMQChannel channel,
+ AMQProtocolSession session,
+ AMQShortString consumerTag,
+ FieldTable filters,
+ boolean noLocal,
+ FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod) throws AMQException;
+
+ Subscription_0_10 createSubscription(final ServerSession session,
+ final String destination,
+ final MessageAcceptMode acceptMode,
+ final MessageAcquireMode acquireMode,
+ final MessageFlowMode flowMode,
+ final FlowCreditManager_0_10 creditManager,
+ final FilterManager filterManager,
+ final Map<String,Object> arguments);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
index 1bba2529c6..1622d63648 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionFactoryImpl.java
@@ -20,17 +20,28 @@
*/
package org.apache.qpid.server.subscription;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.flow.FlowCreditManager;
+import org.apache.qpid.server.flow.FlowCreditManager_0_10;
import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.transport.ServerSession;
+import org.apache.qpid.transport.MessageAcceptMode;
+import org.apache.qpid.transport.MessageAcquireMode;
+import org.apache.qpid.transport.MessageFlowMode;
public class SubscriptionFactoryImpl implements SubscriptionFactory
{
+ private static final AtomicLong SUB_ID_GENERATOR = new AtomicLong(0);
+
public Subscription createSubscription(int channelId, AMQProtocolSession protocolSession,
AMQShortString consumerTag, boolean acks, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager) throws AMQException
@@ -78,18 +89,47 @@ public class SubscriptionFactoryImpl implements SubscriptionFactory
if(isBrowser)
{
- return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
+ return new SubscriptionImpl.BrowserSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
}
else if(acks)
{
- return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
+ return new SubscriptionImpl.AckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
}
else
{
- return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod);
+ return new SubscriptionImpl.NoAckSubscription(channel, protocolSession, consumerTag, filters, noLocal, creditManager, clientMethod, recordMethod, getNextSubscriptionId());
}
}
+ public SubscriptionImpl.GetNoAckSubscription createBasicGetNoAckSubscription(final AMQChannel channel,
+ final AMQProtocolSession session,
+ final AMQShortString consumerTag,
+ final FieldTable filters,
+ final boolean noLocal,
+ final FlowCreditManager creditManager,
+ final ClientDeliveryMethod deliveryMethod,
+ final RecordDeliveryMethod recordMethod) throws AMQException
+ {
+ return new SubscriptionImpl.GetNoAckSubscription(channel, session, null, null, false, creditManager, deliveryMethod, recordMethod, getNextSubscriptionId());
+ }
+
+ public Subscription_0_10 createSubscription(final ServerSession session,
+ final String destination,
+ final MessageAcceptMode acceptMode,
+ final MessageAcquireMode acquireMode,
+ final MessageFlowMode flowMode,
+ final FlowCreditManager_0_10 creditManager,
+ final FilterManager filterManager,
+ final Map<String,Object> arguments)
+ {
+ return new Subscription_0_10(session, destination, acceptMode, acquireMode,
+ flowMode, creditManager, filterManager, arguments, getNextSubscriptionId());
+ }
public static final SubscriptionFactoryImpl INSTANCE = new SubscriptionFactoryImpl();
+
+ private static long getNextSubscriptionId()
+ {
+ return SUB_ID_GENERATOR.getAndIncrement();
+ }
}
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 d8f44c9f7f..d6a256e2e1 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
@@ -88,9 +88,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
private final Lock _stateChangeLock;
- private static final AtomicLong idGenerator = new AtomicLong(0);
- // Create a simple ID that increments for ever new Subscription
- private final long _subscriptionID = idGenerator.getAndIncrement();
+ private final long _subscriptionID;
private LogSubject _logSubject;
private LogActor _logActor;
private UUID _id;
@@ -104,10 +102,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
AMQShortString consumerTag, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
+ RecordDeliveryMethod recordMethod,
+ long subscriptionID)
throws AMQException
{
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
}
@@ -151,10 +150,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
AMQShortString consumerTag, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
+ RecordDeliveryMethod recordMethod,
+ long subscriptionID)
throws AMQException
{
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
}
@@ -211,16 +211,45 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
}
+ /**
+ * NoAck Subscription for use with BasicGet method.
+ */
+ public static final class GetNoAckSubscription extends SubscriptionImpl.NoAckSubscription
+ {
+ public GetNoAckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
+ AMQShortString consumerTag, FieldTable filters,
+ boolean noLocal, FlowCreditManager creditManager,
+ ClientDeliveryMethod deliveryMethod,
+ RecordDeliveryMethod recordMethod,
+ long subscriptionID)
+ throws AMQException
+ {
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
+ }
+
+ public boolean isTransient()
+ {
+ return true;
+ }
+
+ public boolean wouldSuspend(QueueEntry msg)
+ {
+ return !getCreditManager().useCreditForMessage(msg.getMessage());
+ }
+
+ }
+
static final class AckSubscription extends SubscriptionImpl
{
public AckSubscription(AMQChannel channel, AMQProtocolSession protocolSession,
AMQShortString consumerTag, FieldTable filters,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
+ RecordDeliveryMethod recordMethod,
+ long subscriptionID)
throws AMQException
{
- super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod);
+ super(channel, protocolSession, consumerTag, filters, noLocal, creditManager, deliveryMethod, recordMethod, subscriptionID);
}
@@ -296,10 +325,11 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
AMQShortString consumerTag, FieldTable arguments,
boolean noLocal, FlowCreditManager creditManager,
ClientDeliveryMethod deliveryMethod,
- RecordDeliveryMethod recordMethod)
+ RecordDeliveryMethod recordMethod,
+ long subscriptionID)
throws AMQException
{
-
+ _subscriptionID = subscriptionID;
_channel = channel;
_consumerTag = consumerTag;
@@ -445,7 +475,7 @@ public abstract class SubscriptionImpl implements Subscription, FlowCreditManage
//check that the message hasn't been rejected
- if (entry.isRejectedBy(this))
+ if (entry.isRejectedBy(getSubscriptionID()))
{
if (_logger.isDebugEnabled())
{
diff --git a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
index 9ea81660c6..3e6299cb8a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/subscription/SubscriptionList.java
@@ -20,121 +20,108 @@
*/
package org.apache.qpid.server.subscription;
-import org.apache.qpid.server.queue.AMQQueue;
import org.apache.qpid.server.subscription.Subscription;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
-import java.nio.ByteBuffer;
public class SubscriptionList
{
-
private final SubscriptionNode _head = new SubscriptionNode();
- private AtomicReference<SubscriptionNode> _tail = new AtomicReference<SubscriptionNode>(_head);
- private AtomicInteger _size = new AtomicInteger();
-
+ private final AtomicReference<SubscriptionNode> _tail = new AtomicReference<SubscriptionNode>(_head);
+ private final AtomicReference<SubscriptionNode> _subNodeMarker = new AtomicReference<SubscriptionNode>(_head);
+ private final AtomicInteger _size = new AtomicInteger();
- public final class SubscriptionNode
+ public static final class SubscriptionNode
{
private final AtomicBoolean _deleted = new AtomicBoolean();
private final AtomicReference<SubscriptionNode> _next = new AtomicReference<SubscriptionNode>();
private final Subscription _sub;
-
public SubscriptionNode()
{
-
+ //used for sentinel head and dummy node construction
_sub = null;
_deleted.set(true);
}
public SubscriptionNode(final Subscription sub)
{
+ //used for regular node construction
_sub = sub;
}
-
- public SubscriptionNode getNext()
+ /**
+ * Retrieves the first non-deleted node following the current node.
+ * Any deleted non-tail nodes encountered during the search are unlinked.
+ *
+ * @return the next non-deleted node, or null if none was found.
+ */
+ public SubscriptionNode findNext()
{
-
SubscriptionNode next = nextNode();
while(next != null && next.isDeleted())
{
-
final SubscriptionNode newNext = next.nextNode();
if(newNext != null)
{
+ //try to move our _next reference forward to the 'newNext'
+ //node to unlink the deleted node
_next.compareAndSet(next, newNext);
next = nextNode();
}
else
{
+ //'newNext' is null, meaning 'next' is the current tail. Can't unlink
+ //the tail node for thread safety reasons, just use the null.
next = null;
}
-
}
+
return next;
}
- private SubscriptionNode nextNode()
+ /**
+ * Gets the immediately next referenced node in the structure.
+ *
+ * @return the immediately next node in the structure, or null if at the tail.
+ */
+ protected SubscriptionNode nextNode()
{
return _next.get();
}
+ /**
+ * Used to initialise the 'next' reference. Will only succeed if the reference was not previously set.
+ *
+ * @param node the SubscriptionNode to set as 'next'
+ * @return whether the operation succeeded
+ */
+ private boolean setNext(final SubscriptionNode node)
+ {
+ return _next.compareAndSet(null, node);
+ }
+
public boolean isDeleted()
{
return _deleted.get();
}
-
public boolean delete()
{
- if(_deleted.compareAndSet(false,true))
- {
- _size.decrementAndGet();
- advanceHead();
- return true;
- }
- else
- {
- return false;
- }
+ return _deleted.compareAndSet(false,true);
}
-
public Subscription getSubscription()
{
return _sub;
}
}
-
- public SubscriptionList(AMQQueue queue)
- {
- }
-
- private void advanceHead()
- {
- SubscriptionNode head = _head.nextNode();
- while(head._next.get() != null && head.isDeleted())
- {
-
- final SubscriptionNode newhead = head.nextNode();
- if(newhead != null)
- {
- _head._next.compareAndSet(head, newhead);
- }
- head = _head.nextNode();
- }
- }
-
-
- public SubscriptionNode add(Subscription sub)
+ private void insert(final SubscriptionNode node, final boolean count)
{
- SubscriptionNode node = new SubscriptionNode(sub);
for (;;)
{
SubscriptionNode tail = _tail.get();
@@ -143,11 +130,14 @@ public class SubscriptionList
{
if (next == null)
{
- if (tail._next.compareAndSet(null, node))
+ if (tail.setNext(node))
{
_tail.compareAndSet(tail, node);
- _size.incrementAndGet();
- return node;
+ if(count)
+ {
+ _size.incrementAndGet();
+ }
+ return;
}
}
else
@@ -156,27 +146,101 @@ public class SubscriptionList
}
}
}
+ }
+ public void add(final Subscription sub)
+ {
+ SubscriptionNode node = new SubscriptionNode(sub);
+ insert(node, true);
}
- public boolean remove(Subscription sub)
+ public boolean remove(final Subscription sub)
{
- SubscriptionNode node = _head.getNext();
+ SubscriptionNode prevNode = _head;
+ SubscriptionNode node = _head.nextNode();
+
while(node != null)
{
- if(sub.equals(node._sub) && node.delete())
+ if(sub.equals(node.getSubscription()) && node.delete())
{
+ _size.decrementAndGet();
+
+ SubscriptionNode tail = _tail.get();
+ if(node == tail)
+ {
+ //we cant remove the last node from the structure for
+ //correctness reasons, however we have just 'deleted'
+ //the tail. Inserting an empty dummy node after it will
+ //let us scavenge the node containing the Subscription.
+ insert(new SubscriptionNode(), false);
+ }
+
+ //advance the next node reference in the 'prevNode' to scavange
+ //the newly 'deleted' node for the Subscription.
+ prevNode.findNext();
+
+ nodeMarkerCleanup(node);
+
return true;
}
- node = node.getNext();
+
+ prevNode = node;
+ node = node.findNext();
}
+
return false;
}
+ private void nodeMarkerCleanup(final SubscriptionNode node)
+ {
+ SubscriptionNode markedNode = _subNodeMarker.get();
+ if(node == markedNode)
+ {
+ //if the marked node is the one we are removing, then
+ //replace it with a dummy pointing at the next node.
+ //this is OK as the marked node is only used to index
+ //into the list and find the next node to use.
+ //Because we inserted a dummy if node was the
+ //tail, markedNode.nextNode() can never be null.
+ SubscriptionNode dummy = new SubscriptionNode();
+ dummy.setNext(markedNode.nextNode());
+
+ //if the CAS fails the marked node has changed, thus
+ //we don't care about the dummy and just forget it
+ _subNodeMarker.compareAndSet(markedNode, dummy);
+ }
+ else if(markedNode != null)
+ {
+ //if the marked node was already deleted then it could
+ //hold subsequently removed nodes after it in the list
+ //in memory. Scavenge it to ensure their actual removal.
+ if(markedNode != _head && markedNode.isDeleted())
+ {
+ markedNode.findNext();
+ }
+ }
+ }
- public static class SubscriptionNodeIterator
+ public boolean updateMarkedNode(final SubscriptionNode expected, final SubscriptionNode nextNode)
+ {
+ return _subNodeMarker.compareAndSet(expected, nextNode);
+ }
+
+ /**
+ * Get the current marked SubscriptionNode. This should only be used only to index into the list and find the next node
+ * after the mark, since if the previously marked node was subsequently deleted the item returned may be a dummy node
+ * with reference to the next node.
+ *
+ * @return the previously marked node (or a dummy if it was subsequently deleted)
+ */
+ public SubscriptionNode getMarkedNode()
{
+ return _subNodeMarker.get();
+ }
+
+ public static class SubscriptionNodeIterator
+ {
private SubscriptionNode _lastNode;
SubscriptionNodeIterator(SubscriptionNode startNode)
@@ -184,49 +248,25 @@ public class SubscriptionList
_lastNode = startNode;
}
-
- public boolean atTail()
- {
- return _lastNode.nextNode() == null;
- }
-
public SubscriptionNode getNode()
{
-
return _lastNode;
-
}
public boolean advance()
{
+ SubscriptionNode nextNode = _lastNode.findNext();
+ _lastNode = nextNode;
- if(!atTail())
- {
- SubscriptionNode nextNode = _lastNode.nextNode();
- while(nextNode.isDeleted() && nextNode.nextNode() != null)
- {
- nextNode = nextNode.nextNode();
- }
- _lastNode = nextNode;
- return true;
-
- }
- else
- {
- return false;
- }
-
+ return _lastNode != null;
}
-
}
-
public SubscriptionNodeIterator iterator()
{
return new SubscriptionNodeIterator(_head);
}
-
public SubscriptionNode getHead()
{
return _head;
@@ -236,9 +276,6 @@ public class SubscriptionList
{
return _size.get();
}
-
-
-
}
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 b36ac84cdd..c5d6bc203c 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
@@ -40,7 +40,6 @@ import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.SubscriptionMessages;
import org.apache.qpid.server.logging.LogActor;
import org.apache.qpid.server.logging.LogSubject;
-import org.apache.qpid.server.logging.actors.SubscriptionActor;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.message.MessageTransferMessage;
import org.apache.qpid.server.message.AMQMessage;
@@ -80,10 +79,7 @@ import java.nio.ByteBuffer;
public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCreditManagerListener, SubscriptionConfig, LogSubject
{
-
- private static final AtomicLong idGenerator = new AtomicLong(0);
- // Create a simple ID that increments for ever new Subscription
- private final long _subscriptionID = idGenerator.getAndIncrement();
+ private final long _subscriptionID;
private final QueueEntry.SubscriptionAcquiredState _owningState = new QueueEntry.SubscriptionAcquiredState(this);
private final QueueEntry.SubscriptionAssignedState _assignedState = new QueueEntry.SubscriptionAssignedState(this);
@@ -97,7 +93,6 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private FlowCreditManager_0_10 _creditManager;
-
private StateListener _stateListener = new StateListener()
{
@@ -114,16 +109,15 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
private final MessageAcquireMode _acquireMode;
private MessageFlowMode _flowMode;
private final ServerSession _session;
- private AtomicBoolean _stopped = new AtomicBoolean(true);
- private ConcurrentHashMap<Integer, QueueEntry> _sentMap = new ConcurrentHashMap<Integer, QueueEntry>();
+ private final AtomicBoolean _stopped = new AtomicBoolean(true);
private static final Struct[] EMPTY_STRUCT_ARRAY = new Struct[0];
private LogActor _logActor;
- private Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
+ private final Map<String, Object> _properties = new ConcurrentHashMap<String, Object>();
private UUID _id;
private String _traceExclude;
private String _trace;
- private long _createTime = System.currentTimeMillis();
+ private final long _createTime = System.currentTimeMillis();
private final AtomicLong _deliveredCount = new AtomicLong(0);
private final Map<String, Object> _arguments;
@@ -132,8 +126,9 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
MessageAcquireMode acquireMode,
MessageFlowMode flowMode,
FlowCreditManager_0_10 creditManager,
- FilterManager filters,Map<String, Object> arguments)
+ FilterManager filters,Map<String, Object> arguments, long subscriptionId)
{
+ _subscriptionID = subscriptionId;
_session = session;
_destination = destination;
_acceptMode = acceptMode;
@@ -199,7 +194,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public boolean isSuspended()
{
- return !isActive() || _deleted.get(); // TODO check for Session suspension
+ return !isActive() || _deleted.get() || _session.isClosing(); // TODO check for Session suspension
}
public boolean hasInterest(QueueEntry entry)
@@ -208,7 +203,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
//check that the message hasn't been rejected
- if (entry.isRejectedBy(this))
+ if (entry.isRejectedBy(getSubscriptionID()))
{
return false;
@@ -442,7 +437,7 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
Struct[] headers = new Struct[] { deliveryProps, messageProps };
BasicContentHeaderProperties properties =
- (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().properties;
+ (BasicContentHeaderProperties) message_0_8.getContentHeaderBody().getProperties();
final AMQShortString exchange = message_0_8.getMessagePublishInfo().getExchange();
if(exchange != null)
{
@@ -732,13 +727,22 @@ public class Subscription_0_10 implements Subscription, FlowCreditManager.FlowCr
public void stop()
{
- if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ try
{
- _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
+ getSendLock();
+
+ if(_state.compareAndSet(State.ACTIVE, State.SUSPENDED))
+ {
+ _stateListener.stateChange(this, State.ACTIVE, State.SUSPENDED);
+ }
+ _stopped.set(true);
+ FlowCreditManager_0_10 creditManager = getCreditManager();
+ creditManager.clearCredit();
+ }
+ finally
+ {
+ releaseSendLock();
}
- _stopped.set(true);
- FlowCreditManager_0_10 creditManager = getCreditManager();
- creditManager.clearCredit();
}
public void addCredit(MessageCreditUnit unit, long value)
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 3ca22b60c8..abbc5a3805 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,21 +20,21 @@
*/
package org.apache.qpid.server.transport;
-import org.apache.qpid.transport.NetworkDriver;
+import org.apache.qpid.transport.network.NetworkTransport;
public class QpidAcceptor
{
- NetworkDriver _driver;
+ NetworkTransport _transport;
String _protocol;
- public QpidAcceptor(NetworkDriver driver, String protocol)
+ public QpidAcceptor(NetworkTransport transport, String protocol)
{
- _driver = driver;
+ _transport = transport;
_protocol = protocol;
}
- public NetworkDriver getNetworkDriver()
+ public NetworkTransport getNetworkTransport()
{
- return _driver;
+ return _transport;
}
public String 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 d2addfde0c..d83013afba 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,11 +20,19 @@
*/
package org.apache.qpid.server.transport;
-import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.*;
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CONNECTION_FORMAT;
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.SOCKET_FORMAT;
+import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.USER_FORMAT;
+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 javax.security.auth.Subject;
+
import org.apache.qpid.AMQException;
import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.server.configuration.ConnectionConfig;
@@ -35,23 +43,39 @@ import org.apache.qpid.server.logging.actors.GenericActor;
import org.apache.qpid.server.logging.messages.ConnectionMessages;
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;
+import org.apache.qpid.transport.ConnectionCloseCode;
import org.apache.qpid.transport.ExecutionErrorCode;
import org.apache.qpid.transport.ExecutionException;
import org.apache.qpid.transport.Method;
import org.apache.qpid.transport.ProtocolEvent;
+import org.apache.qpid.transport.Session;
-public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject
+public class ServerConnection extends Connection implements AMQConnectionModel, LogSubject, AuthorizationHolder
{
private ConnectionConfig _config;
private Runnable _onOpenTask;
private AtomicBoolean _logClosed = new AtomicBoolean(false);
private LogActor _actor = GenericActor.getInstance(this);
- public ServerConnection()
+ private Subject _authorizedSubject = null;
+ private Principal _authorizedPrincipal = null;
+ private boolean _statisticsEnabled = false;
+ private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
+ private final long _connectionId;
+
+ public ServerConnection(final long connectionId)
{
+ _connectionId = connectionId;
+ }
+ public UUID getId()
+ {
+ return _config.getId();
}
@Override
@@ -72,8 +96,18 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
_onOpenTask.run();
}
_actor.message(ConnectionMessages.OPEN(getClientId(), "0-10", true, true));
+
+ getVirtualHost().getConnectionRegistry().registerConnection(this);
}
-
+
+ if (state == State.CLOSE_RCVD || state == State.CLOSED || state == State.CLOSING)
+ {
+ if(_virtualHost != null)
+ {
+ _virtualHost.getConnectionRegistry().deregisterConnection(this);
+ }
+ }
+
if (state == State.CLOSED)
{
logClosed();
@@ -110,6 +144,8 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
public void setVirtualHost(VirtualHost virtualHost)
{
_virtualHost = virtualHost;
+
+ initialiseStatistics();
}
public void setConnectionConfig(final ConnectionConfig config)
@@ -145,6 +181,11 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
((ServerSession)session).close();
}
+
+ public LogSubject getLogSubject()
+ {
+ return (LogSubject) this;
+ }
@Override
public void received(ProtocolEvent event)
@@ -179,9 +220,9 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
public String toLogString()
{
boolean hasVirtualHost = (null != this.getVirtualHost());
- boolean hasPrincipal = (null != getAuthorizationID());
+ boolean hasClientId = (null != getClientId());
- if (hasPrincipal && hasVirtualHost)
+ if (hasClientId && hasVirtualHost)
{
return "[" +
MessageFormat.format(CONNECTION_FORMAT,
@@ -191,7 +232,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
getVirtualHost().getName())
+ "] ";
}
- else if (hasPrincipal)
+ else if (hasClientId)
{
return "[" +
MessageFormat.format(USER_FORMAT,
@@ -215,4 +256,147 @@ public class ServerConnection extends Connection implements AMQConnectionModel,
{
return _actor;
}
+
+ public void close(AMQConstant cause, String message) throws AMQException
+ {
+ ConnectionCloseCode replyCode = ConnectionCloseCode.NORMAL;
+ try
+ {
+ replyCode = ConnectionCloseCode.get(cause.getCode());
+ }
+ catch (IllegalArgumentException iae)
+ {
+ // Ignore
+ }
+ close(replyCode, message);
+ }
+
+ public List<AMQSessionModel> getSessionModels()
+ {
+ List<AMQSessionModel> sessions = new ArrayList<AMQSessionModel>();
+ for (Session ssn : getChannels())
+ {
+ sessions.add((AMQSessionModel) ssn);
+ }
+ return sessions;
+ }
+
+ public void registerMessageDelivered(long messageSize)
+ {
+ if (isStatisticsEnabled())
+ {
+ _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);
+ }
+ _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();
+ _dataDelivered.reset();
+ _messagesReceived.reset();
+ _dataReceived.reset();
+ }
+
+ 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
+ */
+ public Subject getAuthorizedSubject()
+ {
+ return _authorizedSubject;
+ }
+
+ /**
+ * Sets the authorized subject. It also extracts the UsernamePrincipal from the subject
+ * and caches it for optimisation purposes.
+ *
+ * @param authorizedSubject
+ */
+ public void setAuthorizedSubject(final Subject authorizedSubject)
+ {
+ if (authorizedSubject == null)
+ {
+ _authorizedSubject = null;
+ _authorizedPrincipal = null;
+ }
+ else
+ {
+ _authorizedSubject = authorizedSubject;
+ _authorizedPrincipal = UsernamePrincipal.getUsernamePrincipalFromSubject(_authorizedSubject);
+ }
+ }
+
+ public Principal getAuthorizedPrincipal()
+ {
+ return _authorizedPrincipal;
+ }
+
+ public long getConnectionId()
+ {
+ return _connectionId;
+ }
+
+ @Override
+ public boolean isSessionNameUnique(String name)
+ {
+ return !super.hasSessionWithName(name);
+ }
+
+ @Override
+ public String getUserName()
+ {
+ return _authorizedPrincipal.getName();
+ }
}
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 2b9e92f685..2de8a0425e 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,26 +20,47 @@
*/
package org.apache.qpid.server.transport;
-import org.apache.qpid.transport.*;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.GenericActor;
-import org.apache.qpid.common.ClientProperties;
+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.protocol.ProtocolEngine;
-import org.apache.qpid.server.security.SecurityManager;
+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.subscription.Subscription_0_10;
import org.apache.qpid.server.virtualhost.VirtualHost;
-
-import javax.security.sasl.SaslServer;
-import javax.security.sasl.SaslException;
-import java.util.*;
+import org.apache.qpid.transport.Binary;
+import org.apache.qpid.transport.Connection;
+import org.apache.qpid.transport.ConnectionClose;
+import org.apache.qpid.transport.ConnectionCloseCode;
+import org.apache.qpid.transport.ConnectionOpen;
+import org.apache.qpid.transport.ConnectionOpenOk;
+import org.apache.qpid.transport.ConnectionTuneOk;
+import org.apache.qpid.transport.ServerDelegate;
+import org.apache.qpid.transport.Session;
+import org.apache.qpid.transport.SessionAttach;
+import org.apache.qpid.transport.SessionDelegate;
+import org.apache.qpid.transport.SessionDetach;
+import org.apache.qpid.transport.SessionDetachCode;
+import org.apache.qpid.transport.SessionDetached;
public class ServerConnectionDelegate extends ServerDelegate
{
private String _localFQDN;
private final IApplicationRegistry _appRegistry;
-
public ServerConnectionDelegate(IApplicationRegistry appRegistry, String localFQDN)
{
this(new HashMap<String,Object>(Collections.singletonMap("qpid.federation_tag",appRegistry.getBroker().getFederationTag())), Collections.singletonList((Object)"en_US"), appRegistry, localFQDN);
@@ -68,24 +89,42 @@ public class ServerConnectionDelegate extends ServerDelegate
return list;
}
- @Override
public ServerSession getSession(Connection conn, SessionAttach atc)
{
- SessionDelegate serverSessionDelegate = new ServerSessionDelegate(_appRegistry);
+ SessionDelegate serverSessionDelegate = new ServerSessionDelegate();
ServerSession ssn = new ServerSession(conn, serverSessionDelegate, new Binary(atc.getName()), 0);
return ssn;
}
- @Override
protected SaslServer createSaslServer(String mechanism) throws SaslException
{
return _appRegistry.getAuthenticationManager().createSaslServer(mechanism, _localFQDN);
}
- @Override
+ 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;
+
+
+ if (AuthenticationStatus.SUCCESS.equals(authResult.getStatus()))
+ {
+ tuneAuthorizedConnection(sconn);
+ sconn.setAuthorizedSubject(authResult.getSubject());
+ }
+ else if (AuthenticationStatus.CONTINUE.equals(authResult.getStatus()))
+ {
+ connectionAuthContinue(sconn, authResult.getChallenge());
+ }
+ else
+ {
+ connectionAuthFailed(sconn, authResult.getCause());
+ }
+ }
+
public void connectionClose(Connection conn, ConnectionClose close)
{
try
@@ -99,10 +138,9 @@ public class ServerConnectionDelegate extends ServerDelegate
}
- @Override
public void connectionOpen(Connection conn, ConnectionOpen open)
{
- ServerConnection sconn = (ServerConnection) conn;
+ final ServerConnection sconn = (ServerConnection) conn;
VirtualHost vhost;
String vhostName;
@@ -116,7 +154,7 @@ public class ServerConnectionDelegate extends ServerDelegate
}
vhost = _appRegistry.getVirtualHostRegistry().getVirtualHost(vhostName);
- SecurityManager.setThreadPrincipal(conn.getAuthorizationID());
+ SecurityManager.setThreadSubject(sconn.getAuthorizedSubject());
if(vhost != null)
{
@@ -138,6 +176,27 @@ public class ServerConnectionDelegate extends ServerDelegate
sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown virtualhost '"+vhostName+"'"));
sconn.setState(Connection.State.CLOSING);
}
+
+ }
+
+ @Override
+ public void connectionTuneOk(final Connection conn, final ConnectionTuneOk ok)
+ {
+ ServerConnection sconn = (ServerConnection) conn;
+ int okChannelMax = ok.getChannelMax();
+
+ if (okChannelMax > getChannelMax())
+ {
+ _logger.error("Connection '" + sconn.getConnectionId() + "' being severed, " +
+ "client connectionTuneOk returned a channelMax (" + okChannelMax +
+ ") above the servers offered limit (" + getChannelMax() +")");
+
+ //Due to the error we must forcefully close the connection without negotiation
+ sconn.getSender().close();
+ return;
+ }
+
+ setConnectionTuneOkChannelMax(sconn, okChannelMax);
}
@Override
@@ -152,4 +211,59 @@ public class ServerConnectionDelegate extends ServerDelegate
{
return ApplicationRegistry.getInstance().getConfiguration().getMaxChannelCount();
}
+
+ @Override public void sessionDetach(Connection conn, SessionDetach dtc)
+ {
+ // To ensure a clean detach, we unregister any remaining subscriptions. Unregister ensures
+ // that any in-progress delivery (SubFlushRunner/QueueRunner) is completed before the unregister
+ // completes.
+ unregisterAllSubscriptions(conn, dtc);
+ super.sessionDetach(conn, dtc);
+ }
+
+ private void unregisterAllSubscriptions(Connection conn, SessionDetach dtc)
+ {
+ final ServerSession ssn = (ServerSession) conn.getSession(dtc.getChannel());
+ final Collection<Subscription_0_10> subs = ssn.getSubscriptions();
+ for (Subscription_0_10 subscription_0_10 : subs)
+ {
+ ssn.unregister(subscription_0_10);
+ }
+ }
+
+ @Override
+ public void sessionAttach(final Connection conn, final SessionAttach atc)
+ {
+ final String clientId = new String(atc.getName());
+ final Session ssn = getSession(conn, atc);
+
+ if(isSessionNameUnique(clientId,conn))
+ {
+ conn.registerSession(ssn);
+ super.sessionAttach(conn, atc);
+ }
+ else
+ {
+ ssn.invoke(new SessionDetached(atc.getName(), SessionDetachCode.SESSION_BUSY));
+ ssn.closed();
+ }
+ }
+
+ private boolean isSessionNameUnique(final String name, final Connection conn)
+ {
+ final ServerConnection sconn = (ServerConnection) conn;
+ final String userId = sconn.getUserName();
+
+ final Iterator<AMQConnectionModel> connections =
+ ((ServerConnection)conn).getVirtualHost().getConnectionRegistry().getConnections().iterator();
+ while(connections.hasNext())
+ {
+ final AMQConnectionModel amqConnectionModel = (AMQConnectionModel) connections.next();
+ if (userId.equals(amqConnectionModel.getUserName()) && !amqConnectionModel.isSessionNameUnique(name))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
}
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 540ad3fffd..67ddd6ca77 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
@@ -23,9 +23,25 @@ package org.apache.qpid.server.transport;
import static org.apache.qpid.server.logging.subjects.LogSubjectFormat.CHANNEL_FORMAT;
import static org.apache.qpid.util.Serial.gt;
-import com.sun.security.auth.UserPrincipal;
+import java.lang.ref.WeakReference;
+import java.security.Principal;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+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.protocol.ProtocolEngine;
import org.apache.qpid.server.configuration.ConfigStore;
import org.apache.qpid.server.configuration.ConfiguredObject;
@@ -38,18 +54,18 @@ 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.message.ServerMessage;
+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.BaseQueue;
import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.security.PrincipalHolder;
+import org.apache.qpid.server.security.AuthorizationHolder;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.txn.AutoCommitTransaction;
import org.apache.qpid.server.txn.LocalTransaction;
import org.apache.qpid.server.txn.ServerTransaction;
import org.apache.qpid.server.virtualhost.VirtualHost;
-import org.apache.qpid.server.protocol.AMQSessionModel;
-import org.apache.qpid.server.protocol.AMQConnectionModel;
import org.apache.qpid.transport.Binary;
import org.apache.qpid.transport.Connection;
import org.apache.qpid.transport.MessageTransfer;
@@ -58,24 +74,13 @@ import org.apache.qpid.transport.Range;
import org.apache.qpid.transport.RangeSet;
import org.apache.qpid.transport.Session;
import org.apache.qpid.transport.SessionDelegate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
-import java.lang.ref.WeakReference;
-import java.security.Principal;
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentSkipListMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.AtomicLong;
-
-public class ServerSession extends Session implements PrincipalHolder, SessionConfig, AMQSessionModel, LogSubject
+public class ServerSession extends Session implements AuthorizationHolder, SessionConfig, AMQSessionModel, LogSubject
{
+ private static final Logger _logger = LoggerFactory.getLogger(ServerSession.class);
+
private static final String NULL_DESTINTATION = UUID.randomUUID().toString();
private final UUID _id;
@@ -111,8 +116,7 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
private final AtomicLong _txnCommits = new AtomicLong(0);
private final AtomicLong _txnRejects = new AtomicLong(0);
private final AtomicLong _txnCount = new AtomicLong(0);
-
- private Principal _principal;
+ private final AtomicLong _txnUpdateTime = new AtomicLong(0);
private Map<String, Subscription_0_10> _subscriptions = new ConcurrentHashMap<String, Subscription_0_10>();
@@ -125,27 +129,27 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
this(connection, delegate, name, expiry, ((ServerConnection)connection).getConfig());
}
- protected void setState(State state)
- {
- super.setState(state);
-
- if (state == State.OPEN)
- {
- _actor.message(ChannelMessages.CREATE());
- }
- }
-
public ServerSession(Connection connection, SessionDelegate delegate, Binary name, long expiry, ConnectionConfig connConfig)
{
super(connection, delegate, name, expiry);
_connectionConfig = connConfig;
_transaction = new AutoCommitTransaction(this.getMessageStore());
- _principal = new UserPrincipal(connection.getAuthorizationID());
- _reference = new WeakReference(this);
+
+ _reference = new WeakReference<Session>(this);
_id = getConfigStore().createId();
getConfigStore().addConfiguredObject(this);
}
+ protected void setState(State state)
+ {
+ super.setState(state);
+
+ if (state == State.OPEN)
+ {
+ _actor.message(ChannelMessages.CREATE());
+ }
+ }
+
private ConfigStore getConfigStore()
{
return getConnectionConfig().getConfigStore();
@@ -160,8 +164,8 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
public void enqueue(final ServerMessage message, final ArrayList<? extends BaseQueue> queues)
{
-
- _transaction.enqueue(queues,message, new ServerTransaction.Action()
+ getConnectionModel().registerMessageReceived(message.getSize(), message.getArrivalTime());
+ _transaction.enqueue(queues,message, new ServerTransaction.Action()
{
BaseQueue[] _queues = queues.toArray(new BaseQueue[queues.size()]);
@@ -189,12 +193,14 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
});
incrementOutstandingTxnsIfNecessary();
+ updateTransactionalActivity();
}
public void sendMessage(MessageTransfer xfr,
Runnable postIdSettingAction)
{
+ getConnectionModel().registerMessageDelivered(xfr.getBodySize());
invoke(xfr, postIdSettingAction);
}
@@ -377,6 +383,7 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
entry.release();
}
});
+ updateTransactionalActivity();
}
public Collection<Subscription_0_10> getSubscriptions()
@@ -410,7 +417,7 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
catch (AMQException e)
{
// TODO
- e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
+ _logger.error("Failed to unregister subscription", e);
}
finally
{
@@ -425,6 +432,11 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
// theory
return !(_transaction instanceof AutoCommitTransaction);
}
+
+ public boolean inTransaction()
+ {
+ return isTransactional() && _txnUpdateTime.get() > 0 && _transaction.getTransactionStartTime() > 0;
+ }
public void selectTx()
{
@@ -471,6 +483,17 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
}
}
+ /**
+ * Update last transaction activity timestamp
+ */
+ public void updateTransactionalActivity()
+ {
+ if (isTransactional())
+ {
+ _txnUpdateTime.set(System.currentTimeMillis());
+ }
+ }
+
public Long getTxnStarts()
{
return _txnStarts.get();
@@ -491,9 +514,14 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
return _txnCount.get();
}
- public Principal getPrincipal()
+ public Principal getAuthorizedPrincipal()
{
- return _principal;
+ return ((ServerConnection) getConnection()).getAuthorizedPrincipal();
+ }
+
+ public Subject getAuthorizedSubject()
+ {
+ return ((ServerConnection) getConnection()).getAuthorizedSubject();
}
public void addSessionCloseTask(Task task)
@@ -606,18 +634,61 @@ public class ServerSession extends Session implements PrincipalHolder, SessionCo
return (LogSubject) this;
}
- @Override
+ public void checkTransactionStatus(long openWarn, long openClose, long idleWarn, long idleClose) throws AMQException
+ {
+ if (inTransaction())
+ {
+ long currentTime = System.currentTimeMillis();
+ 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)
+ {
+ 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");
+ }
+ }
+ }
+
public String toLogString()
{
return "[" +
MessageFormat.format(CHANNEL_FORMAT,
- getConnection().getConnectionId(),
+ ((ServerConnection) getConnection()).getConnectionId(),
getClientID(),
((ProtocolEngine) _connectionConfig).getRemoteAddress().toString(),
getVirtualHost().getName(),
getChannel())
+ "] ";
-
}
+ @Override
+ public void close()
+ {
+ // unregister subscriptions in order to prevent sending of new messages
+ // to subscriptions with closing session
+ final Collection<Subscription_0_10> subscriptions = getSubscriptions();
+ for (Subscription_0_10 subscription_0_10 : subscriptions)
+ {
+ unregister(subscription_0_10);
+ }
+
+ super.close();
+ }
}
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 42a3975e24..17bd06538f 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
@@ -25,31 +25,34 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
+import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUnknownExchangeType;
-import org.apache.qpid.common.AMQPFilterTypes;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.server.exchange.*;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.exchange.ExchangeFactory;
+import org.apache.qpid.server.exchange.ExchangeInUseException;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.exchange.ExchangeType;
+import org.apache.qpid.server.exchange.HeadersExchange;
import org.apache.qpid.server.filter.FilterManager;
import org.apache.qpid.server.filter.FilterManagerFactory;
import org.apache.qpid.server.flow.FlowCreditManager_0_10;
import org.apache.qpid.server.flow.WindowCreditManager;
-import org.apache.qpid.server.logging.actors.CurrentActor;
-import org.apache.qpid.server.logging.actors.GenericActor;
+import org.apache.qpid.server.logging.messages.ExchangeMessages;
import org.apache.qpid.server.message.MessageMetaData_0_10;
import org.apache.qpid.server.message.MessageTransferMessage;
-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.queue.BaseQueue;
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.security.SecurityManager;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.store.StoredMessage;
+import org.apache.qpid.server.subscription.SubscriptionFactoryImpl;
import org.apache.qpid.server.subscription.Subscription_0_10;
import org.apache.qpid.server.virtualhost.VirtualHost;
import org.apache.qpid.transport.Acquired;
@@ -95,26 +98,34 @@ import org.apache.qpid.transport.TxSelect;
public class ServerSessionDelegate extends SessionDelegate
{
- private final IApplicationRegistry _appRegistry;
+ private static final Logger LOGGER = Logger.getLogger(ServerSessionDelegate.class);
- public ServerSessionDelegate(IApplicationRegistry appRegistry)
+ public ServerSessionDelegate()
{
- _appRegistry = appRegistry;
+
}
@Override
public void command(Session session, Method method)
{
- SecurityManager.setThreadPrincipal(session.getConnection().getAuthorizationID());
-
- if(!session.isClosing())
+ try
{
- super.command(session, method);
- if (method.isSync())
+ setThreadSubject(session);
+
+ if(!session.isClosing())
{
- session.flushProcessed();
+ super.command(session, method);
+ if (method.isSync())
+ {
+ session.flushProcessed();
+ }
}
}
+ catch(RuntimeException e)
+ {
+ LOGGER.error("Exception processing command", e);
+ exception(session, method, ExecutionErrorCode.INTERNAL_ERROR, "Exception processing command: " + e);
+ }
}
@Override
@@ -123,8 +134,6 @@ public class ServerSessionDelegate extends SessionDelegate
((ServerSession)session).accept(method.getTransfers());
}
-
-
@Override
public void messageReject(Session session, MessageReject method)
{
@@ -159,7 +168,6 @@ public class ServerSessionDelegate extends SessionDelegate
@Override
public void messageSubscribe(Session session, MessageSubscribe method)
{
-
//TODO - work around broken Python tests
if(!method.hasAcceptMode())
{
@@ -203,32 +211,33 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session,method,ExecutionErrorCode.NOT_FOUND, "Queue: " + queueName + " not found");
}
- else if(queue.getPrincipalHolder() != null && queue.getPrincipalHolder() != session)
+ else if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session)
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
else
{
-
if(queue.isExclusive())
{
- if(queue.getPrincipalHolder() == null)
+ ServerSession s = (ServerSession) session;
+ queue.setExclusiveOwningSession(s);
+ if(queue.getAuthorizationHolder() == null)
{
- queue.setPrincipalHolder((ServerSession)session);
+ queue.setAuthorizationHolder(s);
+ queue.setExclusiveOwningSession(s);
((ServerSession) session).addSessionCloseTask(new ServerSession.Task()
{
-
public void doTask(ServerSession session)
{
- if(queue.getPrincipalHolder() == session)
+ if(queue.getAuthorizationHolder() == session)
{
- queue.setPrincipalHolder(null);
+ queue.setAuthorizationHolder(null);
+ queue.setExclusiveOwningSession(null);
}
}
});
}
-
}
FlowCreditManager_0_10 creditManager = new WindowCreditManager(0L,0L);
@@ -244,7 +253,7 @@ public class ServerSessionDelegate extends SessionDelegate
return;
}
- Subscription_0_10 sub = new Subscription_0_10((ServerSession)session,
+ Subscription_0_10 sub = SubscriptionFactoryImpl.INSTANCE.createSubscription((ServerSession)session,
destination,
method.getAcceptMode(),
method.getAcquireMode(),
@@ -275,25 +284,10 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
-
@Override
public void messageTransfer(Session ssn, MessageTransfer xfr)
{
- ExchangeRegistry exchangeRegistry = getExchangeRegistry(ssn);
- Exchange exchange;
- if(xfr.hasDestination())
- {
- exchange = exchangeRegistry.getExchange(xfr.getDestination());
- if(exchange == null)
- {
- exchange = exchangeRegistry.getDefaultExchange();
- }
- }
- else
- {
- exchange = exchangeRegistry.getDefaultExchange();
- }
-
+ final Exchange exchange = getExchangeForMessage(ssn, xfr);
DeliveryProperties delvProps = null;
if(xfr.getHeader() != null && (delvProps = xfr.getHeader().get(DeliveryProperties.class)) != null && delvProps.hasTtl() && !delvProps.hasExpiration())
@@ -301,7 +295,7 @@ public class ServerSessionDelegate extends SessionDelegate
delvProps.setExpiration(System.currentTimeMillis() + delvProps.getTtl());
}
- MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
+ final MessageMetaData_0_10 messageMetaData = new MessageMetaData_0_10(xfr);
if (!getVirtualHost(ssn).getSecurityManager().authorisePublish(messageMetaData.isImmediate(), messageMetaData.getRoutingKey(), exchange.getName()))
{
@@ -311,65 +305,63 @@ public class ServerSessionDelegate extends SessionDelegate
return;
}
-
- final MessageStore store = getVirtualHost(ssn).getMessageStore();
- StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData);
- ByteBuffer body = xfr.getBody();
- if(body != null)
+
+ final Exchange exchangeInUse;
+ ArrayList<? extends BaseQueue> queues = exchange.route(messageMetaData);
+ if(queues.isEmpty() && exchange.getAlternateExchange() != null)
{
- storeMessage.addContent(0, body);
+ final Exchange alternateExchange = exchange.getAlternateExchange();
+ queues = alternateExchange.route(messageMetaData);
+ if (!queues.isEmpty())
+ {
+ exchangeInUse = alternateExchange;
+ }
+ else
+ {
+ exchangeInUse = exchange;
+ }
+ }
+ else
+ {
+ exchangeInUse = exchange;
}
- storeMessage.flushToStore();
- MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference());
-
- ArrayList<? extends BaseQueue> queues = exchange.route(message);
-
-
- if(queues != null && queues.size() != 0)
+ if(!queues.isEmpty())
{
+ final MessageStore store = getVirtualHost(ssn).getMessageStore();
+ final StoredMessage<MessageMetaData_0_10> storeMessage = createAndFlushStoreMessage(xfr, messageMetaData, store);
+ MessageTransferMessage message = new MessageTransferMessage(storeMessage, ((ServerSession)ssn).getReference());
((ServerSession) ssn).enqueue(message, queues);
}
else
{
- if(delvProps == null || !delvProps.hasDiscardUnroutable() || !delvProps.getDiscardUnroutable())
+ if((delvProps == null || !delvProps.getDiscardUnroutable()) && xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT)
{
- if(xfr.getAcceptMode() == MessageAcceptMode.EXPLICIT)
- {
- RangeSet rejects = new RangeSet();
- rejects.add(xfr.getId());
- MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
- ssn.invoke(reject);
- }
- else
- {
- Exchange alternate = exchange.getAlternateExchange();
- if(alternate != null)
- {
- queues = alternate.route(message);
- if(queues != null && queues.size() != 0)
- {
- ((ServerSession) ssn).enqueue(message, queues);
- }
- else
- {
- //TODO - log the message discard
- }
- }
- else
- {
- //TODO - log the message discard
- }
-
-
- }
+ RangeSet rejects = new RangeSet();
+ rejects.add(xfr.getId());
+ MessageReject reject = new MessageReject(rejects, MessageRejectCode.UNROUTABLE, "Unroutable");
+ ssn.invoke(reject);
+ }
+ else
+ {
+ ((ServerSession) ssn).getLogActor().message(ExchangeMessages.DISCARDMSG(exchangeInUse.getName(), messageMetaData.getRoutingKey()));
}
-
-
}
ssn.processed(xfr);
+ }
+ private StoredMessage<MessageMetaData_0_10> createAndFlushStoreMessage(final MessageTransfer xfr,
+ final MessageMetaData_0_10 messageMetaData, final MessageStore store)
+ {
+ final StoredMessage<MessageMetaData_0_10> storeMessage = store.addMessage(messageMetaData);
+ ByteBuffer body = xfr.getBody();
+ if(body != null)
+ {
+ storeMessage.addContent(0, body);
+ }
+ storeMessage.flushToStore();
+ return storeMessage;
}
@Override
@@ -389,7 +381,7 @@ public class ServerSessionDelegate extends SessionDelegate
((ServerSession)session).unregister(sub);
if(!queue.isDeleted() && queue.isExclusive() && queue.getConsumerCount() == 0)
{
- queue.setPrincipalHolder(null);
+ queue.setAuthorizationHolder(null);
}
}
}
@@ -448,6 +440,19 @@ public class ServerSessionDelegate extends SessionDelegate
VirtualHost virtualHost = getVirtualHost(session);
Exchange exchange = getExchange(session, exchangeName);
+ //we must check for any unsupported arguments present and throw not-implemented
+ if(method.hasArguments())
+ {
+ Map<String,Object> args = method.getArguments();
+
+ //QPID-3392: currently we don't support any!
+ if(!args.isEmpty())
+ {
+ exception(session, method, ExecutionErrorCode.NOT_IMPLEMENTED, "Unsupported exchange argument(s) found " + args.keySet().toString());
+ return;
+ }
+ }
+
if(method.getPassive())
{
if(exchange == null)
@@ -457,7 +462,6 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
- // TODO - check exchange has same properties
if(!exchange.getTypeShortString().toString().equals(method.getType()))
{
exception(session, method, ExecutionErrorCode.NOT_ALLOWED, "Cannot redeclare with a different exchange type");
@@ -562,6 +566,25 @@ public class ServerSessionDelegate extends SessionDelegate
}
+ private Exchange getExchangeForMessage(Session ssn, MessageTransfer xfr)
+ {
+ final ExchangeRegistry exchangeRegistry = getExchangeRegistry(ssn);
+ Exchange exchange;
+ if(xfr.hasDestination())
+ {
+ exchange = exchangeRegistry.getExchange(xfr.getDestination());
+ if(exchange == null)
+ {
+ exchange = exchangeRegistry.getDefaultExchange();
+ }
+ }
+ else
+ {
+ exchange = exchangeRegistry.getDefaultExchange();
+ }
+ return exchange;
+ }
+
private VirtualHost getVirtualHost(Session session)
{
ServerConnection conn = getServerConnection(session);
@@ -583,6 +606,12 @@ public class ServerSessionDelegate extends SessionDelegate
try
{
+ if (nameNullOrEmpty(method.getExchange()))
+ {
+ exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Delete not allowed for default exchange");
+ return;
+ }
+
Exchange exchange = getExchange(session, method.getExchange());
if(exchange == null)
@@ -618,6 +647,16 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
+ private boolean nameNullOrEmpty(String name)
+ {
+ if(name == null || name.length() == 0)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
private boolean isStandardExchange(Exchange exchange, Collection<ExchangeType<? extends Exchange>> registeredTypes)
{
for(ExchangeType type : registeredTypes)
@@ -664,9 +703,9 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set");
}
- else if (!method.hasExchange())
+ else if (nameNullOrEmpty(method.getExchange()))
{
- exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "exchange not set");
+ exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Bind not allowed for default exchange");
}
/*
else if (!method.hasBindingKey())
@@ -735,9 +774,9 @@ public class ServerSessionDelegate extends SessionDelegate
{
exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "queue not set");
}
- else if (!method.hasExchange())
+ else if (nameNullOrEmpty(method.getExchange()))
{
- exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "exchange not set");
+ exception(session, method, ExecutionErrorCode.INVALID_ARGUMENT, "Unbind not allowed for default exchange");
}
else if (!method.hasBindingKey())
{
@@ -767,9 +806,6 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
}
-
-
- super.exchangeUnbind(session, method);
}
@Override
@@ -969,10 +1005,10 @@ public class ServerSessionDelegate extends SessionDelegate
}
- if(method.hasAutoDelete()
- && method.getAutoDelete()
- && method.hasExclusive()
- && method.getExclusive())
+ if (method.hasAutoDelete()
+ && method.getAutoDelete()
+ && method.hasExclusive()
+ && method.getExclusive())
{
final AMQQueue q = queue;
final ServerSession.Task deleteQueueTask = new ServerSession.Task()
@@ -999,23 +1035,23 @@ public class ServerSessionDelegate extends SessionDelegate
}
});
}
- else if(method.getExclusive())
+ if (method.hasExclusive()
+ && method.getExclusive())
{
final AMQQueue q = queue;
final ServerSession.Task removeExclusive = new ServerSession.Task()
{
-
public void doTask(ServerSession session)
{
- q.setPrincipalHolder(null);
+ q.setAuthorizationHolder(null);
q.setExclusiveOwningSession(null);
}
};
final ServerSession s = (ServerSession) session;
+ q.setExclusiveOwningSession(s);
s.addSessionCloseTask(removeExclusive);
queue.addQueueDeleteTask(new AMQQueue.Task()
{
-
public void doTask(AMQQueue queue) throws AMQException
{
s.removeSessionCloseTask(removeExclusive);
@@ -1029,7 +1065,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
}
}
- else if (method.getExclusive() && (queue.getPrincipalHolder() != null && !queue.getPrincipalHolder().equals(session)))
+ else if (method.getExclusive() && (queue.getExclusiveOwningSession() != null && !queue.getExclusiveOwningSession().equals(session)))
{
String description = "Cannot declare queue('" + queueName + "'),"
+ " as exclusive queue with same name "
@@ -1077,7 +1113,7 @@ public class ServerSessionDelegate extends SessionDelegate
}
else
{
- if(queue.getPrincipalHolder() != null && queue.getPrincipalHolder() != session)
+ if(queue.getAuthorizationHolder() != null && queue.getAuthorizationHolder() != session)
{
exception(session,method,ExecutionErrorCode.RESOURCE_LOCKED, "Exclusive Queue: " + queueName + " owned exclusively by another session");
}
@@ -1223,6 +1259,8 @@ public class ServerSessionDelegate extends SessionDelegate
@Override
public void closed(Session session)
{
+ setThreadSubject(session);
+
for(Subscription_0_10 sub : getSubscriptions(session))
{
((ServerSession)session).unregister(sub);
@@ -1241,4 +1279,9 @@ public class ServerSessionDelegate extends SessionDelegate
return ((ServerSession)session).getSubscriptions();
}
+ private void setThreadSubject(Session session)
+ {
+ final ServerConnection scon = (ServerConnection) session.getConnection();
+ SecurityManager.setThreadSubject(scon.getAuthorizedSubject());
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
index db781ead96..36e9d78440 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/AutoCommitTransaction.java
@@ -50,6 +50,11 @@ public class AutoCommitTransaction implements ServerTransaction
_transactionLog = transactionLog;
}
+ public long getTransactionStartTime()
+ {
+ return 0L;
+ }
+
/**
* Since AutoCommitTransaction have no concept of a long lived transaction, any Actions registered
* by the caller are executed immediately.
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 a04c743be1..946dbd7c28 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
@@ -20,18 +20,23 @@ package org.apache.qpid.server.txn;
*
*/
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.server.message.EnqueableMessage;
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.queue.BaseQueue;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.store.TransactionLog;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.BaseQueue;
+import org.apache.qpid.server.queue.QueueEntry;
+import org.apache.qpid.server.store.TransactionLog;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A concrete implementation of ServerTransaction where enqueue/dequeue
@@ -41,17 +46,28 @@ import org.apache.qpid.server.store.TransactionLog;
*/
public class LocalTransaction implements ServerTransaction
{
- protected static final Logger _logger = Logger.getLogger(LocalTransaction.class);
+ protected static final Logger _logger = LoggerFactory.getLogger(LocalTransaction.class);
private final List<Action> _postTransactionActions = new ArrayList<Action>();
private volatile TransactionLog.Transaction _transaction;
private TransactionLog _transactionLog;
+ private long _txnStartTime = 0L;
public LocalTransaction(TransactionLog transactionLog)
{
_transactionLog = transactionLog;
}
+
+ public boolean inTransaction()
+ {
+ return _transaction != null;
+ }
+
+ public long getTransactionStartTime()
+ {
+ return _txnStartTime;
+ }
public void addPostTransactionAction(Action postTransactionAction)
{
@@ -89,7 +105,6 @@ public class LocalTransaction implements ServerTransaction
try
{
-
for(QueueEntry entry : queueEntries)
{
ServerMessage message = entry.getMessage();
@@ -113,7 +128,6 @@ public class LocalTransaction implements ServerTransaction
_logger.error("Error during message dequeues", e);
tidyUpOnError(e);
}
-
}
private void tidyUpOnError(Exception e)
@@ -140,8 +154,7 @@ public class LocalTransaction implements ServerTransaction
}
finally
{
- _transaction = null;
- _postTransactionActions.clear();
+ resetDetails();
}
}
@@ -193,6 +206,11 @@ public class LocalTransaction implements ServerTransaction
{
_postTransactionActions.add(postTransactionAction);
+ if (_txnStartTime == 0L)
+ {
+ _txnStartTime = System.currentTimeMillis();
+ }
+
if(message.isPersistent())
{
try
@@ -248,17 +266,14 @@ public class LocalTransaction implements ServerTransaction
}
finally
{
- _transaction = null;
- _postTransactionActions.clear();
+ resetDetails();
}
-
}
public void rollback()
{
try
{
-
if(_transaction != null)
{
_transaction.abortTran();
@@ -280,9 +295,15 @@ public class LocalTransaction implements ServerTransaction
}
finally
{
- _transaction = null;
- _postTransactionActions.clear();
+ resetDetails();
}
}
}
+
+ private void resetDetails()
+ {
+ _transaction = null;
+ _postTransactionActions.clear();
+ _txnStartTime = 0L;
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
index b61b8a5c64..b3c6e1ac3a 100755
--- a/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/txn/ServerTransaction.java
@@ -52,6 +52,13 @@ public interface ServerTransaction
public void onRollback();
}
+ /**
+ * Return the time the current transaction started.
+ *
+ * @return the time this transaction started or 0 if not in a transaction
+ */
+ long getTransactionStartTime();
+
/**
* Register an Action for execution after transaction commit or rollback. Actions
* will be executed in the order in which they are registered.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java b/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java
new file mode 100644
index 0000000000..898a667736
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferInputStream.java
@@ -0,0 +1,87 @@
+/*
+ *
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+
+public class ByteBufferInputStream extends InputStream
+{
+ private final ByteBuffer _buffer;
+
+ public ByteBufferInputStream(ByteBuffer buffer)
+ {
+ _buffer = buffer;
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ return _buffer.get() & 0xFF;
+ }
+
+
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException
+ {
+ if(_buffer.remaining() < len)
+ {
+ len = _buffer.remaining();
+ }
+ _buffer.get(b, off, len);
+
+ return len;
+ }
+
+ @Override
+ public void mark(int readlimit)
+ {
+ _buffer.mark();
+ }
+
+ @Override
+ public void reset() throws IOException
+ {
+ _buffer.reset();
+ }
+
+ @Override
+ public boolean markSupported()
+ {
+ return true;
+ }
+
+ @Override
+ public long skip(long n) throws IOException
+ {
+
+ _buffer.position(_buffer.position()+(int)n);
+
+ return n;
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ return _buffer.remaining();
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java b/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferOutputStream.java
index 0e4444725e..ca9a41bc32 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolEngineFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/util/ByteBufferOutputStream.java
@@ -1,6 +1,5 @@
-package org.apache.qpid.server.protocol;
/*
- *
+ *
* 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
@@ -8,43 +7,40 @@ package org.apache.qpid.server.protocol;
* 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.util;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
-import org.apache.qpid.protocol.ProtocolEngine;
-import org.apache.qpid.protocol.ProtocolEngineFactory;
-import org.apache.qpid.server.registry.ApplicationRegistry;
-import org.apache.qpid.server.virtualhost.VirtualHostRegistry;
-import org.apache.qpid.transport.NetworkDriver;
-
-public class AMQProtocolEngineFactory implements ProtocolEngineFactory
+public class ByteBufferOutputStream extends OutputStream
{
- private VirtualHostRegistry _vhosts;
+ private final ByteBuffer _buffer;
- public AMQProtocolEngineFactory()
+ public ByteBufferOutputStream(ByteBuffer buffer)
{
- this(1);
+ _buffer = buffer;
}
-
- public AMQProtocolEngineFactory(Integer port)
+
+ @Override
+ public void write(int b)
{
- _vhosts = ApplicationRegistry.getInstance(port).getVirtualHostRegistry();
+ _buffer.put((byte)b);
}
-
-
- public ProtocolEngine newProtocolEngine(NetworkDriver networkDriver)
+
+ @Override
+ public void write(byte[] b, int off, int len)
{
- return new AMQProtocolEngine(_vhosts, networkDriver);
+ _buffer.put(b, off, len);
}
-
}
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 2db1944cd1..ebace95f65 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
@@ -63,6 +63,10 @@ public abstract class HouseKeepingTask implements Runnable
{
_logger.warn(this.getClass().getSimpleName() + " throw exception: " + e, e);
}
+ finally
+ {
+ CurrentActor.remove();
+ }
}
public VirtualHost getVirtualHost()
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 4ed0507228..04f19b79bb 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
@@ -20,30 +20,28 @@
*/
package org.apache.qpid.server.virtualhost;
+import java.util.UUID;
+
import org.apache.qpid.common.Closeable;
+import org.apache.qpid.server.binding.BindingFactory;
+import org.apache.qpid.server.configuration.ConfigStore;
+import org.apache.qpid.server.configuration.VirtualHostConfig;
+import org.apache.qpid.server.configuration.VirtualHostConfiguration;
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.configuration.VirtualHostConfiguration;
-import org.apache.qpid.server.configuration.VirtualHostConfig;
-import org.apache.qpid.server.configuration.ConfigStore;
+import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.queue.QueueRegistry;
-import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.exchange.ExchangeFactory;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.TransactionLog;
-import org.apache.qpid.server.store.DurableConfigurationStore;
+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.management.ManagedObject;
-import org.apache.qpid.server.registry.IApplicationRegistry;
-import org.apache.qpid.server.binding.BindingFactory;
-
-import java.util.List;
-import java.util.UUID;
-import java.util.TimerTask;
-import java.util.concurrent.FutureTask;
+import org.apache.qpid.server.stats.StatisticsGatherer;
+import org.apache.qpid.server.store.DurableConfigurationStore;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.TransactionLog;
-public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable
+public interface VirtualHost extends DurableConfigurationStore.Source, VirtualHostConfig, Closeable, StatisticsGatherer
{
IConnectionRegistry getConnectionRegistry();
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 96a9ac729e..0fd31973b2 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
@@ -43,7 +43,10 @@ import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.AMQException;
import org.apache.log4j.Logger;
+import org.apache.qpid.server.util.ByteBufferInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.List;
@@ -236,7 +239,14 @@ public class VirtualHostConfigRecoveryHandler implements ConfigurationRecoveryHa
FieldTable argumentsFT = null;
if(buf != null)
{
- argumentsFT = new FieldTable(org.apache.mina.common.ByteBuffer.wrap(buf),buf.limit());
+ try
+ {
+ argumentsFT = new FieldTable(new DataInputStream(new ByteBufferInputStream(buf)),buf.limit());
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("IOException should not be thrown here", e);
+ }
}
BindingFactory bf = _virtualHost.getBindingFactory();
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 6ec1c512e5..17c65003e9 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,23 +20,21 @@
*/
package org.apache.qpid.server.virtualhost;
-import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
-import org.apache.qpid.AMQInternalException;
import org.apache.qpid.AMQStoreException;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.FieldTable;
@@ -63,6 +61,8 @@ 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.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.queue.DefaultQueueRegistry;
@@ -71,7 +71,7 @@ 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.manager.AuthenticationManager;
-import org.apache.qpid.server.security.auth.manager.PrincipalDatabaseAuthenticationManager;
+import org.apache.qpid.server.stats.StatisticsCounter;
import org.apache.qpid.server.store.ConfigurationRecoveryHandler;
import org.apache.qpid.server.store.DurableConfigurationStore;
import org.apache.qpid.server.store.MessageStore;
@@ -99,7 +99,7 @@ public class VirtualHostImpl implements VirtualHost
private AMQBrokerManagerMBean _brokerMBean;
- private AuthenticationManager _authenticationManager;
+ private final AuthenticationManager _authenticationManager;
private SecurityManager _securityManager;
@@ -111,6 +111,8 @@ public class VirtualHostImpl implements VirtualHost
private BrokerConfig _broker;
private UUID _id;
+ private boolean _statisticsEnabled = false;
+ private StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
private final long _createTime = System.currentTimeMillis();
private final ConcurrentHashMap<BrokerLink,BrokerLink> _links = new ConcurrentHashMap<BrokerLink, BrokerLink>();
@@ -161,12 +163,12 @@ public class VirtualHostImpl implements VirtualHost
public String getObjectInstanceName()
{
- return _name.toString();
+ return ObjectName.quote(_name);
}
public String getName()
{
- return _name.toString();
+ return _name;
}
public VirtualHostImpl getVirtualHost()
@@ -175,22 +177,11 @@ public class VirtualHostImpl implements VirtualHost
}
}
- public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig) throws Exception
- {
- this(appRegistry, hostConfig, null);
- }
-
-
- public VirtualHostImpl(VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
- {
- this(ApplicationRegistry.getInstance(),hostConfig,store);
- }
-
- private VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
+ public VirtualHostImpl(IApplicationRegistry appRegistry, VirtualHostConfiguration hostConfig, MessageStore store) throws Exception
{
if (hostConfig == null)
{
- throw new IllegalAccessException("HostConfig and MessageStore cannot be null");
+ throw new IllegalArgumentException("HostConfig cannot be null");
}
_appRegistry = appRegistry;
@@ -244,21 +235,28 @@ public class VirtualHostImpl implements VirtualHost
initialiseMessageStore(hostConfig);
}
- _authenticationManager = new PrincipalDatabaseAuthenticationManager(_name, _configuration);
+ _authenticationManager = ApplicationRegistry.getInstance().getAuthenticationManager();
_brokerMBean = new AMQBrokerManagerMBean(_virtualHostMBean);
_brokerMBean.register();
- initialiseHouseKeeping(hostConfig.getHousekeepingExpiredMessageCheckPeriod());
+ initialiseHouseKeeping(hostConfig.getHousekeepingCheckPeriod());
+
+ initialiseStatistics();
}
+ /**
+ * Initialise a housekeeping task to iterate over queues cleaning expired messages with no consumers
+ * and checking for idle or open transactions that have exceeded the permitted thresholds.
+ *
+ * @param period
+ */
private void initialiseHouseKeeping(long period)
{
- /* add a timer task to iterate over queues, cleaning expired messages from queues with no consumers */
if (period != 0L)
{
- class ExpiredMessagesTask extends HouseKeepingTask
+ class VirtualHostHouseKeepingTask extends HouseKeepingTask
{
- public ExpiredMessagesTask(VirtualHost vhost)
+ public VirtualHostHouseKeepingTask(VirtualHost vhost)
{
super(vhost);
}
@@ -281,18 +279,29 @@ public class VirtualHostImpl implements VirtualHost
// house keeping task from running.
}
}
+ for (AMQConnectionModel connection : getConnectionRegistry().getConnections())
+ {
+ _logger.debug("Checking for long running open transactions on connection " + connection);
+ for (AMQSessionModel session : connection.getSessionModels())
+ {
+ _logger.debug("Checking for long running open transactions on session " + session);
+ try
+ {
+ session.checkTransactionStatus(_configuration.getTransactionTimeoutOpenWarn(),
+ _configuration.getTransactionTimeoutOpenClose(),
+ _configuration.getTransactionTimeoutIdleWarn(),
+ _configuration.getTransactionTimeoutIdleClose());
+ }
+ catch (Exception e)
+ {
+ _logger.error("Exception in housekeeping for connection: " + connection.toString(), e);
+ }
+ }
+ }
}
}
- scheduleHouseKeepingTask(period, new ExpiredMessagesTask(this));
-
- class ForceChannelClosuresTask extends TimerTask
- {
- public void run()
- {
- _connectionRegistry.expireClosedChannels();
- }
- }
+ scheduleHouseKeepingTask(period, new VirtualHostHouseKeepingTask(this));
Map<String, VirtualHostPluginFactory> plugins =
ApplicationRegistry.getInstance().getPluginManager().getVirtualHostPlugins();
@@ -446,46 +455,57 @@ public class VirtualHostImpl implements VirtualHost
private void configureQueue(QueueConfiguration queueConfiguration) throws AMQException, ConfigurationException
{
AMQQueue queue = AMQQueueFactory.createAMQQueueImpl(queueConfiguration, this);
+ String queueName = queue.getName();
if (queue.isDurable())
{
getDurableConfigurationStore().createQueue(queue);
}
+ //get the exchange name (returns default exchange name if none was specified)
String exchangeName = queueConfiguration.getExchange();
- Exchange exchange = _exchangeRegistry.getExchange(exchangeName == null ? null : new AMQShortString(exchangeName));
-
- if (exchange == null)
- {
- exchange = _exchangeRegistry.getDefaultExchange();
- }
-
+ Exchange exchange = _exchangeRegistry.getExchange(exchangeName);
if (exchange == null)
{
- throw new ConfigurationException("Attempt to bind queue to unknown exchange:" + exchangeName);
+ throw new ConfigurationException("Attempt to bind queue '" + queueName + "' to unknown exchange:" + exchangeName);
}
- List routingKeys = queueConfiguration.getRoutingKeys();
- if (routingKeys == null || routingKeys.isEmpty())
- {
- routingKeys = Collections.singletonList(queue.getNameShortString());
- }
+ Exchange defaultExchange = _exchangeRegistry.getDefaultExchange();
+
+ //get routing keys in configuration (returns empty list if none are defined)
+ List<?> routingKeys = queueConfiguration.getRoutingKeys();
for (Object routingKeyNameObj : routingKeys)
{
- AMQShortString routingKey = new AMQShortString(String.valueOf(routingKeyNameObj));
- if (_logger.isInfoEnabled())
+ String routingKey = String.valueOf(routingKeyNameObj);
+
+ if (exchange.equals(defaultExchange) && !queueName.equals(routingKey))
{
- _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + this);
+ throw new ConfigurationException("Illegal attempt to bind queue '" + queueName +
+ "' to the default exchange with a key other than the queue name: " + routingKey);
}
- _bindingFactory.addBinding(routingKey.toString(), queue, exchange, null);
+
+ configureBinding(queue, exchange, routingKey);
+ }
+
+ if (!exchange.equals(defaultExchange))
+ {
+ //bind the queue to the named exchange using its name
+ configureBinding(queue, exchange, queueName);
}
- if (exchange != _exchangeRegistry.getDefaultExchange())
+ //ensure the queue is bound to the default exchange using its name
+ configureBinding(queue, defaultExchange, queueName);
+ }
+
+ private void configureBinding(AMQQueue queue, Exchange exchange, String routingKey) throws AMQException
+ {
+ if (_logger.isInfoEnabled())
{
- _bindingFactory.addBinding(queue.getNameShortString().toString(), queue, exchange, null);
+ _logger.info("Binding queue:" + queue + " with routing key '" + routingKey + "' to exchange:" + exchange.getName());
}
+ _bindingFactory.addBinding(routingKey, queue, exchange, null);
}
public String getName()
@@ -627,6 +647,80 @@ public class VirtualHostImpl implements VirtualHost
{
return _bindingFactory;
}
+
+ public void registerMessageDelivered(long messageSize)
+ {
+ if (isStatisticsEnabled())
+ {
+ _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);
+ }
+ _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();
+ }
+ }
+
+ 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 void createBrokerConnection(final String transport,
final String host,
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
index dca165fa7e..2c0ceed80b 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/MessageStoreTool.java
@@ -192,7 +192,7 @@ public class MessageStoreTool
if (_initialised)
{
- ApplicationRegistry.remove(1);
+ ApplicationRegistry.remove();
}
_console.println("...exiting");
@@ -274,7 +274,7 @@ public class MessageStoreTool
{
ConfigurationFileApplicationRegistry registry = new ConfigurationFileApplicationRegistry(configFile);
- ApplicationRegistry.remove(1);
+ ApplicationRegistry.remove();
ApplicationRegistry.initialise(registry);
diff --git a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
index 4fd4999b19..806e161bbc 100644
--- a/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
+++ b/java/broker/src/main/java/org/apache/qpid/tools/messagestore/commands/Show.java
@@ -364,7 +364,7 @@ public class Show extends AbstractCommand
{
if(msg instanceof AMQMessage)
{
- headers = ((BasicContentHeaderProperties) ((AMQMessage)msg).getContentHeaderBody().properties);
+ headers = ((BasicContentHeaderProperties) ((AMQMessage)msg).getContentHeaderBody().getProperties());
}
}
catch (AMQException e)