diff options
| author | Keith Wall <kwall@apache.org> | 2014-01-14 14:46:35 +0000 |
|---|---|---|
| committer | Keith Wall <kwall@apache.org> | 2014-01-14 14:46:35 +0000 |
| commit | 840bf7469dc7b18d74eaa275bb23ed09dd0e168b (patch) | |
| tree | eb4ef3da5fdbeb57d89f4ef1f0d0e175c4285e3f /qpid/java | |
| parent | 4e99d2f6a47801531ddd443fc120fee79e0568b2 (diff) | |
| download | qpid-python-840bf7469dc7b18d74eaa275bb23ed09dd0e168b.tar.gz | |
NO-JIRA: Merge latest changes back from trunk.
Changes merged with command:
svn merge -r 1549894:1558036 https://svn.apache.org/repos/asf/qpid/trunk
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-broker-bdb-ha@1558056 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java')
166 files changed, 4506 insertions, 888 deletions
diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java index f46840e9ae..f8af2d388e 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionFactoryImpl.java @@ -26,16 +26,27 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLDecoder; import java.net.URLStreamHandler; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Map; import javax.jms.JMSException; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.TopicConnection; import javax.jms.TopicConnectionFactory; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManagerFactory; + +import org.apache.qpid.amqp_1_0.client.SSLUtil; import org.apache.qpid.amqp_1_0.jms.ConnectionFactory; public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnectionFactory, QueueConnectionFactory { + private final String _protocol; private String _host; private int _port; private String _username; @@ -49,6 +60,13 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection private boolean _useBinaryMessageId = Boolean.parseBoolean(System.getProperty("qpid.use_binary_message_id", "true")); private boolean _syncPublish = Boolean.parseBoolean(System.getProperty("qpid.sync_publish", "false")); private int _maxSessions = Integer.getInteger("qpid.max_sessions", 0); + private int _maxPrefetch; + private String _keyStorePath; + private String _keyStorePassword; + private String _keyStoreCertAlias; + private String _trustStorePath; + private String _trustStorePassword; + private SSLContext _sslContext; public ConnectionFactoryImpl(final String host, @@ -98,6 +116,20 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection final boolean ssl, final int maxSessions) { + this(ssl?"amqps":"amqp",host,port,username,password,clientId,remoteHost,ssl,maxSessions); + } + + public ConnectionFactoryImpl(final String protocol, + final String host, + final int port, + final String username, + final String password, + final String clientId, + final String remoteHost, + final boolean ssl, + final int maxSessions) + { + _protocol = protocol; _host = host; _port = port; _username = username; @@ -113,118 +145,342 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection return createConnection(_username, _password); } - public ConnectionImpl createConnection(final String username, final String password) throws JMSException + public ConnectionImpl createConnection(String username, final String password) throws JMSException { - ConnectionImpl connection = new ConnectionImpl(_host, _port, username, password, _clientId, _remoteHost, _ssl, _maxSessions); + synchronized (this) + { + if(_ssl && _sslContext == null) + { + try + { + _sslContext = SSLUtil.buildSslContext(_keyStoreCertAlias,_keyStorePath, + KeyStore.getDefaultType(), + _keyStorePassword, + KeyManagerFactory.getDefaultAlgorithm(), + _trustStorePath,_trustStorePassword, + KeyStore.getDefaultType(), + TrustManagerFactory.getDefaultAlgorithm()); + if(username == null && _keyStoreCertAlias != null) + { + X509Certificate[] certs = SSLUtil.getClientCertificates(_keyStoreCertAlias, + _keyStorePath, + _keyStorePassword, + KeyStore.getDefaultType(), + KeyManagerFactory.getDefaultAlgorithm()); + if(certs != null && certs.length != 0) + { + username = certs[0].getSubjectDN().getName(); + } + } + + } + catch (GeneralSecurityException e) + { + final JMSException jmsException = new JMSException("Unable to create SSL context"); + jmsException.setLinkedException(e); + jmsException.initCause(e); + throw jmsException; + } + catch (IOException e) + { + final JMSException jmsException = new JMSException("Unable to create SSL context"); + jmsException.setLinkedException(e); + jmsException.initCause(e); + throw jmsException; } + } + } + ConnectionImpl connection = new ConnectionImpl(_protocol,_host, _port, username, password, _clientId, _remoteHost, _sslContext, _maxSessions); connection.setQueuePrefix(_queuePrefix); connection.setTopicPrefix(_topicPrefix); connection.setUseBinaryMessageId(_useBinaryMessageId); connection.setSyncPublish(_syncPublish); + if(_maxPrefetch != 0) + { + connection.setMaxPrefetch(_maxPrefetch); + } return connection; } + public void setMaxPrefetch(final int maxPrefetch) + { + _maxPrefetch = maxPrefetch; + } + + public void setKeyStorePath(final String keyStorePath) + { + _keyStorePath = keyStorePath; + } + + public void setKeyStorePassword(final String keyStorePassword) + { + _keyStorePassword = keyStorePassword; + } + + public void setKeyStoreCertAlias(final String keyStoreCertAlias) + { + _keyStoreCertAlias = keyStoreCertAlias; + } + + public void setTrustStorePath(final String trustStorePath) + { + _trustStorePath = trustStorePath; + } + + public void setTrustStorePassword(final String trustStorePassword) + { + _trustStorePassword = trustStorePassword; + } + + private static class ConnectionOptions + { + String username; + String password; + String clientId; + String remoteHost; + + boolean binaryMessageId = true; + boolean syncPublish; + int maxSessions; + public boolean ssl; + public int maxPrefetch; + public String trustStorePath; + public String trustStorePassword; + public String keyStorePath; + public String keyStorePassword; + public String keyStoreCertAlias; + } + + + + private static abstract class OptionSetter + { + + private static final Map<String, OptionSetter> OPTION_SETTER_MAP = new HashMap<String, OptionSetter>(); + private final String _name; + private final String _description; + + public OptionSetter(String name, String description) + { + OPTION_SETTER_MAP.put(name.toLowerCase(), this); + _name = name; + _description = description; + } + + public abstract void setOption(ConnectionOptions options, String value) throws MalformedURLException; + + public static void parseOptions(URL url, ConnectionOptions options) throws MalformedURLException + { + String query = url.getQuery(); + if(query != null) + { + for(String param : query.split("&")) + { + + String[] keyValuePair = param.split("=",2); + OptionSetter setter = OPTION_SETTER_MAP.get(keyValuePair[0]); + if(setter != null) + { + setter.setOption(options, keyValuePair[1]); + } + else + { + throw new MalformedURLException("Unknown URL option: '"+keyValuePair[0]+"' in connection URL"); + } + + } + } + } + } + + private static final OptionSetter[] _options = + { + new OptionSetter("clientid", "JMS client id / AMQP container id") + { + public void setOption(ConnectionOptions options, String value) + { + options.clientId = value; + } + }, + new OptionSetter("ssl", "Set to \"true\" to use SSL encryption") + { + public void setOption(ConnectionOptions options, String value) + { + options.ssl = Boolean.valueOf(value); + } + }, + new OptionSetter("remote-host", "AMQP remote host") + { + public void setOption(ConnectionOptions options, String value) + { + options.remoteHost = value; + } + }, + new OptionSetter("binary-messageid", "Use binary (rather than String) message ids") + { + public void setOption(ConnectionOptions options, String value) + { + options.binaryMessageId = Boolean.parseBoolean(value); + } + }, + new OptionSetter("sync-publish", "Wait for acknowledge when sending messages") + { + public void setOption(ConnectionOptions options, String value) + { + options.syncPublish = Boolean.parseBoolean(value); + } + }, + new OptionSetter("max-sessions", "set maximum number of sessions allowed") + { + public void setOption(ConnectionOptions options, String value) + { + options.maxSessions = Integer.parseInt(value); + } + }, + new OptionSetter("max-prefetch", "set maximum number of messages prefetched on a link") + { + public void setOption(ConnectionOptions options, String value) + { + options.maxPrefetch = Integer.parseInt(value); + } + }, + new OptionSetter("trust-store","") + { + public void setOption(final ConnectionOptions options, final String value) throws MalformedURLException + { + options.trustStorePath = value; + } + }, + new OptionSetter("trust-store-password","") + { + public void setOption(final ConnectionOptions options, final String value) throws MalformedURLException + { + options.trustStorePassword = value; + } + }, + new OptionSetter("key-store","") + { + public void setOption(final ConnectionOptions options, final String value) throws MalformedURLException + { + options.keyStorePath = value; + } + }, + new OptionSetter("key-store-password","") + { + public void setOption(final ConnectionOptions options, final String value) throws MalformedURLException + { + options.keyStorePassword = value; + } + }, + new OptionSetter("ssl-cert-alias","") + { + public void setOption(final ConnectionOptions options, final String value) throws MalformedURLException + { + options.keyStoreCertAlias = value; + } + } + }; + public static ConnectionFactoryImpl createFromURL(final String urlString) throws MalformedURLException { URL url = new URL(null, urlString, new URLStreamHandler() - { - @Override - protected URLConnection openConnection(URL u) throws IOException - { - throw new UnsupportedOperationException(); - } - }); + { + @Override + protected URLConnection openConnection(URL u) throws IOException + { + throw new UnsupportedOperationException(); + } + }); String protocol = url.getProtocol(); - if(protocol == null || "".equals(protocol)) + if (protocol == null || "".equals(protocol)) { protocol = "amqp"; } - else if(!protocol.equals("amqp") && !protocol.equals("amqps")) - { - throw new MalformedURLException("Protocol '"+protocol+"' unknown. Must be one of 'amqp' or 'amqps'."); - } String host = url.getHost(); int port = url.getPort(); - boolean ssl = false; + final ConnectionOptions options = new ConnectionOptions(); - if(port == -1) + if (port == -1) { - if("amqps".equals(protocol)) + if ("amqps".equals(protocol)) { port = 5671; - ssl = true; + options.ssl = true; } - else + else if("amqp".equals(protocol)) { port = 5672; } + else if("ws".equals(protocol)) + { + port = 80; + } + else if("wss".equals(protocol)) + { + port = 443; + } } - else if("amqps".equals(protocol)) + else if ("amqps".equals(protocol) || "wss".equals(protocol)) { - ssl = true; + options.ssl = true; } - String userInfo = url.getUserInfo(); - String username = null; - String password = null; - String clientId = null; - String remoteHost = null; - boolean binaryMessageId = true; - boolean syncPublish = false; - int maxSessions = 0; + String userInfo = url.getUserInfo(); - if(userInfo != null) + if (userInfo != null) { - String[] components = userInfo.split(":",2); - username = URLDecoder.decode(components[0]); - if(components.length == 2) + String[] components = userInfo.split(":", 2); + options.username = URLDecoder.decode(components[0]); + if (components.length == 2) { - password = URLDecoder.decode(components[1]); - } - } - String query = url.getQuery(); - if(query != null) - { - for(String param : query.split("&")) - { - String[] keyValuePair = param.split("=",2); - if(keyValuePair[0].equalsIgnoreCase("clientid")) - { - clientId = keyValuePair[1]; - } - else if(keyValuePair[0].equalsIgnoreCase("ssl")) - { - ssl = Boolean.valueOf(keyValuePair[1]); - } - else if(keyValuePair[0].equalsIgnoreCase("remote-host")) - { - remoteHost = keyValuePair[1]; - } - else if (keyValuePair[0].equalsIgnoreCase("binary-messageid")) - { - binaryMessageId = Boolean.parseBoolean(keyValuePair[1]); - } - else if (keyValuePair[0].equalsIgnoreCase("sync-publish")) - { - syncPublish = Boolean.parseBoolean(keyValuePair[1]); - } - else if(keyValuePair[0].equalsIgnoreCase("max-sessions")) - { - maxSessions = Integer.parseInt(keyValuePair[1]); - } + options.password = URLDecoder.decode(components[1]); } } - if(remoteHost == null) + OptionSetter.parseOptions(url, options); + + if (options.remoteHost == null) { - remoteHost = host; + options.remoteHost = host; } ConnectionFactoryImpl connectionFactory = - new ConnectionFactoryImpl(host, port, username, password, clientId, remoteHost, ssl, maxSessions); - connectionFactory.setUseBinaryMessageId(binaryMessageId); - connectionFactory.setSyncPublish(syncPublish); + new ConnectionFactoryImpl(protocol, + host, + port, + options.username, + options.password, + options.clientId, + options.remoteHost, + options.ssl, + options.maxSessions); + connectionFactory.setUseBinaryMessageId(options.binaryMessageId); + connectionFactory.setSyncPublish(options.syncPublish); + if (options.maxPrefetch != 0) + { + connectionFactory.setMaxPrefetch(options.maxPrefetch); + } + if (options.keyStorePath != null) + { + connectionFactory.setKeyStorePath(options.keyStorePath); + } + if (options.keyStorePassword != null) + { + connectionFactory.setKeyStorePassword(options.keyStorePassword); + } + if (options.keyStoreCertAlias != null) + { + connectionFactory.setKeyStoreCertAlias(options.keyStoreCertAlias); + } + if (options.trustStorePath != null) + { + connectionFactory.setTrustStorePath(options.trustStorePath); + } + if (options.trustStorePassword != null) + { + connectionFactory.setTrustStorePassword(options.trustStorePassword); + } return connectionFactory; @@ -287,4 +543,6 @@ public class ConnectionFactoryImpl implements ConnectionFactory, TopicConnection { _syncPublish = syncPublish; } + + } diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java index 976ae10c56..7ce445a9b2 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/ConnectionImpl.java @@ -28,7 +28,9 @@ import org.apache.qpid.amqp_1_0.transport.Container; import javax.jms.*; import javax.jms.IllegalStateException; import javax.jms.Queue; +import javax.net.ssl.SSLContext; +import java.security.NoSuchAlgorithmException; import java.util.*; import org.apache.qpid.amqp_1_0.type.Symbol; @@ -38,6 +40,8 @@ import org.apache.qpid.amqp_1_0.type.transport.Error; public class ConnectionImpl implements Connection, QueueConnection, TopicConnection { + private final String _protocol; + private final SSLContext _sslContext; private ConnectionMetaData _connectionMetaData; private volatile ExceptionListener _exceptionListener; @@ -54,13 +58,18 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect private final String _username; private final String _password; private String _remoteHost; - private final boolean _ssl; private String _clientId; private String _queuePrefix; private String _topicPrefix; private boolean _useBinaryMessageId = Boolean.parseBoolean(System.getProperty("qpid.use_binary_message_id", "true")); private boolean _syncPublish = Boolean.parseBoolean(System.getProperty("qpid.sync_publish", "false")); private int _maxSessions; + private int _maxPrefetch; + + public void setMaxPrefetch(final int maxPrefetch) + { + _maxPrefetch = maxPrefetch; + } private static enum State { @@ -87,15 +96,50 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect this(host, port, username, password, clientId, remoteHost, ssl,0); } + public ConnectionImpl(String host, int port, String username, String password, String clientId, String remoteHost, boolean ssl, int maxSessions) throws JMSException { + this(ssl?"amqps":"amqp",host,port,username,password,clientId,remoteHost,ssl,maxSessions); + } + + public ConnectionImpl(String protocol, String host, int port, String username, String password, String clientId, String remoteHost, boolean ssl, int maxSessions) throws JMSException + { + this(protocol, + host, + port, + username, + password, + clientId, + remoteHost, + ssl ? getDefaultSSLContext() : null, + maxSessions); + } + + private static SSLContext getDefaultSSLContext() throws JMSException + { + try + { + return SSLContext.getDefault(); + } + catch (NoSuchAlgorithmException e) + { + JMSException jmsException = new JMSException(e.getMessage()); + jmsException.setLinkedException(e); + jmsException.initCause(e); + throw jmsException; + } + } + + public ConnectionImpl(String protocol, String host, int port, String username, String password, String clientId, String remoteHost, SSLContext sslContext, int maxSessions) throws JMSException + { + _protocol = protocol; _host = host; _port = port; _username = username; _password = password; _clientId = clientId; _remoteHost = remoteHost; - _ssl = ssl; + _sslContext = sslContext; _maxSessions = maxSessions; } @@ -109,11 +153,11 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect _state = State.STOPPED; Container container = _clientId == null ? new Container() : new Container(_clientId); - // TODO - authentication, containerId, clientId, ssl?, etc + try { - _conn = new org.apache.qpid.amqp_1_0.client.Connection(_host, - _port, _username, _password, container, _remoteHost, _ssl, + _conn = new org.apache.qpid.amqp_1_0.client.Connection(_protocol, _host, + _port, _username, _password, container, _remoteHost, _sslContext, _maxSessions - 1); _conn.setConnectionErrorTask(new ConnectionErrorTask()); // TODO - retrieve negotiated AMQP version @@ -182,6 +226,10 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect SessionImpl session = new SessionImpl(this, acknowledgeMode); session.setQueueSession(_isQueueConnection); session.setTopicSession(_isTopicConnection); + if(_maxPrefetch != 0) + { + session.setMaxPrefetch(_maxPrefetch); + } boolean connectionStarted = false; synchronized(_lock) @@ -370,21 +418,47 @@ public class ConnectionImpl implements Connection, QueueConnection, TopicConnect _lock.notifyAll(); } - + + List<JMSException> errors = new ArrayList<JMSException>(); + if (sessions != null) { for(SessionImpl session : sessions) { - session.close(); + try + { + session.close(); + } + catch(JMSException e) + { + errors.add(e); + } } for(CloseTask task : closeTasks) { task.onClose(); } - if(closeConnection) { - _conn.close(); + if(closeConnection) + { + try + { + _conn.close(); + } + catch (ConnectionErrorException e) + { + final JMSException jmsException = new JMSException("Error while closing connection: " + e.getMessage()); + jmsException.setLinkedException(e); + throw jmsException; + } } } + + if(!errors.isEmpty()) + { + final JMSException jmsException = new JMSException("Error while closing connection: " + errors.get(0).getMessage()); + jmsException.setLinkedException(errors.get(0)); + throw jmsException; + } } private void checkClosed() throws IllegalStateException diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java index fd6f09d162..96ee1e984d 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageConsumerImpl.java @@ -76,6 +76,7 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi private Binary _lastTxnUpdate; private final List<Message> _recoverReplayMessages = new ArrayList<Message>(); private final List<Message> _replaymessages = new ArrayList<Message>(); + private int _maxPrefetch = 100; MessageConsumerImpl(final Destination destination, final SessionImpl session, @@ -117,6 +118,10 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi throw new InvalidDestinationException("Invalid destination class " + destination.getClass().getName()); } _session = session; + if(session.getMaxPrefetch() != 0) + { + _maxPrefetch = session.getMaxPrefetch(); + } _receiver = createClientReceiver(); _receiver.setRemoteErrorListener(new Runnable() @@ -442,7 +447,7 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi public void start() { - _receiver.setCredit(UnsignedInteger.valueOf(100), true); + _receiver.setCredit(UnsignedInteger.valueOf(getMaxPrefetch()), true); } public Queue getQueue() throws JMSException @@ -487,4 +492,14 @@ public class MessageConsumerImpl implements MessageConsumer, QueueReceiver, Topi } } } + + public int getMaxPrefetch() + { + return _maxPrefetch; + } + + public void setMaxPrefetch(final int maxPrefetch) + { + _maxPrefetch = maxPrefetch; + } } diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java index cee4f4f6f2..e459575974 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/MessageProducerImpl.java @@ -34,6 +34,8 @@ import javax.jms.*; import javax.jms.IllegalStateException; import javax.jms.Message; import java.util.UUID; +import java.util.concurrent.TimeoutException; + import org.apache.qpid.amqp_1_0.type.messaging.Accepted; import org.apache.qpid.amqp_1_0.type.messaging.Rejected; import org.apache.qpid.amqp_1_0.type.messaging.Source; @@ -221,7 +223,7 @@ public class MessageProducerImpl implements MessageProducer, QueueSender, TopicP } catch (Sender.SenderClosingException e) { - final JMSException jmsException = new JMSException("error closing"); + final JMSException jmsException = new JMSException("Error closing producer: " + e.getMessage()); jmsException.setLinkedException(e); throw jmsException; } @@ -299,8 +301,8 @@ public class MessageProducerImpl implements MessageProducer, QueueSender, TopicP final org.apache.qpid.amqp_1_0.client.Message clientMessage = new org.apache.qpid.amqp_1_0.client.Message(msg.getSections()); DispositionAction action = null; - - if(_syncPublish) + final boolean doSync = _syncPublish || (deliveryMode == DeliveryMode.PERSISTENT && _session.getTxn() == null); + if(doSync) { action = new DispositionAction(_sender); } @@ -315,8 +317,14 @@ public class MessageProducerImpl implements MessageProducer, QueueSender, TopicP jmsException.setLinkedException(e); throw jmsException; } + catch (TimeoutException e) + { + JMSException jmsException = new JMSException("Timed out while waiting to get credit to send"); + jmsException.setLinkedException(e); + throw jmsException; + } - if(_syncPublish && !action.wasAccepted(_syncPublishTimeout)) + if(doSync && !action.wasAccepted(_syncPublishTimeout)) { if (action.getOutcome() instanceof Rejected) { diff --git a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java index 3fa1032111..a1cf0ef4e7 100644 --- a/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java +++ b/qpid/java/amqp-1-0-client-jms/src/main/java/org/apache/qpid/amqp_1_0/jms/impl/SessionImpl.java @@ -81,6 +81,7 @@ public class SessionImpl implements Session, QueueSession, TopicSession private boolean _isQueueSession; private boolean _isTopicSession; private Transaction _txn; + private int _maxPrefetch; protected SessionImpl(final ConnectionImpl connection, final AcknowledgeMode acknowledgeMode) throws JMSException { @@ -523,6 +524,13 @@ public class SessionImpl implements Session, QueueSession, TopicSession messageConsumer = new TopicSubscriberImpl(name, true, (org.apache.qpid.amqp_1_0.jms.Topic) topic, this, selector, noLocal); + + if(_dispatcherThread == null) + { + _dispatcherThread = new Thread(_dispatcher); + _dispatcherThread.start(); + } + addConsumer(messageConsumer); if(_connection.isStarted()) { @@ -836,6 +844,16 @@ public class SessionImpl implements Session, QueueSession, TopicSession return _txn; } + public void setMaxPrefetch(final int maxPrefetch) + { + _maxPrefetch = maxPrefetch; + } + + public int getMaxPrefetch() + { + return _maxPrefetch; + } + private class Dispatcher implements Runnable { diff --git a/qpid/java/amqp-1-0-client-websocket/build.xml b/qpid/java/amqp-1-0-client-websocket/build.xml new file mode 100644 index 0000000000..2d538aab66 --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/build.xml @@ -0,0 +1,39 @@ +<!-- + - + - 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. + - + --> +<project name="AMQP 1.0 Client WebSocket transport" default="build"> + + <property name="module.genpom" value="true"/> + <property name="module.depends" value="amqp-1-0-common amqp-1-0-client"/> + <property name="release.exclude.module.deps" value="true"/> + + <import file="../module.xml"/> + + <target name="release-bin-copy-readme"> + <copy todir="${module.release}" overwrite="true" failonerror="true"> + <fileset file="${basedir}/README.txt" /> + </copy> + </target> + + <target name="release-bin-other" depends="release-bin-copy-readme"/> + + <target name="release-bin" depends="release-bin-tasks"/> + +</project> diff --git a/qpid/java/amqp-1-0-client-websocket/pom.xml b/qpid/java/amqp-1-0-client-websocket/pom.xml new file mode 100644 index 0000000000..205e0d5ab7 --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/pom.xml @@ -0,0 +1,163 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <parent> + <groupId>org.apache.qpid</groupId> + <artifactId>qpid-project</artifactId> + <version>0.26-SNAPSHOT</version> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>qpid-amqp-1-0-client-websocket</artifactId> + + <dependencies> + + <dependency> + <groupId>org.apache.qpid</groupId> + <artifactId>qpid-amqp-1-0-client</artifactId> + <version>0.26-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.apache.qpid</groupId> + <artifactId>qpid-amqp-1-0-common</artifactId> + <version>0.26-SNAPSHOT</version> + <scope>compile</scope> + </dependency> + + + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-servlet_2.5_spec</artifactId> + <version>1.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty.orbit</groupId> + <artifactId>javax.servlet</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-continuation</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-continuation</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-websocket</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + <build> + </build> + +</project> diff --git a/qpid/java/amqp-1-0-client-websocket/resources/LICENSE b/qpid/java/amqp-1-0-client-websocket/resources/LICENSE new file mode 100644 index 0000000000..de4b130f35 --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/resources/LICENSE @@ -0,0 +1,204 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + diff --git a/qpid/java/amqp-1-0-client-websocket/resources/NOTICE b/qpid/java/amqp-1-0-client-websocket/resources/NOTICE new file mode 100644 index 0000000000..8d1c3f3122 --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/resources/NOTICE @@ -0,0 +1,5 @@ +Apache Qpid +Copyright 2006-2012 Apache Software Foundation +This product includes software developed at +Apache Software Foundation (http://www.apache.org/) + diff --git a/qpid/java/amqp-1-0-client-websocket/resources/README.txt b/qpid/java/amqp-1-0-client-websocket/resources/README.txt new file mode 100644 index 0000000000..35d25050fe --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/resources/README.txt @@ -0,0 +1,7 @@ + +Documentation +-------------- +All of our user documentation can be accessed at: + +http://qpid.apache.org/documentation.html + diff --git a/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java b/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java new file mode 100644 index 0000000000..1805b593f1 --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketProvider.java @@ -0,0 +1,322 @@ +/* + * + * 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.amqp_1_0.client.websocket; + +import org.apache.qpid.amqp_1_0.client.ConnectionException; +import org.apache.qpid.amqp_1_0.client.TransportProvider; +import org.apache.qpid.amqp_1_0.codec.FrameWriter; +import org.apache.qpid.amqp_1_0.framing.AMQFrame; +import org.apache.qpid.amqp_1_0.framing.ConnectionHandler; +import org.apache.qpid.amqp_1_0.framing.ExceptionHandler; +import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; +import org.apache.qpid.amqp_1_0.type.FrameBody; +import org.apache.qpid.amqp_1_0.type.SaslFrameBody; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.util.thread.QueuedThreadPool; +import org.eclipse.jetty.websocket.WebSocket; +import org.eclipse.jetty.websocket.WebSocketClient; +import org.eclipse.jetty.websocket.WebSocketClientFactory; + +import javax.net.ssl.SSLContext; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; + +class WebSocketProvider implements TransportProvider +{ + public static final String AMQP_WEBSOCKET_SUBPROTOCOL = "AMQPWSB10"; + + private static final byte AMQP_HEADER_FRAME_TYPE = (byte) 222; + private static int _connections; + private static QueuedThreadPool _threadPool; + private final String _transport; + private static WebSocketClientFactory _factory; + + public WebSocketProvider(final String transport) + { + _transport = transport; + } + + private static synchronized WebSocketClientFactory getWebSocketClientFactory(SSLContext context) throws Exception + { + if(_threadPool == null) + { + _threadPool = new QueuedThreadPool(); + } + if(context != null) + { + WebSocketClientFactory factory = new WebSocketClientFactory(_threadPool); + SslContextFactory sslContextFactory = factory.getSslContextFactory(); + + + sslContextFactory.setSslContext(context); + + factory.start(); + + return factory; + } + else + { + if(_factory == null) + { + _factory = new WebSocketClientFactory(_threadPool); + _factory.start(); + } + _connections++; + return _factory; + } + } + + + private static synchronized void removeClient(final WebSocketClientFactory factory) throws Exception + { + + if(factory == _factory) + { + if(--_connections == 0) + { + _factory.stop(); + _factory = null; + } + } + else + { + factory.stop(); + } + } + + @Override + public void connect(final ConnectionEndpoint conn, + final String address, + final int port, + final SSLContext sslContext, final ExceptionHandler exceptionHandler) throws ConnectionException + { + + try + { + final WebSocketClientFactory webSocketClientFactory = getWebSocketClientFactory(sslContext); + WebSocketClient client = webSocketClientFactory.newWebSocketClient(); + // Configure the client + client.setProtocol(AMQP_WEBSOCKET_SUBPROTOCOL); + + + ConnectionHandler.FrameOutput<FrameBody> out = new ConnectionHandler.FrameOutput<FrameBody>(conn); + + final ConnectionHandler.FrameSource src; + + if(conn.requiresSASL()) + { + ConnectionHandler.FrameOutput<SaslFrameBody> saslOut = new ConnectionHandler.FrameOutput<SaslFrameBody>(conn); + + src = new ConnectionHandler.SequentialFrameSource(new HeaderFrameSource((byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)3, + (byte)1, + (byte)0, + (byte)0), + saslOut, + new HeaderFrameSource((byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)0, + (byte)1, + (byte)0, + (byte)0), + out); + + conn.setSaslFrameOutput(saslOut); + } + else + { + src = new ConnectionHandler.SequentialFrameSource(new HeaderFrameSource((byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)0, + (byte)1, + (byte)0, + (byte)0), + out); + } + + final ConnectionHandler handler = new ConnectionHandler(conn); + conn.setFrameOutputHandler(out); + final URI uri = new URI(_transport +"://"+ address+":"+ port +"/"); + WebSocket.Connection connection = client.open(uri, new WebSocket.OnBinaryMessage() + { + public void onOpen(Connection connection) + { + + Thread outputThread = new Thread(new FrameOutputThread(connection, src, conn, exceptionHandler, webSocketClientFactory)); + outputThread.setDaemon(true); + outputThread.start(); + } + + public void onClose(int closeCode, String message) + { + conn.inputClosed(); + } + + @Override + public void onMessage(final byte[] data, final int offset, final int length) + { + handler.parse(ByteBuffer.wrap(data,offset,length).slice()); + } + }).get(5, TimeUnit.SECONDS); + } + catch (Exception e) + { + throw new ConnectionException(e); + } + + } + + + + public static class HeaderFrameSource implements ConnectionHandler.FrameSource + { + + private final ByteBuffer _buffer; + private boolean _closed; + + public HeaderFrameSource(byte... headerBytes) + { + _buffer = ByteBuffer.wrap(headerBytes); + } + + + @Override + public AMQFrame getNextFrame(final boolean wait) + { + if(_closed) + { + return null; + } + else + { + _closed = true; + return new HeaderFrame(_buffer); + } + } + + public boolean closed() + { + return _closed; + } + + } + + + private static class HeaderFrame extends AMQFrame + { + + public HeaderFrame(final ByteBuffer buffer) + { + super(null,buffer); + } + + @Override + public short getChannel() + { + return 0; + } + + @Override + public byte getFrameType() + { + return AMQP_HEADER_FRAME_TYPE; + } + } + + private class FrameOutputThread implements Runnable + { + private final WebSocket.Connection _connection; + private final ConnectionHandler.FrameSource _frameSource; + private final ExceptionHandler _exceptionHandler; + private final FrameWriter _frameWriter; + private final byte[] _buffer; + private final WebSocketClientFactory _factory; + + public FrameOutputThread(final WebSocket.Connection connection, + final ConnectionHandler.FrameSource src, + final ConnectionEndpoint conn, + final ExceptionHandler exceptionHandler, final WebSocketClientFactory factory) + { + _connection = connection; + _frameSource = src; + _exceptionHandler = exceptionHandler; + _frameWriter = new FrameWriter(conn.getDescribedTypeRegistry()); + _buffer = new byte[conn.getMaxFrameSize()]; + _factory = factory; + } + + @Override + public void run() + { + + final FrameWriter frameWriter = _frameWriter; + final ByteBuffer buffer = ByteBuffer.wrap(_buffer); + try + { + + while(_connection.isOpen() && !_frameSource.closed()) + { + AMQFrame frame = _frameSource.getNextFrame(true); + if(frame instanceof HeaderFrame) + { + _connection.sendMessage(frame.getPayload().array(), + frame.getPayload().arrayOffset(), + frame.getPayload().remaining()); + } + else if(frame != null) + { + frameWriter.setValue(frame); + buffer.clear(); + int length = frameWriter.writeToBuffer(buffer); + _connection.sendMessage(_buffer,0,length); + } + } + if(_frameSource.closed() && _connection.isOpen()) + { + _connection.close(); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + finally + { + try + { + removeClient(_factory); + } + catch (Exception e) + { + e.printStackTrace(); + } + } + } + } +} diff --git a/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketTransportProviderFactory.java b/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketTransportProviderFactory.java new file mode 100644 index 0000000000..0e0dfa14d6 --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/src/main/java/org/apache/qpid/amqp_1_0/client/websocket/WebSocketTransportProviderFactory.java @@ -0,0 +1,42 @@ +/* + * + * 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.amqp_1_0.client.websocket; + +import org.apache.qpid.amqp_1_0.client.TransportProvider; +import org.apache.qpid.amqp_1_0.client.TransportProviderFactory; + +import java.util.Arrays; +import java.util.Collection; + +public class WebSocketTransportProviderFactory implements TransportProviderFactory +{ + @Override + public Collection<String> getSupportedTransports() + { + return Arrays.asList("ws", "wss"); + } + + @Override + public TransportProvider getProvider(final String transport) + { + return new WebSocketProvider(transport); + } +} diff --git a/qpid/java/amqp-1-0-client-websocket/src/main/resources/META-INF/services/org.apache.qpid.amqp_1_0.client.TransportProviderFactory b/qpid/java/amqp-1-0-client-websocket/src/main/resources/META-INF/services/org.apache.qpid.amqp_1_0.client.TransportProviderFactory new file mode 100644 index 0000000000..b5993fd7b0 --- /dev/null +++ b/qpid/java/amqp-1-0-client-websocket/src/main/resources/META-INF/services/org.apache.qpid.amqp_1_0.client.TransportProviderFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.amqp_1_0.client.websocket.WebSocketTransportProviderFactory
\ No newline at end of file diff --git a/qpid/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java b/qpid/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java index 1e4bcfc7d7..e29323eb80 100644 --- a/qpid/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java +++ b/qpid/java/amqp-1-0-client/example/src/main/java/org/apache/qpid/amqp_1_0/client/Respond.java @@ -27,6 +27,8 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Random; +import java.util.concurrent.TimeoutException; + import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.qpid.amqp_1_0.type.Section; @@ -280,7 +282,8 @@ public class Respond extends Util } } - private void respond(Message m) throws Sender.SenderCreationException, ConnectionClosedException, LinkDetachedException + private void respond(Message m) + throws Sender.SenderCreationException, ConnectionClosedException, LinkDetachedException, TimeoutException { List<Section> sections = m.getPayload(); String replyTo = null; diff --git a/qpid/java/amqp-1-0-client/pom.xml b/qpid/java/amqp-1-0-client/pom.xml index 13430c0c22..1d6a444d6d 100644 --- a/qpid/java/amqp-1-0-client/pom.xml +++ b/qpid/java/amqp-1-0-client/pom.xml @@ -35,6 +35,17 @@ </dependencies> <build> + <resources> + <resource> + <directory>src/main/resources</directory> + </resource> + <resource> + <directory>src/main/java</directory> + <includes> + <include>resources/</include> + </includes> + </resource> + </resources> </build> </project> diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java index 6074f9b868..6157ec53f6 100644 --- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Connection.java @@ -20,33 +20,27 @@ */ package org.apache.qpid.amqp_1_0.client; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.Socket; -import java.nio.ByteBuffer; +import java.security.NoSuchAlgorithmException; import java.security.Principal; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.ServiceLoader; +import java.util.concurrent.TimeoutException; -import javax.net.ssl.SSLSocketFactory; - -import org.apache.qpid.amqp_1_0.framing.SocketExceptionHandler; +import org.apache.qpid.amqp_1_0.framing.ExceptionHandler; import org.apache.qpid.amqp_1_0.framing.ConnectionHandler; -import org.apache.qpid.amqp_1_0.transport.AMQPTransport; import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; import org.apache.qpid.amqp_1_0.transport.Container; -import org.apache.qpid.amqp_1_0.transport.StateChangeListener; -import org.apache.qpid.amqp_1_0.type.Binary; +import org.apache.qpid.amqp_1_0.transport.Predicate; import org.apache.qpid.amqp_1_0.type.FrameBody; import org.apache.qpid.amqp_1_0.type.SaslFrameBody; import org.apache.qpid.amqp_1_0.type.UnsignedInteger; +import org.apache.qpid.amqp_1_0.type.transport.AmqpError; import org.apache.qpid.amqp_1_0.type.transport.ConnectionError; import org.apache.qpid.amqp_1_0.type.transport.Error; -public class Connection implements SocketExceptionHandler +import javax.net.ssl.SSLContext; + +public class Connection implements ExceptionHandler { - private static final Logger RAW_LOGGER = Logger.getLogger("RAW"); private static final int MAX_FRAME_SIZE = 65536; private String _address; @@ -145,6 +139,20 @@ public class Connection implements SocketExceptionHandler } + public Connection(final String protocol, + final String address, + final int port, + final String username, + final String password, + final Container container, + final String remoteHost, + final SSLContext sslContext, + final int channelMax) throws ConnectionException + { + this(protocol, address, port, username, password, MAX_FRAME_SIZE,container,remoteHost,sslContext, + channelMax); + } + public Connection(final String address, final int port, final String username, @@ -155,141 +163,119 @@ public class Connection implements SocketExceptionHandler boolean ssl, int channelMax) throws ConnectionException { + this(ssl?"amqp":"amqps",address,port,username,password,maxFrameSize,container,remoteHostname,getSslContext(ssl),channelMax); + } - _address = address; - + private static SSLContext getSslContext(final boolean ssl) throws ConnectionException + { try { - final Socket s; - if(ssl) - { - s = SSLSocketFactory.getDefault().createSocket(address, port); - } - else - { - s = new Socket(address, port); - } - - - Principal principal = username == null ? null : new Principal() - { - - public String getName() - { - return username; - } - }; - _conn = new ConnectionEndpoint(container, principal, password); - if(channelMax >= 0) - { - _conn.setChannelMax((short)channelMax); - } - _conn.setDesiredMaxFrameSize(UnsignedInteger.valueOf(maxFrameSize)); - _conn.setRemoteAddress(s.getRemoteSocketAddress()); - _conn.setRemoteHostname(remoteHostname); - - + return ssl ? SSLContext.getDefault() : null; + } + catch (NoSuchAlgorithmException e) + { + throw new ConnectionException(e); + } + } - ConnectionHandler.FrameOutput<FrameBody> out = new ConnectionHandler.FrameOutput<FrameBody>(_conn); + public Connection(final String protocol, + final String address, + final int port, + final String username, + final String password, + final int maxFrameSize, + final Container container, + final String remoteHostname, + SSLContext sslContext, + int channelMax) throws ConnectionException + { + _address = address; - final OutputStream outputStream = s.getOutputStream(); - ConnectionHandler.BytesSource src; + Principal principal = username == null ? null : new Principal() + { - if(_conn.requiresSASL()) - { - ConnectionHandler.FrameOutput<SaslFrameBody> saslOut = new ConnectionHandler.FrameOutput<SaslFrameBody>(_conn); - - src = new ConnectionHandler.SequentialBytesSource(new ConnectionHandler.HeaderBytesSource(_conn, (byte)'A', - (byte)'M', - (byte)'Q', - (byte)'P', - (byte)3, - (byte)1, - (byte)0, - (byte)0), - new ConnectionHandler.FrameToBytesSourceAdapter(saslOut,_conn.getDescribedTypeRegistry()), - new ConnectionHandler.HeaderBytesSource(_conn, (byte)'A', - (byte)'M', - (byte)'Q', - (byte)'P', - (byte)0, - (byte)1, - (byte)0, - (byte)0), - new ConnectionHandler.FrameToBytesSourceAdapter(out,_conn.getDescribedTypeRegistry()) - ); - - _conn.setSaslFrameOutput(saslOut); - } - else + public String getName() { - src = new ConnectionHandler.SequentialBytesSource(new ConnectionHandler.HeaderBytesSource(_conn,(byte)'A', - (byte)'M', - (byte)'Q', - (byte)'P', - (byte)0, - (byte)1, - (byte)0, - (byte)0), - new ConnectionHandler.FrameToBytesSourceAdapter(out,_conn.getDescribedTypeRegistry()) - ); + return username; } + }; + _conn = new ConnectionEndpoint(container, principal, password); + if(channelMax >= 0) + { + _conn.setChannelMax((short)channelMax); + } + _conn.setDesiredMaxFrameSize(UnsignedInteger.valueOf(maxFrameSize)); + _conn.setRemoteHostname(remoteHostname); + ConnectionHandler.FrameOutput<FrameBody> out = new ConnectionHandler.FrameOutput<FrameBody>(_conn); - ConnectionHandler.BytesOutputHandler outputHandler = new ConnectionHandler.BytesOutputHandler(outputStream, src, _conn, this); - Thread outputThread = new Thread(outputHandler); - outputThread.setDaemon(true); - outputThread.start(); - _conn.setFrameOutputHandler(out); + ConnectionHandler.BytesSource src; + if(_conn.requiresSASL()) + { + ConnectionHandler.FrameOutput<SaslFrameBody> saslOut = new ConnectionHandler.FrameOutput<SaslFrameBody>(_conn); + + src = new ConnectionHandler.SequentialBytesSource(new ConnectionHandler.HeaderBytesSource(_conn, (byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)3, + (byte)1, + (byte)0, + (byte)0), + new ConnectionHandler.FrameToBytesSourceAdapter(saslOut,_conn.getDescribedTypeRegistry()), + new ConnectionHandler.HeaderBytesSource(_conn, (byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)0, + (byte)1, + (byte)0, + (byte)0), + new ConnectionHandler.FrameToBytesSourceAdapter(out,_conn.getDescribedTypeRegistry()) + ); + + _conn.setSaslFrameOutput(saslOut); + } + else + { + src = new ConnectionHandler.SequentialBytesSource(new ConnectionHandler.HeaderBytesSource(_conn,(byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)0, + (byte)1, + (byte)0, + (byte)0), + new ConnectionHandler.FrameToBytesSourceAdapter(out,_conn.getDescribedTypeRegistry()) + ); + } + TransportProvider transportProvider = getTransportProvider(protocol); - final ConnectionHandler handler = new ConnectionHandler(_conn); - final InputStream inputStream = s.getInputStream(); + transportProvider.connect(_conn,address,port, sslContext, this); - Thread inputThread = new Thread(new Runnable() - { - public void run() - { - try - { - doRead(handler, inputStream); - } - finally - { - if(_conn.closedForInput() && _conn.closedForOutput()) - { - try - { - synchronized (outputStream) - { - s.close(); - } - } - catch (IOException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - } - } - }); + _conn.open(); - inputThread.setDaemon(true); - inputThread.start(); + } - _conn.open(); + private TransportProvider getTransportProvider(final String protocol) throws ConnectionException + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + ServiceLoader<TransportProviderFactory> providerFactories = ServiceLoader.load(TransportProviderFactory.class, classLoader); - } - catch (IOException e) + for(TransportProviderFactory tpf : providerFactories) { - throw new ConnectionException(e); + if(tpf.getSupportedTransports().contains(protocol)) + { + return tpf.getProvider(protocol); + } } - + throw new ConnectionException("Unknown protocol: " + protocol); } private Connection(ConnectionEndpoint endpoint) @@ -298,45 +284,6 @@ public class Connection implements SocketExceptionHandler } - private void doRead(final AMQPTransport transport, final InputStream inputStream) - { - byte[] buf = new byte[2<<15]; - ByteBuffer bbuf = ByteBuffer.wrap(buf); - final Object lock = new Object(); - transport.setInputStateChangeListener(new StateChangeListener(){ - - public void onStateChange(final boolean active) - { - synchronized(lock) - { - lock.notifyAll(); - } - } - }); - - try - { - int read; - while((read = inputStream.read(buf)) != -1) - { - bbuf.position(0); - bbuf.limit(read); - - while(bbuf.hasRemaining() && transport.isOpenForInput()) - { - transport.processBytes(bbuf); - } - - - } - } - catch (IOException e) - { - e.printStackTrace(); - } - - } - public Session createSession() throws ConnectionException { checkNotClosed(); @@ -357,84 +304,47 @@ public class Connection implements SocketExceptionHandler return _conn; } - public void awaitOpen() + public void awaitOpen() throws TimeoutException, InterruptedException { - synchronized(getEndpoint().getLock()) + getEndpoint().waitUntil(new Predicate() { - while(!getEndpoint().isOpen() && !getEndpoint().isClosed()) + @Override + public boolean isSatisfied() { - try - { - getEndpoint().getLock().wait(); - } - catch (InterruptedException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } + return getEndpoint().isOpen() || getEndpoint().isClosed(); } - } + }); } - private void doRead(final ConnectionHandler handler, final InputStream inputStream) + public void close() throws ConnectionErrorException { - byte[] buf = new byte[2<<15]; - + _conn.close(); try { - int read; - boolean done = false; - while(!handler.isDone() && (read = inputStream.read(buf)) != -1) + _conn.waitUntil(new Predicate() { - ByteBuffer bbuf = ByteBuffer.wrap(buf, 0, read); - Binary b = new Binary(buf,0,read); - - if(RAW_LOGGER.isLoggable(Level.FINE)) - { - RAW_LOGGER.fine("RECV [" + _conn.getRemoteAddress() + "] : " + b.toString()); - } - while(bbuf.hasRemaining() && !handler.isDone()) + @Override + public boolean isSatisfied() { - handler.parse(bbuf); + return _conn.closedForInput(); } - - - } - if(!handler.isDone()) - { - _conn.inputClosed(); - if(_conn.getConnectionEventListener() != null) - { - _conn.getConnectionEventListener().closeReceived(); - } - } + }); } - catch (IOException e) + catch (InterruptedException e) { - _conn.inputClosed(); - e.printStackTrace(); + throw new ConnectionErrorException(AmqpError.INTERNAL_ERROR, "Interrupted while waiting for connection closure"); } - } - - public void close() - { - _conn.close(); - - synchronized (_conn.getLock()) + catch (TimeoutException e) { - while(!_conn.closedForInput()) - { - try - { - _conn.getLock().wait(); - } - catch (InterruptedException e) - { - - } - } + throw new ConnectionErrorException(AmqpError.INTERNAL_ERROR, "Timed out while waiting for connection closure"); } + if(_conn.getRemoteError() != null) + { + throw new ConnectionErrorException(_conn.getRemoteError()); + } + } /** @@ -458,7 +368,7 @@ public class Connection implements SocketExceptionHandler } @Override - public void processSocketException(Exception exception) + public void handleException(Exception exception) { Error socketError = new Error(); socketError.setDescription(exception.getClass() + ": " + exception.getMessage()); diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ConnectionErrorException.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ConnectionErrorException.java index baf3de8991..302060776a 100644 --- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ConnectionErrorException.java +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/ConnectionErrorException.java @@ -20,15 +20,21 @@ */ package org.apache.qpid.amqp_1_0.client; +import org.apache.qpid.amqp_1_0.type.ErrorCondition; import org.apache.qpid.amqp_1_0.type.transport.Error; public class ConnectionErrorException extends ConnectionException { protected final Error _remoteError; + public ConnectionErrorException(ErrorCondition condition,final String description) + { + this(new Error(condition, description)); + } + public ConnectionErrorException(Error remoteError) { - super(); + super(remoteError.getDescription()); _remoteError = remoteError; } diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java index 5175d1d847..d76899a88b 100644 --- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Receiver.java @@ -23,6 +23,7 @@ package org.apache.qpid.amqp_1_0.client; import org.apache.qpid.amqp_1_0.messaging.SectionDecoder; import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler; import org.apache.qpid.amqp_1_0.transport.LinkEndpoint; +import org.apache.qpid.amqp_1_0.transport.Predicate; import org.apache.qpid.amqp_1_0.transport.ReceivingLinkEndpoint; import org.apache.qpid.amqp_1_0.transport.ReceivingLinkListener; @@ -38,6 +39,7 @@ import org.apache.qpid.amqp_1_0.type.transport.Error; import java.nio.ByteBuffer; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.TimeoutException; public class Receiver implements DeliveryStateHandler { @@ -137,36 +139,47 @@ public class Receiver implements DeliveryStateHandler _endpoint.setLocalUnsettled(unsettled); _endpoint.attach(); - synchronized(_endpoint.getLock()) + try { - while(!_endpoint.isAttached() && !_endpoint.isDetached()) + _endpoint.waitUntil(new Predicate() { - try - { - _endpoint.getLock().wait(); - } - catch (InterruptedException e) + + @Override + public boolean isSatisfied() { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + return _endpoint.isAttached() || _endpoint.isDetached(); } - } + }); + } + catch (TimeoutException e) + { + throw new ConnectionErrorException(AmqpError.INTERNAL_ERROR,"Timeout waiting for attach"); + } + catch (InterruptedException e) + { + throw new ConnectionErrorException(AmqpError.INTERNAL_ERROR,"Interrupted while waiting for attach"); } if(_endpoint.getSource() == null) { - synchronized(_endpoint.getLock()) + try { - while(!_endpoint.isDetached()) + _endpoint.waitUntil(new Predicate() { - try - { - _endpoint.getLock().wait(); - } - catch (InterruptedException e) + @Override + public boolean isSatisfied() { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + return _endpoint.isDetached(); } - } + }); + } + catch (TimeoutException e) + { + throw new ConnectionErrorException(AmqpError.INTERNAL_ERROR,"Timeout waiting for detach following failed attach"); + } + catch (InterruptedException e) + { + throw new ConnectionErrorException(AmqpError.INTERNAL_ERROR,"Interrupted whil waiting for detach following failed attach"); } throw new ConnectionErrorException(getError()); } diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SSLUtil.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SSLUtil.java new file mode 100644 index 0000000000..70e5d08f15 --- /dev/null +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/SSLUtil.java @@ -0,0 +1,215 @@ +/* + * + * 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.amqp_1_0.client; + +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509ExtendedKeyManager; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.Socket; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.Principal; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; + +public class SSLUtil +{ + public static final String TRANSPORT_LAYER_SECURITY_CODE = "TLS"; + + public static SSLContext buildSslContext(final String certAlias, + final String keyStorePath, + final String keyStoreType, + final String keyStorePassword, + final String keyManagerFactoryAlgorithm, + final String trustStorePath, + final String trustStorePassword, + final String trustStoreType, + final String trustManagerFactoryAlgorithm) throws GeneralSecurityException, IOException + { + + final SSLContext sslContext = SSLContext + .getInstance(TRANSPORT_LAYER_SECURITY_CODE); + + final TrustManager[] trustManagers; + final KeyManager[] keyManagers; + + if (trustStorePath != null) + { + final KeyStore ts = getInitializedKeyStore(trustStorePath, trustStorePassword, trustStoreType); + final TrustManagerFactory tmf = TrustManagerFactory.getInstance(trustManagerFactoryAlgorithm); + + tmf.init(ts); + + trustManagers = tmf.getTrustManagers(); + } + else + { + trustManagers = null; + } + + if (keyStorePath != null) + { + if (certAlias != null) + { + keyManagers = new KeyManager[] { new QpidClientX509KeyManager( + certAlias, keyStorePath, keyStoreType, keyStorePassword, + keyManagerFactoryAlgorithm) }; + } + else + { + final KeyStore ks = SSLUtil.getInitializedKeyStore(keyStorePath, keyStorePassword, keyStoreType); + + char[] keyStoreCharPassword = keyStorePassword == null ? null : keyStorePassword.toCharArray(); + // Set up key manager factory to use our key store + final KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryAlgorithm); + kmf.init(ks, keyStoreCharPassword); + keyManagers = kmf.getKeyManagers(); + } + } + else + { + keyManagers = null; + } + + + sslContext.init(keyManagers, trustManagers, null); + + return sslContext; + } + + public static X509Certificate[] getClientCertificates(final String alias, + final String keyStorePath, + final String keyStorePassword, + final String keyStoreType, + final String keyManagerFactoryAlgorithm) + throws GeneralSecurityException, IOException + { + return (new QpidClientX509KeyManager(alias,keyStorePath,keyStoreType,keyStorePassword,keyManagerFactoryAlgorithm)).getCertificateChain(alias); + } + + public static KeyStore getInitializedKeyStore(String storePath, String storePassword, String keyStoreType) throws GeneralSecurityException, IOException + { + KeyStore ks = KeyStore.getInstance(keyStoreType); + InputStream in = null; + try + { + File f = new File(storePath); + if (f.exists()) + { + in = new FileInputStream(f); + } + else + { + in = Thread.currentThread().getContextClassLoader().getResourceAsStream(storePath); + } + if (in == null && !"PKCS11".equalsIgnoreCase(keyStoreType)) // PKCS11 will not require an explicit path + { + throw new IOException("Unable to load keystore resource: " + storePath); + } + + char[] storeCharPassword = storePassword == null ? null : storePassword.toCharArray(); + + ks.load(in, storeCharPassword); + } + finally + { + if (in != null) + { + //noinspection EmptyCatchBlock + try + { + in.close(); + } + catch (IOException ignored) + { + } + } + } + return ks; + } + + public static class QpidClientX509KeyManager extends X509ExtendedKeyManager + { + + private X509ExtendedKeyManager delegate; + private String alias; + + public QpidClientX509KeyManager(String alias, String keyStorePath, String keyStoreType, + String keyStorePassword, String keyManagerFactoryAlgorithmName) throws + GeneralSecurityException, + IOException + { + this.alias = alias; + KeyStore ks = getInitializedKeyStore(keyStorePath, keyStorePassword, keyStoreType); + KeyManagerFactory kmf = KeyManagerFactory.getInstance(keyManagerFactoryAlgorithmName); + kmf.init(ks, keyStorePassword.toCharArray()); + this.delegate = (X509ExtendedKeyManager) kmf.getKeyManagers()[0]; + } + + public String chooseClientAlias(String[] keyType, Principal[] issuers, Socket socket) + { + return alias; + } + + public String chooseServerAlias(String keyType, Principal[] issuers, Socket socket) + { + return delegate.chooseServerAlias(keyType, issuers, socket); + } + + public X509Certificate[] getCertificateChain(String alias) + { + return delegate.getCertificateChain(alias); + } + + public String[] getClientAliases(String keyType, Principal[] issuers) + { + return new String[]{alias}; + } + + public PrivateKey getPrivateKey(String alias) + { + return delegate.getPrivateKey(alias); + } + + public String[] getServerAliases(String keyType, Principal[] issuers) + { + return delegate.getServerAliases(keyType, issuers); + } + + public String chooseEngineClientAlias(String[] keyType, Principal[] issuers, SSLEngine engine) + { + return alias; + } + + public String chooseEngineServerAlias(String keyType, Principal[] issuers, SSLEngine engine) + { + return delegate.chooseEngineServerAlias(keyType, issuers, engine); + } + } +} diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Sender.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Sender.java index e891c5cbe7..1addad2235 100644 --- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Sender.java +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Sender.java @@ -24,6 +24,7 @@ import org.apache.qpid.amqp_1_0.codec.DescribedTypeConstructor; import org.apache.qpid.amqp_1_0.messaging.SectionEncoder; import org.apache.qpid.amqp_1_0.transport.DeliveryStateHandler; import org.apache.qpid.amqp_1_0.transport.LinkEndpoint; +import org.apache.qpid.amqp_1_0.transport.Predicate; import org.apache.qpid.amqp_1_0.transport.SendingLinkEndpoint; import org.apache.qpid.amqp_1_0.transport.SendingLinkListener; import org.apache.qpid.amqp_1_0.type.*; @@ -39,10 +40,15 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.TimeoutException; + import org.apache.qpid.amqp_1_0.type.transport.Error; public class Sender implements DeliveryStateHandler { + private static final long UNSETTLED_MESSAGE_TIMEOUT_MULTIPLIER = 1000l; + private static final long DEFAULT_CREDIT_TIMEOUT = 30000l; + private SendingLinkEndpoint _endpoint; private int _id; private Session _session; @@ -150,17 +156,26 @@ public class Sender implements DeliveryStateHandler synchronized(_endpoint.getLock()) { - while(!(_endpoint.isAttached() || _endpoint.isDetached())) + try { - try - { - _endpoint.getLock().wait(); - } - catch (InterruptedException e) - { - throw new SenderCreationException(e); - } + _endpoint.waitUntil(new Predicate() + { + @Override + public boolean isSatisfied() + { + return _endpoint.isAttached() || _endpoint.isDetached(); + } + }); + } + catch (TimeoutException e) + { + throw new SenderCreationException(e); } + catch (InterruptedException e) + { + throw new SenderCreationException(e); + } + if (session.getEndpoint().isEnded()) { throw new SenderCreationException("Session is closed while creating link, target: " + target.getAddress()); @@ -225,22 +240,22 @@ public class Sender implements DeliveryStateHandler return _endpoint.getTarget(); } - public void send(Message message) throws LinkDetachedException + public void send(Message message) throws LinkDetachedException, TimeoutException { send(message, null, null); } - public void send(Message message, final OutcomeAction action) throws LinkDetachedException + public void send(Message message, final OutcomeAction action) throws LinkDetachedException, TimeoutException { send(message, null, action); } - public void send(Message message, final Transaction txn) throws LinkDetachedException + public void send(Message message, final Transaction txn) throws LinkDetachedException, TimeoutException { send(message, txn, null); } - public void send(Message message, final Transaction txn, OutcomeAction action) throws LinkDetachedException + public void send(Message message, final Transaction txn, OutcomeAction action) throws LinkDetachedException, TimeoutException { List<Section> sections = message.getPayload(); @@ -290,19 +305,26 @@ public class Sender implements DeliveryStateHandler xfr.setSettled(message.getSettled() || _endpoint.getSendingSettlementMode() == SenderSettleMode.SETTLED); } final Object lock = _endpoint.getLock(); + synchronized(lock) { - while(!_endpoint.hasCreditToSend() && !_endpoint.isDetached()) + + try { - try - { - lock.wait(); - } - catch (InterruptedException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } + _endpoint.waitUntil(new Predicate() + { + @Override + public boolean isSatisfied() + { + return _endpoint.hasCreditToSend() || _endpoint.isDetached(); + } + }, getCreditTimeout()); } + catch (InterruptedException e) + { + throw new TimeoutException("Interrupted while waiting for credit"); + } + if(_endpoint.isDetached()) { throw new LinkDetachedException(_error); @@ -312,27 +334,24 @@ public class Sender implements DeliveryStateHandler _outcomeActions.put(message.getDeliveryTag(), action); } _endpoint.transfer(xfr); - //TODO - rationalise sending of flows - // _endpoint.sendFlow(); } if(_windowSize != 0) { - synchronized(lock) + try { - - - while(_endpoint.getUnsettledCount() >= _windowSize) - { - try - { - lock.wait(); - } - catch (InterruptedException e) - { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } + _endpoint.waitUntil(new Predicate() + { + @Override + public boolean isSatisfied() + { + return _endpoint.getUnsettledCount() < _windowSize; + } + }, getUnsettledTimeout()); + } + catch (InterruptedException e) + { + throw new TimeoutException("Interrupted while waiting for the window to expand to allow sending"); } } @@ -340,48 +359,80 @@ public class Sender implements DeliveryStateHandler } + private long getCreditTimeout() + { + return _endpoint.getSyncTimeout() < DEFAULT_CREDIT_TIMEOUT ? DEFAULT_CREDIT_TIMEOUT : _endpoint.getSyncTimeout(); + } + public void close() throws SenderClosingException { + boolean unsettledDeliveries = false; if(_windowSize != 0) { - synchronized(_endpoint.getLock()) - { - + long timeout = getUnsettledTimeout(); - while(_endpoint.getUnsettledCount() > 0) + try + { + _endpoint.waitUntil(new Predicate() { - try - { - _endpoint.getLock().wait(); - } - catch (InterruptedException e) + @Override + public boolean isSatisfied() { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + return _endpoint.getUnsettledCount() == 0; } - } + }, timeout); + } + catch (InterruptedException e) + { + unsettledDeliveries = true; + } + catch (TimeoutException e) + { + unsettledDeliveries = true; } } _session.removeSender(this); _endpoint.setSource(null); - _endpoint.detach(); + _endpoint.close(); _closed = true; - synchronized(_endpoint.getLock()) + try { - while(!_endpoint.isDetached()) + _endpoint.waitUntil(new Predicate() { - try - { - _endpoint.getLock().wait(); - } - catch (InterruptedException e) + @Override + public boolean isSatisfied() { - throw new SenderClosingException(e); + return _endpoint.isDetached(); } - } + }); + } + catch (TimeoutException e) + { + throw new SenderClosingException("Timed out attempting to detach link", e); } + catch (InterruptedException e) + { + throw new SenderClosingException("Interrupted while attempting to detach link", e); + } + if(unsettledDeliveries && _endpoint.getUnsettledCount() > 0) + { + throw new SenderClosingException("Some messages may not have been received by the recipient"); + } + } + + private long getUnsettledTimeout() + { + long timeout = _endpoint.getSyncTimeout(); + + // give a generous timeout where there are unsettled messages + if(timeout < _endpoint.getUnsettledCount() * UNSETTLED_MESSAGE_TIMEOUT_MULTIPLIER) + { + timeout = _endpoint.getUnsettledCount() * UNSETTLED_MESSAGE_TIMEOUT_MULTIPLIER; + } + return timeout; } public boolean isClosed() @@ -468,10 +519,20 @@ public class Sender implements DeliveryStateHandler public class SenderClosingException extends Exception { + public SenderClosingException(final String message, final Throwable cause) + { + super(message, cause); + } + public SenderClosingException(Throwable e) { super(e); } + + public SenderClosingException(final String message) + { + super(message); + } } public static interface OutcomeAction diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProviderFactory.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProviderFactory.java new file mode 100644 index 0000000000..2327a3860a --- /dev/null +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProviderFactory.java @@ -0,0 +1,39 @@ +/* + * + * 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.amqp_1_0.client; + +import java.util.Arrays; +import java.util.Collection; + +public class TCPTransportProviderFactory implements TransportProviderFactory +{ + @Override + public Collection<String> getSupportedTransports() + { + return Arrays.asList("amqp","amqps"); + } + + @Override + public TransportProvider getProvider(final String transport) + { + return new TCPTransportProvier(transport); + } +} diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java new file mode 100644 index 0000000000..6cc749d11d --- /dev/null +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TCPTransportProvier.java @@ -0,0 +1,203 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.framing.ConnectionHandler; +import org.apache.qpid.amqp_1_0.framing.ExceptionHandler; +import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; +import org.apache.qpid.amqp_1_0.type.FrameBody; +import org.apache.qpid.amqp_1_0.type.SaslFrameBody; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Socket; +import java.nio.ByteBuffer; + +class TCPTransportProvier implements TransportProvider +{ + private final String _transport; + + public TCPTransportProvier(final String transport) + { + _transport = transport; + } + + @Override + public void connect(final ConnectionEndpoint conn, + final String address, + final int port, + final SSLContext sslContext, + final ExceptionHandler exceptionHandler) throws ConnectionException + { + try + { + final Socket s; + if(sslContext != null) + { + final SSLSocketFactory socketFactory = sslContext.getSocketFactory(); + + SSLSocket sslSocket = (SSLSocket) socketFactory.createSocket(address, port); + + s=sslSocket; + } + else + { + s = new Socket(address, port); + } + + conn.setRemoteAddress(s.getRemoteSocketAddress()); + + + + ConnectionHandler.FrameOutput<FrameBody> out = new ConnectionHandler.FrameOutput<FrameBody>(conn); + + ConnectionHandler.BytesSource src; + + if(conn.requiresSASL()) + { + ConnectionHandler.FrameOutput<SaslFrameBody> saslOut = new ConnectionHandler.FrameOutput<SaslFrameBody>(conn); + + src = new ConnectionHandler.SequentialBytesSource(new ConnectionHandler.HeaderBytesSource(conn, (byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)3, + (byte)1, + (byte)0, + (byte)0), + new ConnectionHandler.FrameToBytesSourceAdapter(saslOut,conn.getDescribedTypeRegistry()), + new ConnectionHandler.HeaderBytesSource(conn, (byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)0, + (byte)1, + (byte)0, + (byte)0), + new ConnectionHandler.FrameToBytesSourceAdapter(out,conn.getDescribedTypeRegistry()) + ); + + conn.setSaslFrameOutput(saslOut); + } + else + { + src = new ConnectionHandler.SequentialBytesSource(new ConnectionHandler.HeaderBytesSource(conn,(byte)'A', + (byte)'M', + (byte)'Q', + (byte)'P', + (byte)0, + (byte)1, + (byte)0, + (byte)0), + new ConnectionHandler.FrameToBytesSourceAdapter(out,conn.getDescribedTypeRegistry()) + ); + } + + + final OutputStream outputStream = s.getOutputStream(); + ConnectionHandler.BytesOutputHandler outputHandler = + new ConnectionHandler.BytesOutputHandler(outputStream, src, conn, exceptionHandler); + Thread outputThread = new Thread(outputHandler); + outputThread.setDaemon(true); + outputThread.start(); + conn.setFrameOutputHandler(out); + + + final ConnectionHandler handler = new ConnectionHandler(conn); + final InputStream inputStream = s.getInputStream(); + + Thread inputThread = new Thread(new Runnable() + { + + public void run() + { + try + { + doRead(conn, handler, inputStream); + } + finally + { + if(conn.closedForInput() && conn.closedForOutput()) + { + try + { + synchronized (outputStream) + { + s.close(); + } + } + catch (IOException e) + { + e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. + } + } + } + } + }); + + inputThread.setDaemon(true); + inputThread.start(); + + } + catch (IOException e) + { + throw new ConnectionException(e); + } + } + private void doRead(final ConnectionEndpoint conn, final ConnectionHandler handler, final InputStream inputStream) + { + byte[] buf = new byte[2<<15]; + + + try + { + int read; + boolean done = false; + while(!handler.isDone() && (read = inputStream.read(buf)) != -1) + { + ByteBuffer bbuf = ByteBuffer.wrap(buf, 0, read); + while(bbuf.hasRemaining() && !handler.isDone()) + { + handler.parse(bbuf); + } + + + } + if(!handler.isDone()) + { + conn.inputClosed(); + if(conn.getConnectionEventListener() != null) + { + conn.getConnectionEventListener().closeReceived(); + } + } + } + catch (IOException e) + { + conn.inputClosed(); + e.printStackTrace(); + } + } +} diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TransportProvider.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TransportProvider.java new file mode 100644 index 0000000000..2c11d6b6ef --- /dev/null +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TransportProvider.java @@ -0,0 +1,37 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import org.apache.qpid.amqp_1_0.framing.ConnectionHandler; +import org.apache.qpid.amqp_1_0.framing.ExceptionHandler; +import org.apache.qpid.amqp_1_0.transport.ConnectionEndpoint; +import org.apache.qpid.amqp_1_0.type.FrameBody; + +import javax.net.ssl.SSLContext; + +public interface TransportProvider +{ + void connect(ConnectionEndpoint conn, + String address, + int port, + SSLContext sslContext, + ExceptionHandler exceptionHandler) throws ConnectionException; +} diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TransportProviderFactory.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TransportProviderFactory.java new file mode 100644 index 0000000000..82999c5ccc --- /dev/null +++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/TransportProviderFactory.java @@ -0,0 +1,29 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.amqp_1_0.client; + +import java.util.Collection; + +public interface TransportProviderFactory +{ + Collection<String> getSupportedTransports(); + TransportProvider getProvider(String transport); +} diff --git a/qpid/java/amqp-1-0-client/src/main/resources/META-INF/services/org.apache.qpid.amqp_1_0.client.TransportProviderFactory b/qpid/java/amqp-1-0-client/src/main/resources/META-INF/services/org.apache.qpid.amqp_1_0.client.TransportProviderFactory new file mode 100644 index 0000000000..ffde030b30 --- /dev/null +++ b/qpid/java/amqp-1-0-client/src/main/resources/META-INF/services/org.apache.qpid.amqp_1_0.client.TransportProviderFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.amqp_1_0.client.TCPTransportProviderFactory
\ No newline at end of file diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SymbolTypeConstructor.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SymbolTypeConstructor.java index b846b16722..b96e1ab47b 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SymbolTypeConstructor.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/codec/SymbolTypeConstructor.java @@ -66,20 +66,7 @@ public class SymbolTypeConstructor extends VariableWidthTypeConstructor if(symbolVal == null) { ByteBuffer dup = in.duplicate(); - try - { - dup.limit(in.position()+size); - } - catch (IllegalArgumentException e) - { - System.err.println("in.position(): " + in.position()); - System.err.println("size: " + size); - System.err.println("dup.position(): " + dup.position()); - System.err.println("dup.capacity(): " + dup.capacity()); - System.err.println("dup.limit(): " + dup.limit()); - throw e; - - } + dup.limit(in.position()+size); CharBuffer charBuf = ASCII.decode(dup); diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java index 119dd6bf3a..54a4f22d48 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ConnectionHandler.java @@ -65,6 +65,12 @@ public class ConnectionHandler public boolean parse(ByteBuffer in) { + if(RAW_LOGGER.isLoggable(Level.FINE)) + { + Binary b = new Binary(in.array(),in.arrayOffset()+in.position(),in.remaining()); + RAW_LOGGER.fine("RECV [" + _connection.getRemoteAddress() + "] : " + b.toString()); + } + while(in.hasRemaining() && !isDone()) { _delegate = _delegate.parse(in); @@ -376,6 +382,47 @@ public class ConnectionHandler } + public static class SequentialFrameSource implements FrameSource + { + private Queue<FrameSource> _sources = new LinkedList<FrameSource>(); + + public SequentialFrameSource(FrameSource... sources) + { + _sources.addAll(Arrays.asList(sources)); + } + + public synchronized void addSource(FrameSource source) + { + _sources.add(source); + } + + @Override + public synchronized AMQFrame getNextFrame(final boolean wait) + { + FrameSource src = _sources.peek(); + while (src != null && src.closed()) + { + _sources.poll(); + src = _sources.peek(); + } + + if(src != null) + { + return src.getNextFrame(wait); + } + else + { + return null; + } + } + + public boolean closed() + { + return _sources.isEmpty(); + } + } + + public static class BytesOutputHandler implements Runnable, BytesProcessor { @@ -383,28 +430,28 @@ public class ConnectionHandler private BytesSource _bytesSource; private boolean _closed; private ConnectionEndpoint _conn; - private SocketExceptionHandler _exceptionHandler; - - public BytesOutputHandler(OutputStream outputStream, BytesSource source, ConnectionEndpoint conn, SocketExceptionHandler exceptionHandler) - { - _outputStream = outputStream; - _bytesSource = source; - _conn = conn; - _exceptionHandler = exceptionHandler; - } + private ExceptionHandler _exceptionHandler; - public void run() - { + public BytesOutputHandler(OutputStream outputStream, BytesSource source, ConnectionEndpoint conn, ExceptionHandler exceptionHandler) + { + _outputStream = outputStream; + _bytesSource = source; + _conn = conn; + _exceptionHandler = exceptionHandler; + } - final BytesSource bytesSource = _bytesSource; + public void run() + { - while(!(_closed || bytesSource.closed())) - { - _bytesSource.getBytes(this, true); - } + final BytesSource bytesSource = _bytesSource; + while(!(_closed || bytesSource.closed())) + { + _bytesSource.getBytes(this, true); } + } + public void processBytes(final ByteBuffer buf) { try @@ -423,7 +470,7 @@ public class ConnectionHandler catch (IOException e) { _closed = true; - _exceptionHandler.processSocketException(e); + _exceptionHandler.handleException(e); } } } diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/SocketExceptionHandler.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ExceptionHandler.java index 540aee0f8d..3adf3c0b18 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/SocketExceptionHandler.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/ExceptionHandler.java @@ -23,9 +23,9 @@ package org.apache.qpid.amqp_1_0.framing; /** * Callback interface for processing socket exceptions. */ -public interface SocketExceptionHandler +public interface ExceptionHandler { - public void processSocketException(Exception exception); + public void handleException(Exception exception); } diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java index 83cb36246a..bc16ba14e0 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/framing/FrameHandler.java @@ -127,9 +127,9 @@ public class FrameHandler implements ProtocolHandler break; } - else if(size > _connection.getMaxFrameSize()) + else if(size > _connection.getDesiredMaxFrameSize().intValue()) { - frameParsingError = createFramingError("specified frame size %d larger than maximum frame header size %d", size, _connection.getMaxFrameSize()); + frameParsingError = createFramingError("specified frame size %d larger than maximum frame header size %d", size, _connection.getDesiredMaxFrameSize().intValue()); state = State.ERROR; break; } diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java index a3c4ad7b5a..9c93c1f0a5 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/ConnectionEndpoint.java @@ -40,10 +40,8 @@ import org.apache.qpid.amqp_1_0.type.transport.*; import org.apache.qpid.amqp_1_0.type.transport.Error; import org.apache.qpid.amqp_1_0.type.codec.AMQPDescribedTypeRegistry; -import javax.security.sasl.Sasl; import javax.security.sasl.SaslException; import javax.security.sasl.SaslServer; -import javax.security.sasl.SaslServerFactory; import java.net.SocketAddress; import java.nio.ByteBuffer; @@ -51,7 +49,7 @@ import java.nio.charset.Charset; import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; -import java.util.Enumeration; +import java.util.concurrent.TimeoutException; import java.util.logging.Level; import java.util.logging.Logger; @@ -71,6 +69,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour private static final short DEFAULT_CHANNEL_MAX = Integer.getInteger("amqp.channel_max", 255).shortValue(); private static final int DEFAULT_MAX_FRAME = Integer.getInteger("amqp.max_frame_size", 1 << 15); + private static final long DEFAULT_SYNC_TIMEOUT = Long.getLong("amqp.connection_sync_timeout",5000l); private ConnectionState _state = ConnectionState.UNOPENED; @@ -104,7 +103,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour private UnsignedInteger _handleMax = UnsignedInteger.MAX_VALUE; private ConnectionEventListener _connectionEventListener = ConnectionEventListener.DEFAULT; private String _password; - private final boolean _requiresSASLClient; + private boolean _requiresSASLClient; private final boolean _requiresSASLServer; @@ -122,6 +121,7 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour private Error _remoteError; private Map _properties; + private long _syncTimeout = DEFAULT_SYNC_TIMEOUT; public ConnectionEndpoint(Container container, SaslServerProvider cbs) { @@ -140,6 +140,14 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour _requiresSASLServer = false; } + public void setPrincipal(Principal user) + { + if(_user == null) + { + _user = user; + _requiresSASLClient = user != null; + } + } public synchronized void open() { @@ -1054,4 +1062,42 @@ public class ConnectionEndpoint implements DescribedTypeConstructorRegistry.Sour { _channelMax = channelMax; } + + public long getSyncTimeout() + { + return _syncTimeout; + } + + public void setSyncTimeout(final long syncTimeout) + { + _syncTimeout = syncTimeout; + } + + public void waitUntil(Predicate predicate) throws InterruptedException, TimeoutException + { + waitUntil(predicate, _syncTimeout); + } + + public void waitUntil(Predicate predicate, long timeout) throws InterruptedException, TimeoutException + { + long endTime = System.currentTimeMillis() + timeout; + + synchronized(getLock()) + { + while(!predicate.isSatisfied()) + { + getLock().wait(timeout); + + if(!predicate.isSatisfied()) + { + timeout = endTime - System.currentTimeMillis(); + if(timeout <= 0l) + { + throw new TimeoutException(); + } + } + } + } + + } } diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/LinkEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/LinkEndpoint.java index 32fffd545a..301dd0695a 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/LinkEndpoint.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/LinkEndpoint.java @@ -28,6 +28,7 @@ import org.apache.qpid.amqp_1_0.type.transport.Error; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.TimeoutException; public abstract class LinkEndpoint<T extends LinkEventListener> { @@ -324,6 +325,23 @@ public abstract class LinkEndpoint<T extends LinkEventListener> return _session.getLock(); } + + public long getSyncTimeout() + { + return _session.getSyncTimeout(); + } + + public void waitUntil(Predicate predicate) throws TimeoutException, InterruptedException + { + _session.waitUntil(predicate); + } + + public void waitUntil(Predicate predicate, long timeout) throws TimeoutException, InterruptedException + { + _session.waitUntil(predicate, timeout); + } + + public void attach() { synchronized(getLock()) diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Predicate.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Predicate.java new file mode 100644 index 0000000000..3acd576527 --- /dev/null +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/Predicate.java @@ -0,0 +1,26 @@ +/* + * + * 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.amqp_1_0.transport; + +public interface Predicate +{ + boolean isSatisfied(); +} diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java index f7a3cd3800..c37c52c6ea 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/transport/SessionEndpoint.java @@ -35,6 +35,7 @@ import org.apache.qpid.amqp_1_0.type.transport.Error; import java.nio.ByteBuffer; import java.util.*; +import java.util.concurrent.TimeoutException; public class SessionEndpoint { @@ -579,19 +580,7 @@ public class SessionEndpoint if(payload != null && payloadSent < payload.remaining()) { payload = payload.duplicate(); -try -{ payload.position(payload.position()+payloadSent); -} -catch(IllegalArgumentException e) -{ - System.err.println("UNEXPECTED"); - System.err.println("Payload Position: " + payload.position()); - System.err.println("Payload Sent: " + payloadSent); - System.err.println("Payload Remaining: " + payload.remaining()); - throw e; - -} Transfer secondTransfer = new Transfer(); @@ -618,6 +607,23 @@ catch(IllegalArgumentException e) return _connection.getLock(); } + + public long getSyncTimeout() + { + return _connection.getSyncTimeout(); + } + + public void waitUntil(Predicate predicate) throws TimeoutException, InterruptedException + { + _connection.waitUntil(predicate); + } + + public void waitUntil(Predicate predicate, long timeout) throws TimeoutException, InterruptedException + { + _connection.waitUntil(predicate, timeout); + } + + public ReceivingLinkEndpoint createReceivingLinkEndpoint(final String name, String targetAddr, String sourceAddr, diff --git a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Error.java b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Error.java index 6e1af84cc9..11319f738b 100644 --- a/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Error.java +++ b/qpid/java/amqp-1-0-common/src/main/java/org/apache/qpid/amqp_1_0/type/transport/Error.java @@ -31,8 +31,7 @@ import java.util.Map; import org.apache.qpid.amqp_1_0.type.*; public class Error - { - +{ private ErrorCondition _condition; @@ -40,6 +39,16 @@ public class Error private Map _info; + public Error() + { + } + + public Error(final ErrorCondition condition, final String description) + { + _condition = condition; + _description = description; + } + public ErrorCondition getCondition() { return _condition; diff --git a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java index abe71fb78c..2816667fc6 100644 --- a/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java +++ b/qpid/java/bdbstore/src/main/java/org/apache/qpid/server/store/berkeleydb/BDBMessageStore.java @@ -36,6 +36,7 @@ import java.util.Map; import java.util.Random; import java.util.UUID; import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicBoolean; import org.apache.log4j.Logger; import org.apache.qpid.AMQStoreException; import org.apache.qpid.server.message.EnqueableMessage; @@ -84,6 +85,8 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore private static final String[] DATABASE_NAMES = new String[] { CONFIGURED_OBJECTS_DB_NAME, MESSAGE_META_DATA_DB_NAME, MESSAGE_CONTENT_DB_NAME, DELIVERY_DB_NAME, BRIDGEDB_NAME, LINKDB_NAME, XID_DB_NAME, CONFIG_VERSION_DB_NAME }; + private final AtomicBoolean _closed = new AtomicBoolean(false); + private EnvironmentFacade _environmentFacade; private final AtomicLong _messageId = new AtomicLong(0); @@ -282,16 +285,19 @@ public class BDBMessageStore implements MessageStore, DurableConfigurationStore @Override public void close() throws AMQStoreException { - _stateManager.attainState(State.CLOSING); - try - { - closeEnvironment(); - } - catch(DatabaseException e) - { - throw new AMQStoreException("Exception occured on message store close", e); + if (_closed.compareAndSet(false, true)) + { + _stateManager.attainState(State.CLOSING); + try + { + closeEnvironment(); + } + catch(DatabaseException e) + { + throw new AMQStoreException("Exception occured on message store close", e); + } + _stateManager.attainState(State.CLOSED); } - _stateManager.attainState(State.CLOSED); } private void closeEnvironment() diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html index ec5356e2a0..2a88832bdb 100644 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html +++ b/qpid/java/bdbstore/src/main/java/resources/virtualhost/bdb_ha/add.html @@ -1,3 +1,19 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> <table class="tableContainer-table tableContainer-table-horiz"> <tr> <td class="tableContainer-labelCell" style="width: 300px;"><strong>Path to store location*: </strong></td> diff --git a/qpid/java/bdbstore/src/main/java/resources/virtualhost/store/bdb/add.html b/qpid/java/bdbstore/src/main/java/resources/virtualhost/store/bdb/add.html index 2ed5b35c10..ead232d0b1 100644 --- a/qpid/java/bdbstore/src/main/java/resources/virtualhost/store/bdb/add.html +++ b/qpid/java/bdbstore/src/main/java/resources/virtualhost/store/bdb/add.html @@ -1,3 +1,19 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> <table class="tableContainer-table tableContainer-table-horiz"> <tr> <td class="tableContainer-labelCell" style="width: 300px;"><strong>Path to store location*: </strong></td> diff --git a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java index ef1b1cc42b..c190498a36 100644 --- a/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java +++ b/qpid/java/bdbstore/systests/src/main/java/org/apache/qpid/server/store/berkeleydb/HAClusterManagementTest.java @@ -215,12 +215,10 @@ public class HAClusterManagementTest extends QpidBrokerTestCase catch(RuntimeException rte) { //check cause was BDBs EnvironmentFailureException - boolean isExpectedException = rte.getMessage().contains(EnvironmentFailureException.class.getName()); - if (!isExpectedException) - { - rte.printStackTrace(); - } - assertTrue("Unexpected exception message:" + rte.getMessage(), isExpectedException); + assertTrue("Message '"+rte.getMessage()+"' does not contain '" + + EnvironmentFailureException.class.getName() + + "'.", + rte.getMessage().contains(EnvironmentFailureException.class.getName())); // PASS } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java index 7de0ebe1de..f180e4532c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/Broker.java @@ -29,8 +29,6 @@ import java.util.Set; import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.configuration.BrokerProperties; import org.apache.qpid.server.configuration.ConfigurationEntryStore; import org.apache.qpid.server.configuration.BrokerConfigurationStoreCreator; import org.apache.qpid.server.configuration.store.ManagementModeStoreHandler; @@ -125,6 +123,7 @@ public class Broker } catch(Exception e) { + LOGGER.fatal("Exception during startup", e); try { _applicationRegistry.close(); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java index c30ebe17be..ac2fa5e60d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java @@ -25,7 +25,6 @@ import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java index aed2ddb8cf..5aea60f1b5 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchange.java @@ -31,7 +31,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.logging.LogSubject; import org.apache.qpid.server.logging.actors.CurrentActor; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java index 612fa855a4..994f6730e0 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DefaultExchangeFactory.java @@ -26,7 +26,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.AMQUnknownExchangeType; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.plugin.QpidServiceLoader; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java index 1e022c994e..4571ec09af 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchange.java @@ -26,11 +26,7 @@ import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.apache.qpid.AMQInvalidArgumentException; -import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.filter.JMSSelectorFilter; import org.apache.qpid.server.filter.MessageFilter; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.plugin.ExchangeType; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java index d61d10155e..99c913ad07 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/DirectExchangeType.java @@ -24,7 +24,6 @@ import java.util.UUID; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java index f364691666..f4a3fd940d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeFactory.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.plugin.ExchangeType; import java.util.Collection; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java index 53ee7de661..7b4dbf925b 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/ExchangeRegistry.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.exchange; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import java.util.Collection; import java.util.UUID; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java index cd830d69a9..6665fe5a9d 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java @@ -22,17 +22,12 @@ package org.apache.qpid.server.exchange; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.List; import java.util.Map; -import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicReference; import org.apache.log4j.Logger; import org.apache.qpid.AMQInvalidArgumentException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.filter.MessageFilter; import org.apache.qpid.server.message.InboundMessage; @@ -41,7 +36,6 @@ import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.BaseQueue; import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; public class FanoutExchange extends AbstractExchange { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java index ac864df02c..9fc0d1f071 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FanoutExchangeType.java @@ -24,7 +24,6 @@ import java.util.UUID; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java index e78516cf69..9968ae6f5e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/FilterSupport.java @@ -30,7 +30,6 @@ import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.filter.SelectorParsingException; import org.apache.qpid.filter.selector.ParseException; import org.apache.qpid.filter.selector.TokenMgrError; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.filter.JMSSelectorFilter; import org.apache.qpid.server.filter.MessageFilter; import org.apache.qpid.server.message.InboundMessage; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java index eb4a84a5b9..474c0862ad 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersBinding.java @@ -23,8 +23,6 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; import org.apache.qpid.AMQInvalidArgumentException; -import org.apache.qpid.framing.AMQTypedValue; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.filter.MessageFilter; import org.apache.qpid.server.message.AMQMessageHeader; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java index 41dd7e010c..977ac7249e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java @@ -22,10 +22,7 @@ package org.apache.qpid.server.exchange; import org.apache.log4j.Logger; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; -import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.queue.AMQQueue; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java index 42d04f5a97..097a7bd5bd 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/HeadersExchangeType.java @@ -24,7 +24,6 @@ import java.util.UUID; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java index 6b8b84f5dd..7085d72390 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchange.java @@ -29,8 +29,6 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.apache.log4j.Logger; import org.apache.qpid.AMQInvalidArgumentException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.topic.TopicExchangeResult; import org.apache.qpid.server.exchange.topic.TopicMatcherResult; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java index 3bbae700be..c1f42017bf 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/exchange/TopicExchangeType.java @@ -24,7 +24,6 @@ import java.util.UUID; import org.apache.qpid.AMQException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java index 07049a6c97..dda3973ed8 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/filter/FilterManagerFactory.java @@ -28,7 +28,6 @@ import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.filter.SelectorParsingException; import org.apache.qpid.filter.selector.ParseException; import org.apache.qpid.filter.selector.TokenMgrError; -import org.apache.qpid.framing.FieldTable; import java.util.Map; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java index 3139850892..31d40c7c3e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Connection.java @@ -79,6 +79,7 @@ public interface Connection extends ConfiguredObject public static final String REMOTE_PROCESS_PID = "remoteProcessPid"; public static final String SESSION_COUNT_LIMIT = "sessionCountLimit"; public static final String TRANSPORT = "transport"; + /** Name of port associated with the connection */ public static final String PORT = "port"; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Transport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Transport.java index ae6e5ac43a..7338e5046a 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Transport.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/Transport.java @@ -25,7 +25,10 @@ import java.util.EnumSet; public enum Transport { TCP, - SSL; + SSL, + WS, + WSS, + SCTP; public static Transport valueOfObject(Object transportObject) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java index a4ce95e5aa..c255ce2f4a 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/AmqpPortAdapter.java @@ -19,12 +19,8 @@ */ package org.apache.qpid.server.model.adapter; -import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; - -import java.net.InetSocketAddress; import java.security.GeneralSecurityException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.Map; @@ -42,21 +38,21 @@ import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.messages.BrokerMessages; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.KeyStore; -import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.model.TrustStore; import org.apache.qpid.server.configuration.updater.TaskExecutor; +import org.apache.qpid.server.plugin.QpidServiceLoader; +import org.apache.qpid.server.plugin.TransportProviderFactory; import org.apache.qpid.server.protocol.AmqpProtocolVersion; -import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; -import org.apache.qpid.transport.NetworkTransportConfiguration; -import org.apache.qpid.transport.network.IncomingNetworkTransport; +import org.apache.qpid.server.transport.AcceptingTransport; +import org.apache.qpid.server.transport.TransportProvider; import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; public class AmqpPortAdapter extends PortAdapter { private final Broker _broker; - private IncomingNetworkTransport _transport; + private AcceptingTransport _transport; public AmqpPortAdapter(UUID id, Broker broker, Map<String, Object> attributes, Map<String, Object> defaultAttributes, TaskExecutor taskExecutor) { @@ -70,42 +66,36 @@ public class AmqpPortAdapter extends PortAdapter Collection<Transport> transports = getTransports(); Set<AmqpProtocolVersion> supported = convertFromModelProtocolsToAmqp(getProtocols()); - SSLContext sslContext = null; - if (transports.contains(Transport.SSL)) + TransportProvider transportProvider = null; + final HashSet<Transport> transportSet = new HashSet<Transport>(transports); + for(TransportProviderFactory tpf : (new QpidServiceLoader<TransportProviderFactory>()).instancesOf(TransportProviderFactory.class)) { - sslContext = createSslContext(); + if(tpf.getSupportedTransports().contains(transports)) + { + transportProvider = tpf.getTransportProvider(transportSet); + } } - AmqpProtocolVersion defaultSupportedProtocolReply = getDefaultAmqpSupportedReply(); - - String bindingAddress = (String) getAttribute(Port.BINDING_ADDRESS); - if (WILDCARD_ADDRESS.equals(bindingAddress)) + if(transportProvider == null) { - bindingAddress = null; + throw new IllegalConfigurationException("No transport providers found which can satisfy the requirement to support the transports: " + transports); } - Integer port = (Integer) getAttribute(Port.PORT); - InetSocketAddress bindingSocketAddress = null; - if ( bindingAddress == null ) - { - bindingSocketAddress = new InetSocketAddress(port); - } - else + + SSLContext sslContext = null; + if (transports.contains(Transport.SSL) || transports.contains(Transport.WSS)) { - bindingSocketAddress = new InetSocketAddress(bindingAddress, port); + sslContext = createSslContext(); } - final NetworkTransportConfiguration settings = new ServerNetworkTransportConfiguration( - bindingSocketAddress, (Boolean)getAttribute(TCP_NO_DELAY), - (Integer)getAttribute(SEND_BUFFER_SIZE), (Integer)getAttribute(RECEIVE_BUFFER_SIZE), - (Boolean)getAttribute(NEED_CLIENT_AUTH), (Boolean)getAttribute(WANT_CLIENT_AUTH)); + AmqpProtocolVersion defaultSupportedProtocolReply = getDefaultAmqpSupportedReply(); - _transport = org.apache.qpid.transport.network.Transport.getIncomingTransportInstance(); - final MultiVersionProtocolEngineFactory protocolEngineFactory = new MultiVersionProtocolEngineFactory( - _broker, transports.contains(Transport.TCP) ? sslContext : null, - settings.wantClientAuth(), settings.needClientAuth(), - supported, defaultSupportedProtocolReply, this, transports.contains(Transport.TCP) ? Transport.TCP : Transport.SSL); + _transport = transportProvider.createTransport(transportSet, + sslContext, + this, + supported, + defaultSupportedProtocolReply); - _transport.accept(settings, protocolEngineFactory, transports.contains(Transport.TCP) ? null : sslContext); + _transport.start(); for(Transport transport : getTransports()) { CurrentActor.get().message(BrokerMessages.LISTENING(String.valueOf(transport), getPort())); @@ -210,68 +200,4 @@ public class AmqpPortAdapter extends PortAdapter } return null; } - - class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration - { - private final InetSocketAddress _bindingSocketAddress; - private final Boolean _tcpNoDelay; - private final Integer _sendBufferSize; - private final Integer _receiveBufferSize; - private final boolean _needClientAuth; - private final boolean _wantClientAuth; - - public ServerNetworkTransportConfiguration( - InetSocketAddress bindingSocketAddress, boolean tcpNoDelay, - int sendBufferSize, int receiveBufferSize, - boolean needClientAuth, boolean wantClientAuth) - { - _bindingSocketAddress = bindingSocketAddress; - _tcpNoDelay = tcpNoDelay; - _sendBufferSize = sendBufferSize; - _receiveBufferSize = receiveBufferSize; - _needClientAuth = needClientAuth; - _wantClientAuth = wantClientAuth; - } - - @Override - public boolean wantClientAuth() - { - return _wantClientAuth; - } - - @Override - public boolean needClientAuth() - { - return _needClientAuth; - } - - @Override - public Boolean getTcpNoDelay() - { - return _tcpNoDelay; - } - - @Override - public Integer getSendBufferSize() - { - return _sendBufferSize; - } - - @Override - public Integer getReceiveBufferSize() - { - return _receiveBufferSize; - } - - @Override - public InetSocketAddress getAddress() - { - return _bindingSocketAddress; - } - }; - - public String toString() - { - return getName(); - } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java index e8bacb2712..dd5fc67b48 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/ConnectionAdapter.java @@ -35,6 +35,7 @@ import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.model.ConfiguredObject; import org.apache.qpid.server.model.Connection; import org.apache.qpid.server.model.LifetimePolicy; +import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Session; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.Statistics; @@ -226,7 +227,8 @@ final class ConnectionAdapter extends AbstractAdapter implements Connection } else if(name.equals(PORT)) { - return String.valueOf(_connection.getPort()); + Port port = _connection.getPort(); + return String.valueOf(port == null ? null : port.getName()); } return super.getAttribute(name); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java index 0547f961d0..3e7d03b5ac 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortAdapter.java @@ -556,4 +556,11 @@ public class PortAdapter extends AbstractAdapter implements Port return trustStores; } + + @Override + public String toString() + { + return getClass().getSimpleName() + " [id=" + getId() + ", name=" + getName() + ", port=" + getPort() + "]"; + } + } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java index 8dc446e5b2..25a8cc93ad 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/adapter/PortFactory.java @@ -111,7 +111,7 @@ public class PortFactory throw new IllegalConfigurationException("Can't create port which requests SSL client certificates but has no trust stores configured."); } - if(useClientAuth && !port.getTransports().contains(Transport.SSL)) + if(useClientAuth && !(port.getTransports().contains(Transport.SSL) || port.getTransports().contains(Transport.WSS))) { throw new IllegalConfigurationException("Can't create port which requests SSL client certificates but doesn't use SSL transport."); } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java index ab19fa196e..423b76ab8e 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/ExchangeType.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.plugin; import java.util.UUID; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/TransportProviderFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/TransportProviderFactory.java new file mode 100644 index 0000000000..81a6adc40e --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/plugin/TransportProviderFactory.java @@ -0,0 +1,35 @@ +/* + * + * 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.plugin; + +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.transport.TransportProvider; + +import java.util.Set; + +public interface TransportProviderFactory extends Pluggable +{ + Set<Set<Transport>> getSupportedTransports(); + + TransportProvider getTransportProvider(Set<Transport> transports); + + +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java index 47b578c4ef..01b220fd79 100755 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngine.java @@ -30,6 +30,8 @@ import java.util.Set; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLEngine; import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSocket; + import org.apache.log4j.Logger; import org.apache.qpid.protocol.ServerProtocolEngine; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -38,6 +40,7 @@ import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.model.Port; import org.apache.qpid.server.model.Transport; import org.apache.qpid.server.plugin.ProtocolEngineCreator; +import org.apache.qpid.transport.Binary; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.NetworkConnection; import org.apache.qpid.transport.network.security.SSLStatus; @@ -143,11 +146,6 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine private static final int MINIMUM_REQUIRED_HEADER_BYTES = 8; - public void setNetworkConnection(NetworkConnection networkConnection) - { - setNetworkConnection(networkConnection, networkConnection.getSender()); - } - public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender) { _network = network; @@ -274,9 +272,9 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine public void received(ByteBuffer msg) { - _lastReadTime = System.currentTimeMillis(); - ByteBuffer msgheader = msg.duplicate(); + ByteBuffer msgheader = msg.duplicate().slice(); + if(_header.remaining() > msgheader.limit()) { msg.position(msg.limit()); @@ -329,6 +327,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine } } + if(newDelegate == null && looksLikeSSL(headerBytes)) { if(_sslContext != null) @@ -475,7 +474,7 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine SSLStatus sslStatus = new SSLStatus(); _sslReceiver = new SSLReceiver(_engine,_decryptEngine,sslStatus); _sslSender = new SSLBufferingSender(_engine,_sender,sslStatus); - _decryptEngine.setNetworkConnection(new SSLNetworkConnection(_engine,_network, _sslSender)); + _decryptEngine.setNetworkConnection(new SSLNetworkConnection(_engine,_network, _sslSender), _sslSender); } @Override @@ -592,6 +591,9 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine private final NetworkConnection _network; private final SSLBufferingSender _sslSender; private final SSLEngine _engine; + private Principal _principal; + private boolean _principalChecked; + private final Object _lock = new Object(); public SSLNetworkConnection(SSLEngine engine, NetworkConnection network, SSLBufferingSender sslSender) @@ -647,21 +649,25 @@ public class MultiVersionProtocolEngine implements ServerProtocolEngine } @Override - public void setPeerPrincipal(Principal principal) - { - _network.setPeerPrincipal(principal); - } - - @Override public Principal getPeerPrincipal() { - try - { - return _engine.getSession().getPeerPrincipal(); - } - catch (SSLPeerUnverifiedException e) + synchronized (_lock) { - return null; + if(!_principalChecked) + { + try + { + _principal = _engine.getSession().getPeerPrincipal(); + } + catch (SSLPeerUnverifiedException e) + { + _principal = null; + } + + _principalChecked = true; + } + + return _principal; } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java index ceebe4f965..c00881ca94 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/AMQQueue.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.Exchange; @@ -35,7 +34,6 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Collection; import java.util.List; -import java.util.Map; import java.util.Set; public interface AMQQueue extends Comparable<AMQQueue>, ExchangeReferrer, TransactionLogResource, BaseQueue diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java index 6145570b0c..7aba1a2342 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/BaseQueue.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.store.TransactionLogResource; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java index 2a78ee430c..df26037eed 100755 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/InboundMessageAdapter.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.queue; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.InboundMessage; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java index fb36433799..b002419064 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/queue/SimpleAMQQueue.java @@ -38,7 +38,6 @@ import java.util.concurrent.atomic.AtomicLong; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; import org.apache.qpid.AMQSecurityException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.pool.ReferenceCountingExecutorService; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.configuration.BrokerProperties; @@ -734,7 +733,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes && mightAssign(sub, entry) && !sub.wouldSuspend(entry)) { - if (sub.acquires() && !(assign(sub, entry) && entry.acquire(sub))) + if (sub.acquires() && !assign(sub, entry)) { // restore credit here that would have been taken away by wouldSuspend since we didn't manage // to acquire the entry for this subscription @@ -755,10 +754,18 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes private boolean assign(final Subscription sub, final QueueEntry entry) { - return _messageGroupManager == null || _messageGroupManager.acceptMessage(sub, entry); + if(_messageGroupManager == null) + { + //no grouping, try to acquire immediately. + return entry.acquire(sub); + } + else + { + //the group manager is responsible for acquiring the message if/when appropriate + return _messageGroupManager.acceptMessage(sub, entry); + } } - private boolean mightAssign(final Subscription sub, final QueueEntry entry) { if(_messageGroupManager == null || !sub.acquires()) @@ -1646,7 +1653,7 @@ public class SimpleAMQQueue implements AMQQueue, Subscription.StateListener, Mes { if (!sub.wouldSuspend(node)) { - if (sub.acquires() && !(assign(sub, node) && node.acquire(sub))) + if (sub.acquires() && !assign(sub, node)) { // restore credit here that would have been taken away by wouldSuspend since we didn't manage // to acquire the entry for this subscription diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java index 244ab0dd94..066c05b898 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/security/SubjectCreator.java @@ -37,6 +37,7 @@ import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationS import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManager; import org.apache.qpid.server.security.auth.manager.AuthenticationManager; +import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager; /** * Creates a {@link Subject} formed by the {@link Principal}'s returned from: @@ -129,6 +130,17 @@ public class SubjectCreator } } + public Subject createSubjectWithGroups(Principal principal) + { + Subject authenticationSubject = new Subject(); + + authenticationSubject.getPrincipals().add(principal); + authenticationSubject.getPrincipals().addAll(getGroupPrincipals(principal.getName())); + authenticationSubject.setReadOnly(); + + return authenticationSubject; + } + public Subject createSubjectWithGroups(String username) { Subject authenticationSubject = new Subject(); @@ -159,4 +171,9 @@ public class SubjectCreator { return _authenticationManager instanceof AnonymousAuthenticationManager; } + + public boolean isExternalAuthenticationAllowed() + { + return _authenticationManager instanceof ExternalAuthenticationManager; + } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java index 4a32d0a27e..96f6983402 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/AbstractJDBCMessageStore.java @@ -79,7 +79,7 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC private static final int DB_VERSION = 7; private final AtomicLong _messageId = new AtomicLong(0); - private AtomicBoolean _closed = new AtomicBoolean(false); + private final AtomicBoolean _closed = new AtomicBoolean(false); private static final String CREATE_DB_VERSION_TABLE = "CREATE TABLE "+ DB_VERSION_TABLE_NAME + " ( version int not null )"; private static final String INSERT_INTO_DB_VERSION = "INSERT INTO "+ DB_VERSION_TABLE_NAME + " ( version ) VALUES ( ? )"; @@ -683,12 +683,14 @@ abstract public class AbstractJDBCMessageStore implements MessageStore, DurableC @Override public void close() throws AMQStoreException { - _closed.getAndSet(true); - _stateManager.attainState(State.CLOSING); + if (_closed.compareAndSet(false, true)) + { + _stateManager.attainState(State.CLOSING); - doClose(); + doClose(); - _stateManager.attainState(State.CLOSED); + _stateManager.attainState(State.CLOSED); + } } diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java index a3534d3fa5..c6ebe90802 100755 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/ConfigurationRecoveryHandler.java @@ -20,9 +20,6 @@ */ package org.apache.qpid.server.store; -import org.apache.qpid.framing.FieldTable; - -import java.nio.ByteBuffer; import java.util.Map; import java.util.UUID; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java index d311685375..a688b493e1 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/store/DurableConfigurationStoreHelper.java @@ -29,14 +29,11 @@ import java.util.Map; import java.util.Set; import org.apache.qpid.AMQStoreException; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.model.Binding; import org.apache.qpid.server.model.Exchange; import org.apache.qpid.server.model.LifetimePolicy; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.QueueArgumentsConverter; public class DurableConfigurationStoreHelper { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java index efedad1181..ae7e11afa4 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/AssignedSubscriptionMessageGroupManager.java @@ -63,6 +63,18 @@ public class AssignedSubscriptionMessageGroupManager implements MessageGroupMana public boolean acceptMessage(Subscription sub, QueueEntry entry) { + if(assignMessage(sub, entry)) + { + return entry.acquire(sub); + } + else + { + return false; + } + } + + private boolean assignMessage(Subscription sub, QueueEntry entry) + { Object groupVal = entry.getMessage().getMessageHeader().getHeader(_groupId); if(groupVal == null) { diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java index f38e23b342..55110c46de 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/DefinedGroupMessageGroupManager.java @@ -136,9 +136,21 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager public synchronized boolean acceptMessage(final Subscription sub, final QueueEntry entry) { + if(assignMessage(sub, entry)) + { + return entry.acquire(sub); + } + else + { + return false; + } + } + + private boolean assignMessage(final Subscription sub, final QueueEntry entry) + { Object groupId = getKey(entry); Group group = _groupMap.get(groupId); - + if(group == null || !group.isValid()) { group = new Group(groupId, sub); @@ -152,11 +164,10 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager { return false; } - } - + Subscription assignedSub = group.getSubscription(); - + if(assignedSub == sub) { entry.addStateChangeListener(new GroupStateChangeListener(group, entry)); @@ -167,8 +178,7 @@ public class DefinedGroupMessageGroupManager implements MessageGroupManager return false; } } - - + public synchronized QueueEntry findEarliestAssignedAvailableEntry(final Subscription sub) { EntryFinder visitor = new EntryFinder(sub); diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/Subscription.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/Subscription.java index 36d49d8279..fde3d3809c 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/Subscription.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/subscription/Subscription.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.subscription; import java.util.concurrent.atomic.AtomicLong; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.protocol.AMQSessionModel; import org.apache.qpid.server.queue.AMQQueue; diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/AcceptingTransport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/AcceptingTransport.java new file mode 100644 index 0000000000..bf7f2835e0 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/AcceptingTransport.java @@ -0,0 +1,27 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport; + +public interface AcceptingTransport +{ + public void start(); + public void close(); +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java new file mode 100644 index 0000000000..a26f892483 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransport.java @@ -0,0 +1,146 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport; + +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; +import org.apache.qpid.transport.NetworkTransportConfiguration; +import org.apache.qpid.transport.network.IncomingNetworkTransport; + +import javax.net.ssl.SSLContext; +import java.net.InetSocketAddress; +import java.util.Set; + +import static org.apache.qpid.transport.ConnectionSettings.WILDCARD_ADDRESS; + +class TCPandSSLTransport implements AcceptingTransport +{ + private IncomingNetworkTransport _networkTransport; + private Set<Transport> _transports; + private SSLContext _sslContext; + private InetSocketAddress _bindingSocketAddress; + private Port _port; + private Set<AmqpProtocolVersion> _supported; + private AmqpProtocolVersion _defaultSupportedProtocolReply; + + TCPandSSLTransport(final Set<Transport> transports, + final SSLContext sslContext, + final Port port, + final Set<AmqpProtocolVersion> supported, + final AmqpProtocolVersion defaultSupportedProtocolReply) + { + _transports = transports; + _sslContext = sslContext; + _port = port; + _supported = supported; + _defaultSupportedProtocolReply = defaultSupportedProtocolReply; + } + + @Override + public void start() + { + String bindingAddress = (String) _port.getAttribute(Port.BINDING_ADDRESS); + if (WILDCARD_ADDRESS.equals(bindingAddress)) + { + bindingAddress = null; + } + Integer port = (Integer) _port.getAttribute(Port.PORT); + if ( bindingAddress == null ) + { + _bindingSocketAddress = new InetSocketAddress(port); + } + else + { + _bindingSocketAddress = new InetSocketAddress(bindingAddress, port); + } + + final NetworkTransportConfiguration settings = new ServerNetworkTransportConfiguration(); + _networkTransport = org.apache.qpid.transport.network.Transport.getIncomingTransportInstance(); + final MultiVersionProtocolEngineFactory protocolEngineFactory = + new MultiVersionProtocolEngineFactory( + _port.getParent(Broker.class), _transports.contains(Transport.TCP) ? _sslContext : null, + settings.wantClientAuth(), settings.needClientAuth(), + _supported, + _defaultSupportedProtocolReply, + _port, + _transports.contains(Transport.TCP) ? Transport.TCP : Transport.SSL); + + _networkTransport.accept(settings, protocolEngineFactory, _transports.contains(Transport.TCP) ? null : _sslContext); + } + + @Override + public void close() + { + _networkTransport.close(); + } + + class ServerNetworkTransportConfiguration implements NetworkTransportConfiguration + { + public ServerNetworkTransportConfiguration() + { + } + + @Override + public boolean wantClientAuth() + { + return (Boolean)_port.getAttribute(Port.WANT_CLIENT_AUTH); + } + + @Override + public boolean needClientAuth() + { + return (Boolean)_port.getAttribute(Port.NEED_CLIENT_AUTH); + } + + @Override + public Boolean getTcpNoDelay() + { + return (Boolean)_port.getAttribute(Port.TCP_NO_DELAY); + } + + @Override + public Integer getSendBufferSize() + { + return (Integer)_port.getAttribute(Port.SEND_BUFFER_SIZE); + } + + @Override + public Integer getReceiveBufferSize() + { + return (Integer)_port.getAttribute(Port.RECEIVE_BUFFER_SIZE); + } + + @Override + public InetSocketAddress getAddress() + { + return _bindingSocketAddress; + } + + @Override + public String toString() + { + return _port.toString(); + } + } +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java new file mode 100644 index 0000000000..33c7774a29 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProvider.java @@ -0,0 +1,41 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport; + +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; + +import javax.net.ssl.SSLContext; +import java.util.Set; + +class TCPandSSLTransportProvider implements TransportProvider +{ + @Override + public AcceptingTransport createTransport(final Set<Transport> transports, + final SSLContext sslContext, + final Port port, + final Set<AmqpProtocolVersion> supported, + final AmqpProtocolVersion defaultSupportedProtocolReply) + { + return new TCPandSSLTransport(transports, sslContext, port, supported, defaultSupportedProtocolReply); + } +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProviderFactory.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProviderFactory.java new file mode 100644 index 0000000000..9b61d1d037 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TCPandSSLTransportProviderFactory.java @@ -0,0 +1,55 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport; + +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.plugin.TransportProviderFactory; + +import java.util.Arrays; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; + +public class TCPandSSLTransportProviderFactory implements TransportProviderFactory +{ + + private static final String TYPE = "TCPandSSL"; + + @Override + public Set<Set<Transport>> getSupportedTransports() + { + return new HashSet<Set<Transport>>(Arrays.asList(EnumSet.of(Transport.TCP), + EnumSet.of(Transport.SSL), + EnumSet.of(Transport.TCP,Transport.SSL))); + } + + @Override + public TransportProvider getTransportProvider(final Set<Transport> transports) + { + return new TCPandSSLTransportProvider(); + } + + @Override + public String getType() + { + return TYPE; + } +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java new file mode 100644 index 0000000000..86b1e31727 --- /dev/null +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/transport/TransportProvider.java @@ -0,0 +1,38 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport; + +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; + +import javax.net.ssl.SSLContext; +import java.net.InetSocketAddress; +import java.util.Set; + +public interface TransportProvider +{ + AcceptingTransport createTransport(Set<Transport> transports, + SSLContext sslContext, + Port port, + Set<AmqpProtocolVersion> supported, + AmqpProtocolVersion defaultSupportedProtocolReply); +} diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java index 0cd4f0b6b2..5859ce3c68 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java @@ -563,11 +563,6 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg String alternateExchangeName) throws AMQException { - - if(_exchangeRegistry.isReservedExchangeName(name)) - { - throw new ReservedExchangeNameException(name); - } synchronized (_exchangeRegistry) { Exchange existing; @@ -575,6 +570,11 @@ public abstract class AbstractVirtualHost implements VirtualHost, IConnectionReg { throw new ExchangeExistsException(name,existing); } + if(_exchangeRegistry.isReservedExchangeName(name)) + { + throw new ReservedExchangeNameException(name); + } + Exchange alternateExchange; if(alternateExchangeName != null) diff --git a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java index a321c285b7..de6d3d9e75 100644 --- a/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java +++ b/qpid/java/broker-core/src/main/java/org/apache/qpid/server/virtualhost/BindingRecoverer.java @@ -20,15 +20,12 @@ */ package org.apache.qpid.server.virtualhost; -import java.nio.ByteBuffer; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.UUID; import org.apache.log4j.Logger; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.exchange.ExchangeRegistry; diff --git a/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.TransportProviderFactory b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.TransportProviderFactory new file mode 100644 index 0000000000..3838a9c39f --- /dev/null +++ b/qpid/java/broker-core/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.TransportProviderFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.transport.TCPandSSLTransportProviderFactory
\ No newline at end of file diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java index dc9ddf7b32..f60f173de9 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/configuration/VirtualHostConfigurationTest.java @@ -26,7 +26,6 @@ import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.XMLConfiguration; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.queue.AMQPriorityQueue; import org.apache.qpid.server.queue.AMQQueue; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java index 86ae3e6e9c..16d3e44bb5 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/DefaultExchangeFactoryTest.java @@ -26,7 +26,6 @@ import java.util.List; import java.util.UUID; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.plugin.ExchangeType; import org.apache.qpid.server.virtualhost.VirtualHost; import org.apache.qpid.test.utils.QpidTestCase; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java index 7335d43b2e..98ff2421bc 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/FanoutExchangeTest.java @@ -37,8 +37,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.FieldTable; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.message.AMQMessageHeader; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java index 0f1ab65244..757624d090 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/HeadersExchangeTest.java @@ -32,7 +32,6 @@ import junit.framework.TestCase; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.common.AMQPFilterTypes; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.message.AMQMessageHeader; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java index a84f5e1ecb..344ddd9366 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/exchange/TopicExchangeTest.java @@ -24,14 +24,12 @@ import java.util.List; import junit.framework.Assert; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.server.model.UUIDGenerator; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.AMQQueueFactory; import org.apache.qpid.server.queue.BaseQueue; import org.apache.qpid.server.util.BrokerTestHelper; import org.apache.qpid.server.virtualhost.VirtualHost; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java index e52ead451e..d9ecfc91b1 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/logging/subjects/BindingLogSubjectTest.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.logging.subjects; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.queue.AMQQueue; import org.apache.qpid.server.queue.MockAMQQueue; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java index 584e26d88f..2c7fa3a8d0 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/InboundMessageAdapterTest.java @@ -23,7 +23,6 @@ package org.apache.qpid.server.queue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.ServerMessage; import org.apache.qpid.test.utils.QpidTestCase; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java index 2a0c12ff3e..d7ef240ef4 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/MockAMQQueue.java @@ -21,7 +21,6 @@ package org.apache.qpid.server.queue; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.binding.Binding; import org.apache.qpid.server.configuration.QueueConfiguration; import org.apache.qpid.server.exchange.Exchange; @@ -35,7 +34,6 @@ import org.apache.qpid.server.virtualhost.VirtualHost; import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.CopyOnWriteArrayList; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java index 3a41bb9c72..4058eac99d 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/queue/SimpleAMQQueueTest.java @@ -34,8 +34,6 @@ import org.apache.qpid.AMQException; import org.apache.qpid.AMQInternalException; import org.apache.qpid.AMQSecurityException; import org.apache.qpid.exchange.ExchangeDefaults; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.framing.abstraction.MessagePublishInfo; import org.apache.qpid.server.exchange.DirectExchange; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.MessageReference; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java index d99adb91fe..a52b9f8d14 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/store/TestMessageMetaData.java @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ package org.apache.qpid.server.store; import java.io.DataOutputStream; diff --git a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java index 77f09dc567..508f33fd35 100644 --- a/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java +++ b/qpid/java/broker-core/src/test/java/org/apache/qpid/server/subscription/MockSubscription.java @@ -22,7 +22,6 @@ package org.apache.qpid.server.subscription; import org.apache.qpid.AMQException; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.LogSubject; diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java index cc93c540df..52f55f7e2d 100644 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java +++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java @@ -25,7 +25,6 @@ import java.security.Principal; import javax.security.auth.Subject; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.security.Result; import org.apache.qpid.server.security.access.ObjectProperties; import org.apache.qpid.server.security.access.ObjectType; diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java index 092ea7c3c9..2ca680869f 100755 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageMetaData_0_10.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.protocol.v0_10; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.plugin.MessageMetaDataType; diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java index e5914d1d4e..34cf6998ab 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageTransferMessage.java @@ -20,7 +20,6 @@ */ package org.apache.qpid.server.protocol.v0_10; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.message.AMQMessageHeader; import org.apache.qpid.server.message.AbstractServerMessageImpl; import org.apache.qpid.server.message.InboundMessage; diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java index 9e41a5234c..b8fcdbfe6d 100755 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ProtocolEngine_0_10.java @@ -60,15 +60,8 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol if(network != null) { - setNetworkConnection(network); + setNetworkConnection(network, network.getSender()); } - - - } - - public void setNetworkConnection(NetworkConnection network) - { - setNetworkConnection(network, network.getSender()); } public void setNetworkConnection(NetworkConnection network, Sender<ByteBuffer> sender) @@ -77,7 +70,6 @@ public class ProtocolEngine_0_10 extends InputHandler implements ServerProtocol _connection.setNetworkConnection(network); _connection.setSender(new Disassembler(wrapSender(sender), MAX_FRAME_SIZE)); - _connection.setPeerPrincipal(_network.getPeerPrincipal()); // FIXME Two log messages to maintain compatibility with earlier protocol versions _connection.getLogActor().message(ConnectionMessages.OPEN(null, null, null, null, false, false, false, false)); _connection.getLogActor().message(ConnectionMessages.OPEN(null, "0-10", null, null, false, true, false, false)); diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java index 72d6a0832d..b4d591a72f 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnection.java @@ -73,7 +73,6 @@ public class ServerConnection extends Connection implements AMQConnectionModel, private Port _port; private AtomicLong _lastIoTime = new AtomicLong(); private boolean _blocking; - private Principal _peerPrincipal; private NetworkConnection _networkConnection; private Transport _transport; private volatile boolean _stopped; @@ -529,12 +528,7 @@ public class ServerConnection extends Connection implements AMQConnectionModel, public Principal getPeerPrincipal() { - return _peerPrincipal; - } - - public void setPeerPrincipal(Principal peerPrincipal) - { - _peerPrincipal = peerPrincipal; + return _networkConnection.getPeerPrincipal(); } @Override diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java index 395aed29ce..041e1d3645 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java @@ -212,10 +212,21 @@ public class ServerSessionDelegate extends SessionDelegate { ServerSession s = (ServerSession) session; queue.setExclusiveOwningSession(s); + + ((ServerSession) session).addSessionCloseTask(new ServerSession.Task() + { + public void doTask(ServerSession session) + { + if(queue.getExclusiveOwningSession() == session) + { + queue.setExclusiveOwningSession(null); + } + } + }); + if(queue.getAuthorizationHolder() == null) { queue.setAuthorizationHolder(s); - queue.setExclusiveOwningSession(s); ((ServerSession) session).addSessionCloseTask(new ServerSession.Task() { public void doTask(ServerSession session) @@ -223,7 +234,6 @@ public class ServerSessionDelegate extends SessionDelegate if(queue.getAuthorizationHolder() == session) { queue.setAuthorizationHolder(null); - queue.setExclusiveOwningSession(null); } } }); diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java index 4cacae134e..f04475eb33 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java @@ -1271,11 +1271,11 @@ public class AMQProtocolEngine implements ServerProtocolEngine, AMQProtocolSessi } else if (throwable instanceof IOException) { - _logger.error("IOException caught in" + this + ", session closed implictly: " + throwable); + _logger.info("IOException caught in " + this + ", connection closed implicitly: " + throwable); } else { - _logger.error("Exception caught in" + this + ", closing session explictly: " + throwable, throwable); + _logger.error("Exception caught in " + this + ", closing connection explicitly: " + throwable, throwable); MethodRegistry methodRegistry = MethodRegistry.getMethodRegistry(getProtocolVersion()); diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java index 0535236f94..4ebddb0f68 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/handler/ExchangeBoundHandler.java @@ -29,7 +29,6 @@ import org.apache.qpid.server.protocol.v0_8.AMQChannel; import org.apache.qpid.server.exchange.Exchange; import org.apache.qpid.server.protocol.v0_8.AMQProtocolSession; import org.apache.qpid.server.queue.AMQQueue; -import org.apache.qpid.server.queue.QueueRegistry; import org.apache.qpid.server.protocol.v0_8.state.AMQStateManager; import org.apache.qpid.server.protocol.v0_8.state.StateAwareMethodListener; import org.apache.qpid.server.virtualhost.VirtualHost; @@ -80,13 +79,9 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo channel.sync(); - AMQShortString exchangeName = body.getExchange(); + AMQShortString exchangeName = body.getExchange() == null ? AMQShortString.EMPTY_STRING : body.getExchange(); AMQShortString queueName = body.getQueue(); AMQShortString routingKey = body.getRoutingKey(); - if (exchangeName == null) - { - throw new AMQException("Exchange exchange must not be null"); - } Exchange exchange = virtualHost.getExchange(exchangeName.toString()); ExchangeBoundOkBody response; if (exchange == null) @@ -94,7 +89,7 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo response = methodRegistry.createExchangeBoundOkBody(EXCHANGE_NOT_FOUND, - new AMQShortString("Exchange " + exchangeName + " not found")); + new AMQShortString("Exchange '" + exchangeName + "' not found")); } else if (routingKey == null) { @@ -119,7 +114,7 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo { response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode - new AMQShortString("Queue " + queueName + " not found")); // replyText + new AMQShortString("Queue '" + queueName + "' not found")); // replyText } else { @@ -133,7 +128,7 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo { response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_BOUND, // replyCode - new AMQShortString("Queue " + queueName + " not bound to exchange " + exchangeName)); // replyText + new AMQShortString("Queue '" + queueName + "' not bound to exchange '" + exchangeName + "'")); // replyText } } } @@ -145,7 +140,7 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo { response = methodRegistry.createExchangeBoundOkBody(QUEUE_NOT_FOUND, // replyCode - new AMQShortString("Queue " + queueName + " not found")); // replyText + new AMQShortString("Queue '" + queueName + "' not found")); // replyText } else { @@ -159,8 +154,8 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo else { - String message = "Queue " + queueName + " not bound with routing key " + - body.getRoutingKey() + " to exchange " + exchangeName; + String message = "Queue '" + queueName + "' not bound with routing key '" + + body.getRoutingKey() + "' to exchange '" + exchangeName + "'"; if(message.length()>255) { @@ -183,8 +178,8 @@ public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBo { response = methodRegistry.createExchangeBoundOkBody(NO_QUEUE_BOUND_WITH_RK, // replyCode - new AMQShortString("No queue bound with routing key " + body.getRoutingKey() + - " to exchange " + exchangeName)); // replyText + new AMQShortString("No queue bound with routing key '" + body.getRoutingKey() + + "' to exchange '" + exchangeName + "'")); // replyText } } session.writeFrame(response.generateFrame(channelId)); diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngineTest.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngineTest.java index f5e58cfd02..1506ecb92f 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngineTest.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngineTest.java @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ package org.apache.qpid.server.protocol.v0_8; import static org.mockito.Mockito.mock; diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java index 5b1e5af7bd..f1dfc52ba4 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/test/java/org/apache/qpid/server/protocol/v0_8/InternalTestProtocolSession.java @@ -314,11 +314,6 @@ public class InternalTestProtocolSession extends AMQProtocolEngine implements Pr } @Override - public void setPeerPrincipal(Principal principal) - { - } - - @Override public Principal getPeerPrincipal() { return null; diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java index 68e9a88b0b..9b11c0f48d 100644 --- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/Message_1_0.java @@ -26,7 +26,6 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicIntegerFieldUpdater; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.message.InboundMessage; import org.apache.qpid.server.message.MessageReference; import org.apache.qpid.server.message.ServerMessage; diff --git a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java index e832ef7569..92bccf871f 100644 --- a/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java +++ b/qpid/java/broker-plugins/amqp-msg-conv-0-8-to-0-10/src/main/java/org/apache/qpid/server/protocol/converter/v0_8_v0_10/MessageConverter_0_10_to_0_8.java @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ package org.apache.qpid.server.protocol.converter.v0_8_v0_10; import java.nio.ByteBuffer; diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/resources/virtualhost/store/derby/add.html b/qpid/java/broker-plugins/derby-store/src/main/java/resources/virtualhost/store/derby/add.html index 2ed5b35c10..ead232d0b1 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/resources/virtualhost/store/derby/add.html +++ b/qpid/java/broker-plugins/derby-store/src/main/java/resources/virtualhost/store/derby/add.html @@ -1,3 +1,19 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> <table class="tableContainer-table tableContainer-table-horiz"> <tr> <td class="tableContainer-labelCell" style="width: 300px;"><strong>Path to store location*: </strong></td> diff --git a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html index 52da8f52ae..0a83bd9f6f 100644 --- a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html +++ b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/virtualhost/store/pool/bonecp/add.html @@ -1,3 +1,19 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> <table class="tableContainer-table tableContainer-table-horiz"> <tr> diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/jdbc/add.html b/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/jdbc/add.html index 966b4fcc06..c3d6c287a2 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/jdbc/add.html +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/jdbc/add.html @@ -1,3 +1,19 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> <table class="tableContainer-table tableContainer-table-horiz"> <tr> <td class="tableContainer-labelCell" style="width: 300px;"><strong>JDBC Url*: </strong></td> diff --git a/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/pool/none/add.html b/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/pool/none/add.html index e69de29bb2..2666129a1f 100644 --- a/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/pool/none/add.html +++ b/qpid/java/broker-plugins/jdbc-store/src/main/java/resources/virtualhost/store/pool/none/add.html @@ -0,0 +1,17 @@ +<!-- + ~ 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. + --> + diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java index f8a2091282..e92960a719 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagement.java @@ -23,15 +23,13 @@ package org.apache.qpid.server.management.plugin; import java.lang.reflect.Type; import java.net.SocketAddress; import java.security.GeneralSecurityException; -import java.util.Collection; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.UUID; +import java.util.*; +import javax.net.ssl.KeyManager; import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + import org.apache.log4j.Logger; import org.apache.qpid.server.configuration.IllegalConfigurationException; import org.apache.qpid.server.logging.actors.CurrentActor; @@ -78,6 +76,7 @@ import org.apache.qpid.server.model.VirtualHost; import org.apache.qpid.server.model.adapter.AbstractPluginAdapter; import org.apache.qpid.server.plugin.PluginFactory; import org.apache.qpid.server.util.MapValueConverter; +import org.apache.qpid.transport.network.security.ssl.QpidMultipleTrustManager; import org.eclipse.jetty.server.Connector; import org.eclipse.jetty.server.DispatcherType; import org.eclipse.jetty.server.Server; @@ -183,7 +182,7 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem } catch (Exception e) { - throw new RuntimeException("Failed to start http management on ports " + httpPorts); + throw new RuntimeException("Failed to start HTTP management on ports : " + httpPorts, e); } CurrentActor.get().message(ManagementConsoleMessages.READY(OPERATIONAL_LOGGING_NAME)); @@ -200,7 +199,7 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem } catch (Exception e) { - throw new RuntimeException("Failed to stop http management on port " + getHttpPorts(getBroker().getPorts())); + throw new RuntimeException("Failed to stop HTTP management on ports : " + getHttpPorts(getBroker().getPorts()), e); } } @@ -240,28 +239,93 @@ public class HttpManagement extends AbstractPluginAdapter implements HttpManagem else if (transports.contains(Transport.SSL)) { KeyStore keyStore = port.getKeyStore(); + Collection<TrustStore> trustStores = port.getTrustStores(); if (keyStore == null) { throw new IllegalConfigurationException("Key store is not configured. Cannot start management on HTTPS port without keystore"); } SslContextFactory factory = new SslContextFactory(); + final boolean needClientAuth = Boolean.valueOf(String.valueOf(port.getAttribute(Port.NEED_CLIENT_AUTH))); + final boolean wantClientAuth = Boolean.valueOf(String.valueOf(port.getAttribute(Port.WANT_CLIENT_AUTH))); + boolean needClientCert = needClientAuth || wantClientAuth; + if (needClientCert && trustStores.isEmpty()) + { + throw new IllegalConfigurationException("Client certificate authentication is enabled on AMQP port '" + + this.getName() + "' but no trust store defined"); + } + try { SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(keyStore.getKeyManagers(), null, null); + KeyManager[] keyManagers = keyStore.getKeyManagers(); + + TrustManager[] trustManagers; + if(trustStores == null || trustStores.isEmpty()) + { + trustManagers = null; + } + else if(trustStores.size() == 1) + { + trustManagers = trustStores.iterator().next().getTrustManagers(); + } + else + { + Collection<TrustManager> trustManagerList = new ArrayList<TrustManager>(); + final QpidMultipleTrustManager mulTrustManager = new QpidMultipleTrustManager(); + + for(TrustStore ts : trustStores) + { + TrustManager[] managers = ts.getTrustManagers(); + if(managers != null) + { + for(TrustManager manager : managers) + { + if(manager instanceof X509TrustManager) + { + mulTrustManager.addTrustManager((X509TrustManager)manager); + } + else + { + trustManagerList.add(manager); + } + } + } + } + if(!mulTrustManager.isEmpty()) + { + trustManagerList.add(mulTrustManager); + } + trustManagers = trustManagerList.toArray(new TrustManager[trustManagerList.size()]); + } + sslContext.init(keyManagers, trustManagers, null); + factory.setSslContext(sslContext); + if(needClientAuth) + { + factory.setNeedClientAuth(true); + } + else if(wantClientAuth) + { + factory.setWantClientAuth(true); + } } catch (GeneralSecurityException e) { throw new RuntimeException("Cannot configure port " + port.getName() + " for transport " + Transport.SSL, e); } connector = new SslSocketConnector(factory); + } else { throw new IllegalArgumentException("Unexpected transport on port " + port.getName() + ":" + transports); } lastPort = port.getPort(); + String bindingAddress = port.getBindingAddress(); + if(bindingAddress != null && !bindingAddress.trim().equals("") && !bindingAddress.trim().equals("*")) + { + connector.setHost(bindingAddress.trim()); + } connector.setPort(port.getPort()); server.addConnector(connector); } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java index 990ff1c53b..f6674b5152 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/HttpManagementUtil.java @@ -23,10 +23,14 @@ package org.apache.qpid.server.management.plugin; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.security.AccessControlException; +import java.security.Principal; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.security.cert.X509Certificate; +import java.util.Collections; import javax.security.auth.Subject; +import javax.security.auth.x500.X500Principal; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @@ -36,11 +40,17 @@ import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.HttpManagementActor; import org.apache.qpid.server.management.plugin.session.LoginLogoutReporter; +import org.apache.qpid.server.model.AuthenticationProvider; import org.apache.qpid.server.model.Broker; import org.apache.qpid.server.security.SecurityManager; import org.apache.qpid.server.security.SubjectCreator; +import org.apache.qpid.server.security.auth.AuthenticatedPrincipal; import org.apache.qpid.server.security.auth.AuthenticationResult.AuthenticationStatus; import org.apache.qpid.server.security.auth.SubjectAuthenticationResult; +import org.apache.qpid.server.security.auth.UsernamePrincipal; +import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManager; +import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerFactory; +import org.apache.qpid.transport.network.security.ssl.SSLUtil; public class HttpManagementUtil { @@ -164,17 +174,41 @@ public class HttpManagementUtil session.setAttribute(ATTR_LOGIN_LOGOUT_REPORTER, new LoginLogoutReporter(logActor, subject)); } - private static Subject tryToAuthenticate(HttpServletRequest request, HttpManagementConfiguration managementConfig) + public static Subject tryToAuthenticate(HttpServletRequest request, HttpManagementConfiguration managementConfig) { Subject subject = null; SocketAddress localAddress = getSocketAddress(request); - SubjectCreator subjectCreator = managementConfig.getAuthenticationProvider(localAddress).getSubjectCreator(); + final AuthenticationProvider authenticationProvider = managementConfig.getAuthenticationProvider(localAddress); + SubjectCreator subjectCreator = authenticationProvider.getSubjectCreator(); String remoteUser = request.getRemoteUser(); if (remoteUser != null || subjectCreator.isAnonymousAuthenticationAllowed()) { subject = authenticateUser(subjectCreator, remoteUser, null); } + else if(subjectCreator.isExternalAuthenticationAllowed() + && Collections.list(request.getAttributeNames()).contains("javax.servlet.request.X509Certificate")) + { + Principal principal = null; + X509Certificate[] certificates = + (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); + if(certificates != null && certificates.length != 0) + { + principal = certificates[0].getSubjectX500Principal(); + + if(!Boolean.valueOf(String.valueOf(authenticationProvider.getAttribute(ExternalAuthenticationManagerFactory.ATTRIBUTE_USE_FULL_DN)))) + { + String username; + String dn = ((X500Principal) principal).getName(X500Principal.RFC2253); + + + username = SSLUtil.getIdFromSubjectDN(dn); + principal = new UsernamePrincipal(username); + } + + subject = subjectCreator.createSubjectWithGroups(new AuthenticatedPrincipal(principal)); + } + } else { String header = request.getHeader("Authorization"); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java index a08d6496bf..ee481ebdbe 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/AbstractServlet.java @@ -33,7 +33,6 @@ import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.log4j.Logger; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.server.logging.LogActor; import org.apache.qpid.server.logging.actors.CurrentActor; import org.apache.qpid.server.logging.actors.HttpManagementActor; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java index 2b035fed8f..9ad52007ab 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java @@ -284,6 +284,11 @@ public class SaslServlet extends AbstractServlet @Override protected Subject getAuthorisedSubject(HttpServletRequest request) { - return HttpManagementUtil.getAuthorisedSubject(request.getSession()); + Subject subject = HttpManagementUtil.getAuthorisedSubject(request.getSession()); + if(subject == null) + { + subject = HttpManagementUtil.tryToAuthenticate(request, HttpManagementUtil.getManagementConfiguration(getServletContext())); + } + return subject; } } diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html index 59abbadf32..c7676d27b7 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html @@ -42,9 +42,11 @@ data-dojo-props="name:'authenticationProvider',label:'Authentication Provider*:', searchAttr: 'name', required: true, placeHolder: 'Select Provider'"> </select> </div> - <div id="formAddPort:fieldsAMQP"> + <div id="formAddPort:fieldsBindingAddress"> <input id="formAddPort.bindingAddress" type="text" name="bindingAddress" placeholder="*" - dojoType="dijit.form.TextBox" data-dojo-props="label: 'Binding address:'"/> + dojoType="dijit.form.TextBox" data-dojo-props="label: 'Binding address:'"/> + </div> + <div id="formAddPort:fieldsAMQP"> <input id="formAddPort.protocolsDefault" type="checkbox" checked="checked" dojoType="dijit.form.CheckBox" data-dojo-props="label: 'Support default protocols:'"/> <select id="formAddPort.protocolsAMQP" name="protocols" data-dojo-type="dijit.form.MultiSelect" multiple="true" diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/footer.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/footer.html index fa84825e80..76d1d26695 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/footer.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/footer.html @@ -19,10 +19,10 @@ - --> -<div class="footer"><p>© 2004-<span class="currentYear">2012</span> The Apache Software Foundation. +<div class="footer"><p>© 2004-<span class="currentYear">2014</span> The Apache Software Foundation. <br/> Apache Qpid, Qpid, Apache, the Apache feather logo, and the Apache Qpid project logo are trademarks of The Apache Software Foundation. <br/> All other marks mentioned may be trademarks or registered trademarks of their respective owners. -</div>
\ No newline at end of file +</div> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js index b0ad1c661b..2b455a90f1 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Connection.js @@ -84,12 +84,11 @@ define(["dojo/_base/xhr", } storeNodes(["name", - "state", - "durable", + "clientVersion", + "clientId", "principal", "port", "transport", - "lifetimePolicy", "msgInRate", "bytesInRate", "bytesInRateUnits", @@ -125,12 +124,11 @@ define(["dojo/_base/xhr", ConnectionUpdater.prototype.updateHeader = function() { this.name.innerHTML = entities.encode(String(this.connectionData[ "name" ])); - this.state.innerHTML = entities.encode(String(this.connectionData[ "state" ])); - this.durable.innerHTML = entities.encode(String(this.connectionData[ "durable" ])); + this.clientId.innerHTML = entities.encode(String(this.connectionData[ "clientId" ])); + this.clientVersion.innerHTML = entities.encode(String(this.connectionData[ "clientVersion" ])); this.principal.innerHTML = entities.encode(String(this.connectionData[ "principal" ])); this.port.innerHTML = entities.encode(String(this.connectionData[ "port" ])); this.transport.innerHTML = entities.encode(String(this.connectionData[ "transport" ])); - this.lifetimePolicy.innerHTML = entities.encode(String(this.connectionData[ "lifetimePolicy" ])); }; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js index 18abfa443f..86ded8f059 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/addPort.js @@ -110,7 +110,7 @@ define(["dojo/_base/xhr", } var type = dijit.byId("formAddPort.type").value; - if (type == "AMQP") + if (type == "AMQP" || type == "HTTP") { var transportWidget = registry.byId("formAddPort.transports"); var needClientAuth = dijit.byId("formAddPort.needClientAuth"); @@ -154,7 +154,7 @@ define(["dojo/_base/xhr", { var clientAuthPanel = dojo.byId("formAddPort:fieldsClientAuth"); var display = clientAuthPanel.style.display; - if (transportType == "SSL" && protocolType == "AMQP") + if (transportType == "SSL" && (protocolType == "AMQP" || protocolType == "HTTP")) { clientAuthPanel.style.display = "block"; registry.byId("formAddPort.needClientAuth").set("disabled", false); @@ -212,8 +212,11 @@ define(["dojo/_base/xhr", }); var isAMQP = ("AMQP" == newValue); - registry.byId("formAddPort.needClientAuth").set("enabled", isAMQP); - registry.byId("formAddPort.wantClientAuth").set("enabled", isAMQP); + + var isHTTP = ("HTTP" == newValue); + + registry.byId("formAddPort.needClientAuth").set("enabled", isAMQP || isHTTP); + registry.byId("formAddPort.wantClientAuth").set("enabled", isAMQP || isHTTP); registry.byId("formAddPort:fields" + newValue).domNode.style.display = "block"; var defaultsAMQPProtocols = registry.byId("formAddPort.protocolsDefault"); @@ -246,13 +249,15 @@ define(["dojo/_base/xhr", transportWidget.set("disabled", disableTransportWidget); registry.byId("formAddPort.authenticationProvider").set("disabled", isRMI); registry.byId("formAddPort:fieldsAuthenticationProvider").domNode.style.display = isRMI? "none" : "block"; + registry.byId("formAddPort:fieldsBindingAddress").domNode.style.display = newValue == "JMX" ? "none" : "block"; + }); theForm = registry.byId("formAddPort"); var containers = ["formAddPort:fields", "formAddPort:fieldsTransportSSL", "formAddPort:fieldsAMQP", "formAddPort:fieldsJMX", "formAddPort:fieldsHTTP", "formAddPort:transport", - "formAddPort:fieldsClientAuthCheckboxes", "formAddPort:fieldsAuthenticationProvider"]; + "formAddPort:fieldsClientAuthCheckboxes", "formAddPort:fieldsAuthenticationProvider", "formAddPort:fieldsBindingAddress"]; var labelWidthValue = "200"; for(var i = 0; i < containers.length; i++) { @@ -448,8 +453,10 @@ define(["dojo/_base/xhr", { var httpProtocolsWidget = registry.byId("formAddPort.protocolsHTTP"); httpProtocolsWidget.set("disabled", false); - httpProtocolsWidget.set("value", protocols[0]) + httpProtocolsWidget.set("value", protocols[0]); typeWidget.set("value", "HTTP"); + var addressWidget = registry.byId("formAddPort.bindingAddress"); + addressWidget.set("value", port.bindingAddress) } registry.byId("formAddPort:fields" + typeWidget.value).domNode.style.display = "block"; typeWidget.set("disabled", true); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showConnection.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showConnection.html index 4611b77f6c..1032bdeaef 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showConnection.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showConnection.html @@ -19,30 +19,28 @@ - --> <div class="connection"> - <span style="">Name:</span><span class="name" style="position:absolute; left:6em"></span> + <span style="">Name:</span><span class="name" style="position:absolute; left:8em"></span> <br/> - <span style="">State:</span><span class="state" style="position:absolute; left:6em"></span> + <span style="">User:</span><span class="principal" style="position:absolute; left:8em"></span> <span style="position:absolute; left:26em">Pre-fetched:</span> <br/> - <span style="">Durable:</span><span class="durable" style="position:absolute; left:6em"></span> + <span style="">ClientID:</span><span class="clientId" style="position:absolute; left:8em"></span> <span style="position:absolute; left:26em">Inbound:</span> <span class="msgInRate" style="position:absolute; right:9.5em"></span> <span style="position:absolute; right: 5em; width: 4em"> msg/s</span> <span class="bytesInRate" style="position:absolute; right: 3.3em"></span> <span class="bytesInRateUnits" style="position:absolute; right: 0em; width: 3em"></span> <br/> - <span style="">Lifespan:</span><span style="position:absolute; left:6em" class="lifetimePolicy"></span> + <span style="">Client Version:</span><span style="position:absolute; left:8em" class="clientVersion"></span> <span style="position:absolute; left:26em">Outbound:</span> <span class="msgOutRate" style="position:absolute; right:9.5em"></span> <span style="position:absolute; right: 5em; width: 4em"> msg/s</span> <span class="bytesOutRate" style="position:absolute; right: 3.3em"></span> <span class="bytesOutRateUnits" style="position:absolute; right: 0em; width: 3em"></span> <br/> - <span style="">User:</span><span style="position:absolute; left:6em" class="principal"></span> + <span style="">Port:</span><span style="position:absolute; left:8em" class="port"></span> <br/> - <span style="">Port:</span><span style="position:absolute; left:6em" class="port"></span> - <br/> - <span style="">Transport:</span><span style="position:absolute; left:6em" class="transport"></span> + <span style="">Transport:</span><span style="position:absolute; left:8em" class="transport"></span> <br/> <br/> <div data-dojo-type="dijit.TitlePane" data-dojo-props="title: 'Sessions'"> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html index 9a6ec55686..caf26bc075 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showMessage.html @@ -24,10 +24,18 @@ <td><span class="message-id"></span></td> </tr> <tr style="margin-bottom: 4pt"> + <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Size:</span></td> + <td><span class="message-size"></span> bytes</td> + </tr> + <tr style="margin-bottom: 4pt"> <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Message Id:</span></td> <td><span class="message-messageId"></span></td> </tr> <tr style="margin-bottom: 4pt"> + <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Correlation Id:</span></td> + <td><span class="message-correlationId"></span></td> + </tr> + <tr style="margin-bottom: 4pt"> <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">State:</span></td> <td><span class="message-state"></span></td> </tr> diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/standard/add.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/standard/add.html index 3519d0dbd6..050ea9533e 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/standard/add.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/virtualhost/standard/add.html @@ -1,3 +1,19 @@ +<!-- + ~ Licensed to the Apache Software Foundation (ASF) under one or more + ~ contributor license agreements. See the NOTICE file distributed with + ~ this work for additional information regarding copyright ownership. + ~ The ASF licenses this file to You under the Apache License, Version 2.0 + ~ (the "License"); you may not use this file except in compliance with + ~ the License. You may obtain a copy of the License at + ~ + ~ http://www.apache.org/licenses/LICENSE-2.0 + ~ + ~ Unless required by applicable law or agreed to in writing, software + ~ distributed under the License is distributed on an "AS IS" BASIS, + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + ~ See the License for the specific language governing permissions and + ~ limitations under the License. + --> <table class="tableContainer-table tableContainer-table-horiz"> <tr> <td class="tableContainer-labelCell" style="width: 300px;"><strong>Store Type*: </strong></td> diff --git a/qpid/java/broker-plugins/memory-store/src/main/java/resources/virtualhost/store/memory/add.html b/qpid/java/broker-plugins/memory-store/src/main/java/resources/virtualhost/store/memory/add.html index e69de29bb2..2666129a1f 100644 --- a/qpid/java/broker-plugins/memory-store/src/main/java/resources/virtualhost/store/memory/add.html +++ b/qpid/java/broker-plugins/memory-store/src/main/java/resources/virtualhost/store/memory/add.html @@ -0,0 +1,17 @@ +<!-- + ~ 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. + --> + diff --git a/qpid/java/broker-plugins/websocket/build.xml b/qpid/java/broker-plugins/websocket/build.xml new file mode 100644 index 0000000000..fc3dd3b846 --- /dev/null +++ b/qpid/java/broker-plugins/websocket/build.xml @@ -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. + --> +<project name="Qpid Broker-Plugins Websocket Transport" default="build"> + <property name="module.depends" value="common broker-core" /> + <property name="module.test.depends" value="qpid-test-utils broker-core/tests" /> + + <property name="module.genpom" value="true"/> + <property name="module.genpom.args" value="-Sqpid-common=provided -Sqpid-broker-core=provided"/> + + <property name="broker.plugin" value="true"/> + <property name="broker-plugins-websocket.libs" value="" /> + + <import file="../../module.xml" /> + + <target name="bundle" depends="bundle-tasks"/> +</project> diff --git a/qpid/java/broker-plugins/websocket/pom.xml b/qpid/java/broker-plugins/websocket/pom.xml new file mode 100644 index 0000000000..2029bd33aa --- /dev/null +++ b/qpid/java/broker-plugins/websocket/pom.xml @@ -0,0 +1,158 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <parent> + <artifactId>qpid-project</artifactId> + <groupId>org.apache.qpid</groupId> + <version>0.26-SNAPSHOT</version> + <relativePath>../../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>qpid-broker-plugins-websocket</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.qpid</groupId> + <artifactId>qpid-broker-core</artifactId> + <version>0.26-SNAPSHOT</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-servlet_2.5_spec</artifactId> + <version>1.2</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty.orbit</groupId> + <artifactId>javax.servlet</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-continuation</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-continuation</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-servlet</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-security</artifactId> + </exclusion> + </exclusions> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + </dependency> + + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-websocket</artifactId> + <version>7.6.10.v20130312</version> + <scope>compile</scope> + <exclusions> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-util</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-io</artifactId> + </exclusion> + <exclusion> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-http</artifactId> + </exclusion> + </exclusions> + </dependency> + </dependencies> + + <build> + </build> + +</project>
\ No newline at end of file diff --git a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java new file mode 100644 index 0000000000..fde93a27e3 --- /dev/null +++ b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketProvider.java @@ -0,0 +1,315 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport.websocket; + +import org.apache.qpid.protocol.ProtocolEngine; +import org.apache.qpid.protocol.ProtocolEngineFactory; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.protocol.MultiVersionProtocolEngineFactory; +import org.apache.qpid.server.transport.AcceptingTransport; +import org.apache.qpid.transport.Binary; +import org.apache.qpid.transport.Sender; +import org.apache.qpid.transport.network.NetworkConnection; +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; +import org.eclipse.jetty.server.ssl.SslSocketConnector; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.eclipse.jetty.websocket.WebSocket; +import org.eclipse.jetty.websocket.WebSocketHandler; + +import javax.net.ssl.SSLContext; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.security.Principal; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Collections; +import java.util.Set; + +class WebSocketProvider implements AcceptingTransport +{ + public static final String AMQP_WEBSOCKET_SUBPROTOCOL = "AMQPWSB10"; + private final Transport _transport; + private final SSLContext _sslContext; + private final Port _port; + private final Set<AmqpProtocolVersion> _supported; + private final AmqpProtocolVersion _defaultSupportedProtocolReply; + private final ProtocolEngineFactory _factory; + private Server _server; + + WebSocketProvider(final Transport transport, + final SSLContext sslContext, + final Port port, + final Set<AmqpProtocolVersion> supported, + final AmqpProtocolVersion defaultSupportedProtocolReply) + { + _transport = transport; + _sslContext = sslContext; + _port = port; + _supported = supported; + _defaultSupportedProtocolReply = defaultSupportedProtocolReply; + _factory = new MultiVersionProtocolEngineFactory( + _port.getParent(Broker.class), null, + (Boolean)_port.getAttribute(Port.WANT_CLIENT_AUTH), + (Boolean)_port.getAttribute(Port.NEED_CLIENT_AUTH), + _supported, + _defaultSupportedProtocolReply, + _port, + _transport); + + } + + @Override + public void start() + { + _server = new Server(); + + Connector connector = null; + + + if (_transport == Transport.WS) + { + connector = new SelectChannelConnector(); + } + else if (_transport == Transport.WSS) + { + SslContextFactory factory = new SslContextFactory(); + factory.setSslContext(_sslContext); + factory.setNeedClientAuth(true); + connector = new SslSelectChannelConnector(factory); + } + else + { + throw new IllegalArgumentException("Unexpected transport on port " + _port.getName() + ":" + _transport); + } + String bindingAddress = _port.getBindingAddress(); + if(bindingAddress != null && !bindingAddress.trim().equals("") && !bindingAddress.trim().equals("*")) + { + connector.setHost(bindingAddress.trim()); + } + connector.setPort(_port.getPort()); + _server.addConnector(connector); + + WebSocketHandler wshandler = new WebSocketHandler() + { + @Override + public WebSocket doWebSocketConnect(final HttpServletRequest request, final String protocol) + { + + Principal principal = null; + if(Collections.list(request.getAttributeNames()).contains("javax.servlet.request.X509Certificate")) + { + X509Certificate[] certificates = + (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate"); + if(certificates != null && certificates.length != 0) + { + principal = certificates[0].getSubjectDN(); + } + } + + SocketAddress remoteAddress = new InetSocketAddress(request.getRemoteHost(), request.getRemotePort()); + SocketAddress localAddress = new InetSocketAddress(request.getLocalName(), request.getLocalPort()); + return AMQP_WEBSOCKET_SUBPROTOCOL.equals(protocol) ? new AmqpWebSocket(_transport, localAddress, remoteAddress, principal) : null; + } + }; + + _server.setHandler(wshandler); + try + { + _server.start(); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + + } + + @Override + public void close() + { + + } + + private class AmqpWebSocket implements WebSocket,WebSocket.OnBinaryMessage + { + private final SocketAddress _localAddress; + private final SocketAddress _remoteAddress; + private final Principal _userPrincipal; + private Connection _connection; + private final Transport _transport; + private ProtocolEngine _engine; + + private AmqpWebSocket(final Transport transport, + final SocketAddress localAddress, + final SocketAddress remoteAddress, + final Principal userPrincipal) + { + _transport = transport; + _localAddress = localAddress; + _remoteAddress = remoteAddress; + _userPrincipal = userPrincipal; + } + + @Override + public void onMessage(final byte[] data, final int offset, final int length) + { + _engine.received(ByteBuffer.wrap(data, offset, length).slice()); + } + + @Override + public void onOpen(final Connection connection) + { + _connection = connection; + + _engine = _factory.newProtocolEngine(); + + final ConnectionWrapper connectionWrapper = + new ConnectionWrapper(connection, _localAddress, _remoteAddress); + connectionWrapper.setPeerPrincipal(_userPrincipal); + _engine.setNetworkConnection(connectionWrapper, connectionWrapper.getSender()); + + } + + @Override + public void onClose(final int closeCode, final String message) + { + _engine.closed(); + } + } + + private class ConnectionWrapper implements NetworkConnection, Sender<ByteBuffer> + { + private final WebSocket.Connection _connection; + private final SocketAddress _localAddress; + private final SocketAddress _remoteAddress; + private Principal _principal; + private int _maxWriteIdle; + private int _maxReadIdle; + + public ConnectionWrapper(final WebSocket.Connection connection, + final SocketAddress localAddress, + final SocketAddress remoteAddress) + { + _connection = connection; + _localAddress = localAddress; + _remoteAddress = remoteAddress; + } + + @Override + public Sender<ByteBuffer> getSender() + { + return this; + } + + @Override + public void start() + { + + } + + @Override + public void setIdleTimeout(final int i) + { + + } + + @Override + public void send(final ByteBuffer msg) + { + try + { + _connection.sendMessage(msg.array(),msg.arrayOffset()+msg.position(),msg.remaining()); + } + catch (IOException e) + { + close(); + } + } + + @Override + public void flush() + { + + } + + @Override + public void close() + { + _connection.close(); + } + + @Override + public SocketAddress getRemoteAddress() + { + return _remoteAddress; + } + + @Override + public SocketAddress getLocalAddress() + { + return _localAddress; + } + + @Override + public void setMaxWriteIdle(final int sec) + { + _maxWriteIdle = sec; + } + + @Override + public void setMaxReadIdle(final int sec) + { + _maxReadIdle = sec; + } + + @Override + public Principal getPeerPrincipal() + { + return _principal; + } + + @Override + public int getMaxReadIdle() + { + return _maxReadIdle; + } + + @Override + public int getMaxWriteIdle() + { + return _maxWriteIdle; + } + + void setPeerPrincipal(final Principal peerPrincipal) + { + _principal = peerPrincipal; + } + } +} diff --git a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java new file mode 100644 index 0000000000..02d1100315 --- /dev/null +++ b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProvider.java @@ -0,0 +1,51 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport.websocket; + +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.protocol.AmqpProtocolVersion; +import org.apache.qpid.server.transport.AcceptingTransport; +import org.apache.qpid.server.transport.TransportProvider; + +import javax.net.ssl.SSLContext; +import java.util.Set; + +class WebSocketTransportProvider implements TransportProvider +{ + public WebSocketTransportProvider() + { + } + + @Override + public AcceptingTransport createTransport(final Set<Transport> transports, + final SSLContext sslContext, + final Port port, + final Set<AmqpProtocolVersion> supported, + final AmqpProtocolVersion defaultSupportedProtocolReply) + { + return new WebSocketProvider(transports.iterator().next(), + sslContext, + port, + supported, + defaultSupportedProtocolReply); + } +} diff --git a/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProviderFactory.java b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProviderFactory.java new file mode 100644 index 0000000000..e7c5a786b5 --- /dev/null +++ b/qpid/java/broker-plugins/websocket/src/main/java/org/apache/qpid/server/transport/websocket/WebSocketTransportProviderFactory.java @@ -0,0 +1,56 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.transport.websocket; + +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.plugin.TransportProviderFactory; +import org.apache.qpid.server.transport.TransportProvider; + +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Set; + +public class WebSocketTransportProviderFactory implements TransportProviderFactory +{ + + private static final String TYPE = "Websocket"; + + @Override + public Set<Set<Transport>> getSupportedTransports() + { + return new HashSet<Set<Transport>>(Arrays.asList(EnumSet.of(Transport.WS), + EnumSet.of(Transport.WSS))); + } + + @Override + public TransportProvider getTransportProvider(final Set<Transport> transports) + { + return new WebSocketTransportProvider(); + } + + @Override + public String getType() + { + return TYPE; + } +} diff --git a/qpid/java/broker-plugins/websocket/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.TransportProviderFactory b/qpid/java/broker-plugins/websocket/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.TransportProviderFactory new file mode 100644 index 0000000000..55b88cc7be --- /dev/null +++ b/qpid/java/broker-plugins/websocket/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.TransportProviderFactory @@ -0,0 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +org.apache.qpid.server.transport.websocket.WebSocketTransportProviderFactory
\ No newline at end of file diff --git a/qpid/java/build.deps b/qpid/java/build.deps index 67a67783c9..58dea7009e 100644 --- a/qpid/java/build.deps +++ b/qpid/java/build.deps @@ -74,6 +74,7 @@ amqp-1-0-common.libs= amqp-1-0-client.libs= amqp-1-0-client-example.libs=${commons-cli} amqp-1-0-client-jms.libs=${geronimo-jms} +amqp-1-0-client-websocket.libs = ${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jetty-websocket} tools.libs=${commons-configuration.libs} ${log4j} broker-core.libs=${commons-cli} ${commons-logging} ${log4j} ${slf4j-log4j} \ ${xalan} ${derby-db} ${commons-configuration.libs} \ @@ -82,7 +83,7 @@ broker-core.libs=${commons-cli} ${commons-logging} ${log4j} ${slf4j-log4j} \ #Borrow the broker-core libs, hack for release binary generation broker.libs=${broker-core.libs} -broker-plugins-management-http.libs=${jetty} ${jetty-continuation} ${jetty-security} ${jetty-http} ${jetty-io} ${jetty-servlet} ${jetty-util} ${servlet-api} ${jackson-core} ${jackson-mapper} ${dojo} +broker-plugins-management-http.libs=${dojo} broker-plugins.libs=${log4j} ${commons-configuration.libs} test.libs=${slf4j-log4j} ${log4j} ${junit} ${slf4j-api} ${mockito-all} diff --git a/qpid/java/build.xml b/qpid/java/build.xml index e761677f6d..219029b908 100644 --- a/qpid/java/build.xml +++ b/qpid/java/build.xml @@ -34,7 +34,7 @@ <findSubProjects name="broker-plugins" dir="broker-plugins" excludes="${broker-plugins-exclude}"/> <findSubProjects name="client-plugins" dir="client-plugins"/> - <property name="modules.core" value="qpid-test-utils common management/common amqp-1-0-common broker-core broker client amqp-1-0-client amqp-1-0-client-jms tools"/> + <property name="modules.core" value="qpid-test-utils common management/common amqp-1-0-common broker-core broker client amqp-1-0-client amqp-1-0-client-jms amqp-1-0-client-websocket tools"/> <property name="modules.examples" value="client/example management/example amqp-1-0-client/example amqp-1-0-client-jms/example"/> <property name="modules.tests" value="systests perftests"/> <property name="modules.plugin" value="${broker-plugins} ${client-plugins}"/> diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java index 018a1ec851..8224c77ba9 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/AMQSession.java @@ -109,7 +109,7 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic /** System property to enable failure if strict AMQP compliance is violated. */ public static final String STRICT_AMQP_FATAL = "STRICT_AMQP_FATAL"; - /** Strickt AMQP failure default. */ + /** Strict AMQP failure default. */ public static final String STRICT_AMQP_FATAL_DEFAULT = "true"; /** System property to enable immediate message prefetching. */ @@ -124,6 +124,9 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic private final boolean _declareExchanges = Boolean.parseBoolean(System.getProperty(ClientProperties.QPID_DECLARE_EXCHANGES_PROP_NAME, "true")); + private final boolean _bindQueues = + Boolean.parseBoolean(System.getProperty(ClientProperties.QPID_BIND_QUEUES_PROP_NAME, "true")); + private final boolean _useAMQPEncodedMapMessage; private final boolean _useAMQPEncodedStreamMessage; @@ -2870,10 +2873,13 @@ public abstract class AMQSession<C extends BasicMessageConsumer, P extends Basic { declareQueue(amqd, consumer.isNoLocal(), nowait); } - if(!isBound(amqd.getExchangeName(), amqd.getAMQQueueName(), amqd.getRoutingKey())) + if (_bindQueues) { - bindQueue(amqd.getAMQQueueName(), amqd.getRoutingKey(), - amqd instanceof AMQTopic ? consumer.getArguments() : null, amqd.getExchangeName(), amqd, nowait); + if(!isBound(amqd.getExchangeName(), amqd.getAMQQueueName(), amqd.getRoutingKey())) + { + bindQueue(amqd.getAMQQueueName(), amqd.getRoutingKey(), + amqd instanceof AMQTopic ? consumer.getArguments() : null, amqd.getExchangeName(), amqd, nowait); + } } } diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java index f733e6bbca..f735895c81 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer_0_8.java @@ -116,7 +116,7 @@ public class BasicMessageConsumer_0_8 extends BasicMessageConsumer<UnprocessedMe { return getMessageFactory().createMessage(messageFrame.getDeliveryTag(), - messageFrame.isRedelivered(), messageFrame.getExchange(), + messageFrame.isRedelivered(), messageFrame.getExchange() == null ? AMQShortString.EMPTY_STRING : messageFrame.getExchange(), messageFrame.getRoutingKey(), messageFrame.getContentHeader(), messageFrame.getBodies(), _queueDestinationCache, _topicDestinationCache); diff --git a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java index ad19b0e620..784c33cf02 100644 --- a/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java +++ b/qpid/java/client/src/main/java/org/apache/qpid/client/message/AbstractAMQMessageDelegate.java @@ -60,7 +60,10 @@ public abstract class AbstractAMQMessageDelegate implements AMQMessageDelegate _exchangeTypeToDestinationType.put(ExchangeDefaults.FANOUT_EXCHANGE_CLASS, AMQDestination.TOPIC_TYPE); _exchangeTypeToDestinationType.put(ExchangeDefaults.HEADERS_EXCHANGE_CLASS, AMQDestination.QUEUE_TYPE); - _exchangeMap.put("", new ExchangeInfo("","",AMQDestination.QUEUE_TYPE)); + _exchangeMap.put(ExchangeDefaults.DEFAULT_EXCHANGE_NAME, + new ExchangeInfo(ExchangeDefaults.DEFAULT_EXCHANGE_NAME, + ExchangeDefaults.DIRECT_EXCHANGE_CLASS, + AMQDestination.QUEUE_TYPE)); _exchangeMap.put(ExchangeDefaults.DIRECT_EXCHANGE_NAME, new ExchangeInfo(ExchangeDefaults.DIRECT_EXCHANGE_NAME, diff --git a/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java b/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java index 1ec217e468..c9af1de6a7 100644 --- a/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java +++ b/qpid/java/client/src/test/java/org/apache/qpid/client/transport/TestNetworkConnection.java @@ -75,11 +75,6 @@ public class TestNetworkConnection implements NetworkConnection } @Override - public void setPeerPrincipal(Principal principal) - { - } - - @Override public Principal getPeerPrincipal() { return null; diff --git a/qpid/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java b/qpid/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java index b43b9d450b..0e7d061ba7 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/configuration/ClientProperties.java @@ -230,6 +230,12 @@ public class ClientProperties * producer/consumer creation when using BindingURLs. */ public static final String QPID_DECLARE_EXCHANGES_PROP_NAME = "qpid.declare_exchanges"; + /** + * System property to control whether the client will bind queues during + * consumer creation when using BindingURLs. + */ + public static final String QPID_BIND_QUEUES_PROP_NAME = "qpid.bind_queues"; + public static final String VERIFY_QUEUE_ON_SEND = "qpid.verify_queue_on_send"; public static final String QPID_MAX_CACHED_ADDR_OPTION_STRINGS = "qpid.max_cached_address_option_strings"; diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java index 050d194c47..1b8bbebdf5 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/NetworkConnection.java @@ -47,8 +47,6 @@ public interface NetworkConnection void setMaxReadIdle(int sec); - void setPeerPrincipal(Principal principal); - Principal getPeerPrincipal(); int getMaxReadIdle(); diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java index f5c09ac2cc..4a4bd3ddc0 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkConnection.java @@ -24,11 +24,14 @@ import java.net.Socket; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.security.Principal; + +import javax.net.ssl.SSLPeerUnverifiedException; +import javax.net.ssl.SSLSocket; + import org.apache.qpid.transport.Receiver; import org.apache.qpid.transport.Sender; import org.apache.qpid.transport.network.Ticker; import org.apache.qpid.transport.network.NetworkConnection; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -39,15 +42,11 @@ public class IoNetworkConnection implements NetworkConnection private final long _timeout; private final IoSender _ioSender; private final IoReceiver _ioReceiver; - private Principal _principal; private int _maxReadIdle; private int _maxWriteIdle; - - public IoNetworkConnection(Socket socket, Receiver<ByteBuffer> delegate, - int sendBufferSize, int receiveBufferSize, long timeout) - { - this(socket,delegate,sendBufferSize,receiveBufferSize,timeout,null); - } + private Principal _principal; + private boolean _principalChecked; + private final Object _lock = new Object(); public IoNetworkConnection(Socket socket, Receiver<ByteBuffer> delegate, int sendBufferSize, int receiveBufferSize, long timeout, Ticker ticker) @@ -108,15 +107,29 @@ public class IoNetworkConnection implements NetworkConnection } @Override - public void setPeerPrincipal(Principal principal) - { - _principal = principal; - } - - @Override public Principal getPeerPrincipal() { - return _principal; + synchronized (_lock) + { + if(!_principalChecked) + { + if(_socket instanceof SSLSocket) + { + try + { + _principal = ((SSLSocket) _socket).getSession().getPeerPrincipal(); + } + catch(SSLPeerUnverifiedException e) + { + _principal = null; + } + } + + _principalChecked = true; + } + + return _principal; + } } @Override diff --git a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java index 18a8bf2779..4ccb88bbf8 100644 --- a/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java +++ b/qpid/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java @@ -146,7 +146,7 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet } catch (IOException e) { - throw new TransportException("Unable to start server socket", e); + throw new TransportException("Failed to start AMQP on port : " + config, e); } } @@ -245,19 +245,6 @@ public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNet ticker.setConnection(connection); - if(_sslContext != null && socket instanceof SSLSocket) - { - try - { - Principal peerPrincipal = ((SSLSocket) socket).getSession().getPeerPrincipal(); - connection.setPeerPrincipal(peerPrincipal); - } - catch(SSLPeerUnverifiedException e) - { - // ignore - } - } - engine.setNetworkConnection(connection, connection.getSender()); connection.start(); diff --git a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java index 5cdd7a8597..a445cff0a7 100644 --- a/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java +++ b/qpid/java/common/src/test/java/org/apache/qpid/transport/network/io/IdleTimeoutTickerTest.java @@ -233,11 +233,6 @@ public class IdleTimeoutTickerTest extends TestCase implements TransportActivity } @Override - public void setPeerPrincipal(Principal principal) - { - } - - @Override public Principal getPeerPrincipal() { return null; diff --git a/qpid/java/ivy.nexus.xml b/qpid/java/ivy.nexus.xml index d492169ff3..ee0ec27d48 100644 --- a/qpid/java/ivy.nexus.xml +++ b/qpid/java/ivy.nexus.xml @@ -135,6 +135,12 @@ <artifact name="qpid-amqp-1-0-client-jms" type="jar.asc" ext="jar.asc"/> <artifact name="qpid-amqp-1-0-client-jms" type="source" ext="jar" e:classifier="sources"/> <artifact name="qpid-amqp-1-0-client-jms" type="source.asc" ext="jar.asc" e:classifier="sources"/> + <artifact name="qpid-amqp-1-0-client-websocket" type="pom" ext="pom"/> + <artifact name="qpid-amqp-1-0-client-websocket" type="pom.asc" ext="pom.asc"/> + <artifact name="qpid-amqp-1-0-client-websocket" type="jar" ext="jar"/> + <artifact name="qpid-amqp-1-0-client-websocket" type="jar.asc" ext="jar.asc"/> + <artifact name="qpid-amqp-1-0-client-websocket" type="source" ext="jar" e:classifier="sources"/> + <artifact name="qpid-amqp-1-0-client-websocket" type="source.asc" ext="jar.asc" e:classifier="sources"/> <artifact name="qpid-management-common" type="pom" ext="pom"/> <artifact name="qpid-management-common" type="pom.asc" ext="pom.asc"/> <artifact name="qpid-management-common" type="jar" ext="jar"/> diff --git a/qpid/java/jca/README-GERONIMO.txt b/qpid/java/jca/README-GERONIMO.txt index 3b72a7e094..504d33eab8 100644 --- a/qpid/java/jca/README-GERONIMO.txt +++ b/qpid/java/jca/README-GERONIMO.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Resource Adapter Apache Geronimo 2.x Installation and Configuration Instructions diff --git a/qpid/java/jca/README-JBOSS-EAP6.txt b/qpid/java/jca/README-JBOSS-EAP6.txt index 219bfb6468..cd5f42d9aa 100644 --- a/qpid/java/jca/README-JBOSS-EAP6.txt +++ b/qpid/java/jca/README-JBOSS-EAP6.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Resource Adapter JBoss EAP 6.x Installation and Configuration Instructions diff --git a/qpid/java/jca/README-JBOSS.txt b/qpid/java/jca/README-JBOSS.txt index 717565b938..80d6573b33 100644 --- a/qpid/java/jca/README-JBOSS.txt +++ b/qpid/java/jca/README-JBOSS.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Resource Adapter JBoss EAP 5.x Installation and Configuration Instructions diff --git a/qpid/java/jca/README.txt b/qpid/java/jca/README.txt index d4c14112a4..86f548ce39 100644 --- a/qpid/java/jca/README.txt +++ b/qpid/java/jca/README.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Resource Adapter Installation/Configuration Instructions Overview diff --git a/qpid/java/jca/example/README-EXAMPLE.txt b/qpid/java/jca/example/README-EXAMPLE.txt index fd0af585ef..7ff331116c 100644 --- a/qpid/java/jca/example/README-EXAMPLE.txt +++ b/qpid/java/jca/example/README-EXAMPLE.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Example Overview diff --git a/qpid/java/jca/example/README-GERONIMO.txt b/qpid/java/jca/example/README-GERONIMO.txt index d58d034c79..51cf2c4e9c 100644 --- a/qpid/java/jca/example/README-GERONIMO.txt +++ b/qpid/java/jca/example/README-GERONIMO.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Example - Apache Geronimo 2.x Overview diff --git a/qpid/java/jca/example/README-GLASSFISH.txt b/qpid/java/jca/example/README-GLASSFISH.txt index 1b73ba68fd..ccbc257c04 100644 --- a/qpid/java/jca/example/README-GLASSFISH.txt +++ b/qpid/java/jca/example/README-GLASSFISH.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Example - Glassfish 3.x Overview diff --git a/qpid/java/jca/example/README-JBOSS.txt b/qpid/java/jca/example/README-JBOSS.txt index e23b3ba308..ffc750a078 100644 --- a/qpid/java/jca/example/README-JBOSS.txt +++ b/qpid/java/jca/example/README-JBOSS.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Example - JBoss EAP 5.x, JBoss 5.x, 6.x Overview diff --git a/qpid/java/jca/example/README-JBOSS7.txt b/qpid/java/jca/example/README-JBOSS7.txt index 5234a0b293..ae12078cd0 100644 --- a/qpid/java/jca/example/README-JBOSS7.txt +++ b/qpid/java/jca/example/README-JBOSS7.txt @@ -1,3 +1,21 @@ +# +# 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. +# Qpid JCA Example - JBoss AS 7 Overview diff --git a/qpid/java/jca/example/conf/glassfish-ejb-jar.xml b/qpid/java/jca/example/conf/glassfish-ejb-jar.xml index e3ea140472..3416e2b4ae 100644 --- a/qpid/java/jca/example/conf/glassfish-ejb-jar.xml +++ b/qpid/java/jca/example/conf/glassfish-ejb-jar.xml @@ -1,4 +1,24 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> <!DOCTYPE glassfish-ejb-jar PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 EJB 3.1//EN" "http://glassfish.org/dtds/glassfish-ejb-jar_3_1-1.dtd"> <glassfish-ejb-jar> <enterprise-beans> diff --git a/qpid/java/jca/example/conf/glassfish-resources.xml b/qpid/java/jca/example/conf/glassfish-resources.xml index 9eab4302d5..ce1fc5b764 100644 --- a/qpid/java/jca/example/conf/glassfish-resources.xml +++ b/qpid/java/jca/example/conf/glassfish-resources.xml @@ -1,4 +1,24 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> <!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd"> <resources> diff --git a/qpid/java/jca/example/conf/glassfish-web.xml b/qpid/java/jca/example/conf/glassfish-web.xml index 950ee73d51..3aa49c01b1 100644 --- a/qpid/java/jca/example/conf/glassfish-web.xml +++ b/qpid/java/jca/example/conf/glassfish-web.xml @@ -1,4 +1,24 @@ <?xml version="1.0" encoding="UTF-8"?> +<!-- + - + - Licensed to the Apache Software Foundation (ASF) under one + - or more contributor license agreements. See the NOTICE file + - distributed with this work for additional information + - regarding copyright ownership. The ASF licenses this file + - to you under the Apache License, Version 2.0 (the + - "License"); you may not use this file except in compliance + - with the License. You may obtain a copy of the License at + - + - http://www.apache.org/licenses/LICENSE-2.0 + - + - Unless required by applicable law or agreed to in writing, + - software distributed under the License is distributed on an + - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + - KIND, either express or implied. See the License for the + - specific language governing permissions and limitations + - under the License. + - + --> <!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd"> <glassfish-web-app> diff --git a/qpid/java/module.xml b/qpid/java/module.xml index 28c31f967d..6d3f08a386 100644 --- a/qpid/java/module.xml +++ b/qpid/java/module.xml @@ -584,8 +584,8 @@ <copylist todir="${build.lib}" dir="${project.root}" files="${module.libs}"/> </target> - - <target name="libs-release" description="copy dependencies into module release"> + + <target name="libs-release-basic" description="copy dependencies into module release"> <!-- Copy the module dependencies --> <echo message="${module.libs}"/> <copylist todir="${module.release}/lib" dir="${project.root}" files="${module.libs}"/> @@ -594,10 +594,18 @@ <!-- Copy the jar for this module --> <copy todir="${module.release}/lib" failonerror="true"> <fileset file="${module.jar}"/> + </copy> + </target> + + <target name="libs-release-module-depends" description="copy dependencies into module release" unless="release.exclude.module.deps"> + <copy todir="${module.release}/lib" failonerror="true"> <fileset dir="${build.lib}" includes="${module.depends.jars}"/> </copy> </target> + <target name="libs-release" description="copy dependencies into module release" depends="libs-release-basic,libs-release-module-depends"> + </target> + <target name="resources" description="copy resources into build tree"> <copy todir="${build}" failonerror="false" flatten="true"> <fileset dir="${basedir}${file.separator}.." includes="${resources}"/> diff --git a/qpid/java/pom.xml b/qpid/java/pom.xml index 7ea1db66aa..1b313b3514 100644 --- a/qpid/java/pom.xml +++ b/qpid/java/pom.xml @@ -29,22 +29,24 @@ <packaging>pom</packaging> <!-- ###### TODO ###### - + - Fix the jca/rar pom module name, it should be qpid-ra not qpid-rar. + - Add the Excludes files, log4j config, etc test resources to a module (qpid-test-utils?) which can be + used (extracted?) by the others to prevent them having to reference outside their directly for the files. + - Fix what the systests/perftests do to copy the test-profiles dir to the necessary location. + - Fix the log4j configuration property to work with all the modules, resolve the currently generated log4j exceptions during test runs. - Add project details such as Website, Mailing List, SCM. - - Test deploying the modules to a local Nexus instance (overriding the repo properties). - - Dont deploy modules we aren't already doing so. - - Decide on name for this parent module. - Fix the version numbers in all the modules. - - Align the XML in the pom files consistently, fix whitepsace errors. - - Complete setting properties for the dependency version numbers. - - Use dependancy management sections to control the version numbers. - - Add LICENCE, NOTICE, README files to the binary assemblies. - - Add the test profiles, log4j config etc to a module which can be extracted by the others. - - Then fix log4j configuration property to work with all modules. - - Then fix what the systests/perftests do to copy the test-profiles dir to the encessary location. + - Decide on a final name for this parent module, qpid-project isnt necessarily appropriate given it doesnt encompass the whole project. + - Test deploying the modules to a local Nexus instance (by overriding the repo properties locally). + - Ensure we dont deploy modules we aren't already doing so, it will make changing them later less of a pain for everyone. - Figure out dependency setup for optional bdbstore tests. - - Add the other test profiles + - Add the other test profiles, e.g. derby and other protocols. - Generate HTML reports of the test results + - Decide on how to handle the surefire report target re-running the tests (there is a report-only task that doesnt, provided as a workaround) + - Add LICENCE, NOTICE, README files to the binary assemblies. + - Complete setting properties for all the dependency version numbers from the modules. + - Use dependancy management sections to control the version numbers? + - Align the XML in the pom files consistently, fix whitepsace errors. === Once the Ant build is removed === - Move all the resources to be in the /src/foo/resources folders. @@ -55,6 +57,7 @@ - Fix the tests not to be dependant on the working dir being the java dir. - Fix the tests not to be dependant on the test config/output dirs being children of qpid.home. - Remove the QBTC output file mechanics, rely on Surefire to do it? + - JUnit test profiles instead of Exludes files? --> <properties> @@ -134,6 +137,7 @@ <modules> <module>amqp-1-0-client</module> <module>amqp-1-0-client-jms</module> + <module>amqp-1-0-client-websocket</module> <module>amqp-1-0-common</module> <module>broker</module> <module>broker-core</module> @@ -150,6 +154,7 @@ <module>broker-plugins/management-http</module> <module>broker-plugins/management-jmx</module> <module>broker-plugins/memory-store</module> + <module>broker-plugins/websocket</module> <module>common</module> <module>client</module> <module>management/common</module> diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java index c999be634b..099e011054 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/protocol/MultiVersionProtocolEngineFactoryTest.java @@ -254,11 +254,6 @@ public class MultiVersionProtocolEngineFactoryTest extends QpidTestCase } @Override - public void setPeerPrincipal(Principal principal) - { - } - - @Override public Principal getPeerPrincipal() { return null; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MessageGroupQueueTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MessageGroupQueueTest.java index d5cee17fa8..cb8ced4ddb 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MessageGroupQueueTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/server/queue/MessageGroupQueueTest.java @@ -20,22 +20,28 @@ */ package org.apache.qpid.server.queue; -import org.apache.qpid.AMQException; -import org.apache.qpid.client.AMQConnection; -import org.apache.qpid.client.AMQDestination; -import org.apache.qpid.client.AMQSession; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.test.utils.QpidBrokerTestCase; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import javax.jms.Connection; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; +import javax.jms.MessageListener; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; -import java.util.HashMap; -import java.util.Map; + +import org.apache.qpid.AMQException; +import org.apache.qpid.client.AMQConnection; +import org.apache.qpid.client.AMQDestination; +import org.apache.qpid.client.AMQSession; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.jms.ConnectionURL; +import org.apache.qpid.test.utils.QpidBrokerTestCase; public class MessageGroupQueueTest extends QpidBrokerTestCase { @@ -469,7 +475,6 @@ public class MessageGroupQueueTest extends QpidBrokerTestCase } - private Message createMessage(int msg, String group) throws JMSException { Message send = producerSession.createTextMessage("Message: " + msg); @@ -478,4 +483,122 @@ public class MessageGroupQueueTest extends QpidBrokerTestCase return send; } + + /** + * Tests that when a number of new messages for a given groupid are arriving while the delivery group + * state is also in the process of being emptied (due to acking a message while using prefetch=1), that only + * 1 of a number of existing consumers is ever receiving messages for the shared group at a time. + */ + public void testSingleSharedGroupWithMultipleConsumers() throws Exception + { + final Map<String,Object> arguments = new HashMap<String, Object>(); + arguments.put(QueueArgumentsConverter.QPID_GROUP_HEADER_KEY,"group"); + arguments.put(QueueArgumentsConverter.QPID_SHARED_MSG_GROUP,"1"); + + ((AMQSession) producerSession).createQueue(new AMQShortString(QUEUE), true, false, false, arguments); + queue = (Queue) producerSession.createQueue("direct://amq.direct/"+QUEUE+"/"+QUEUE+"?durable='false'&autodelete='true'"); + + ((AMQSession) producerSession).declareAndBind((AMQDestination)queue); + producer = producerSession.createProducer(queue); + + + consumerConnection.close(); + Map<String, String> options = new HashMap<String, String>(); + options.put(ConnectionURL.OPTIONS_MAXPREFETCH, "1"); + consumerConnection = getConnectionWithOptions(options); + + int numMessages = 100; + SharedGroupTestMessageListener groupingTestMessageListener = new SharedGroupTestMessageListener(numMessages); + + Session cs1 = ((AMQConnection)consumerConnection).createSession(false, Session.AUTO_ACKNOWLEDGE); + Session cs2 = ((AMQConnection)consumerConnection).createSession(false, Session.AUTO_ACKNOWLEDGE); + Session cs3 = ((AMQConnection)consumerConnection).createSession(false, Session.AUTO_ACKNOWLEDGE); + Session cs4 = ((AMQConnection)consumerConnection).createSession(false, Session.AUTO_ACKNOWLEDGE); + + MessageConsumer consumer1 = cs1.createConsumer(queue); + consumer1.setMessageListener(groupingTestMessageListener); + MessageConsumer consumer2 = cs2.createConsumer(queue); + consumer2.setMessageListener(groupingTestMessageListener); + MessageConsumer consumer3 = cs3.createConsumer(queue); + consumer3.setMessageListener(groupingTestMessageListener); + MessageConsumer consumer4 = cs4.createConsumer(queue); + consumer4.setMessageListener(groupingTestMessageListener); + consumerConnection.start(); + + for(int i = 1; i <= numMessages; i++) + { + producer.send(createMessage(i, "GROUP")); + } + producerSession.commit(); + producer.close(); + producerSession.close(); + producerConnection.close(); + + assertTrue("Mesages not all recieved in the allowed timeframe", groupingTestMessageListener.waitForLatch(30)); + assertEquals("Unexpected concurrent processing of messages for the group", 0, groupingTestMessageListener.getConcurrentProcessingCases()); + assertNull("Unexpecte throwable in message listeners", groupingTestMessageListener.getThrowable()); + } + + public static class SharedGroupTestMessageListener implements MessageListener + { + private final CountDownLatch _count; + private final AtomicInteger _activeListeners = new AtomicInteger(); + private final AtomicInteger _concurrentProcessingCases = new AtomicInteger(); + private Throwable _throwable; + + public SharedGroupTestMessageListener(int numMessages) + { + _count = new CountDownLatch(numMessages); + } + + public void onMessage(Message message) + { + try + { + int currentActiveListeners = _activeListeners.incrementAndGet(); + + if (currentActiveListeners > 1) + { + _concurrentProcessingCases.incrementAndGet(); + + System.err.println("Concurrent processing when handling message: " + message.getIntProperty("msg")); + } + + try + { + Thread.sleep(25); + } + catch (InterruptedException e) + { + Thread.currentThread().interrupt(); + } + + _activeListeners.decrementAndGet(); + } + catch (Throwable t) + { + _throwable = t; + t.printStackTrace(); + } + finally + { + _count.countDown(); + } + } + + public boolean waitForLatch(int seconds) throws Exception + { + return _count.await(seconds, TimeUnit.SECONDS); + } + + public int getConcurrentProcessingCases() + { + return _concurrentProcessingCases.get(); + } + + public Throwable getThrowable() + { + return _throwable; + } + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java index 594239b2ee..8c0a11b7cc 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/management/jmx/ExchangeManagementTest.java @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ package org.apache.qpid.systest.management.jmx; import java.util.Collections; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java index 1294c30612..cd9f6e721b 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/Asserts.java @@ -41,6 +41,7 @@ import org.apache.qpid.server.model.Protocol; import org.apache.qpid.server.model.Queue; import org.apache.qpid.server.model.State; import org.apache.qpid.server.model.VirtualHost; +import org.apache.qpid.test.utils.TestBrokerConfiguration; public class Asserts { @@ -126,7 +127,7 @@ public class Asserts Queue.DISCARDS_TTL_MESSAGES, Queue.STATE_CHANGED); } - public static void assertAttributesPresent(Map<String, Object> data, String[] attributes) + public static void assertAttributesPresent(Map<String, Object> data, String... attributes) { for (String name : attributes) { @@ -164,6 +165,8 @@ public class Asserts Connection.INCOMING, Connection.REMOTE_PROCESS_NAME, Connection.REMOTE_PROCESS_PID, Connection.LOCAL_ADDRESS, Connection.PROPERTIES); + assertEquals("Unexpected value for connection attribute " + Connection.PORT, + TestBrokerConfiguration.ENTRY_NAME_AMQP_PORT, connectionData.get(Connection.PORT)); assertEquals("Unexpected value of connection attribute " + Connection.SESSION_COUNT_LIMIT, (int) connection.getMaximumChannelCount(), connectionData.get(Connection.SESSION_COUNT_LIMIT)); assertEquals("Unexpected value of connection attribute " + Connection.CLIENT_ID, "clientid", diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsClientCertAuthTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsClientCertAuthTest.java new file mode 100644 index 0000000000..e92b38b4e0 --- /dev/null +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/BrokerRestHttpsClientCertAuthTest.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.systest.rest; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.model.AuthenticationProvider; +import org.apache.qpid.server.model.Broker; +import org.apache.qpid.server.model.Port; +import org.apache.qpid.server.model.Protocol; +import org.apache.qpid.server.model.Transport; +import org.apache.qpid.server.security.auth.manager.AnonymousAuthenticationManagerFactory; +import org.apache.qpid.server.security.auth.manager.ExternalAuthenticationManagerFactory; +import org.apache.qpid.test.utils.TestBrokerConfiguration; + +import java.io.IOException; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; + +public class BrokerRestHttpsClientCertAuthTest extends QpidRestTestCase +{ + + @Override + public void setUp() throws Exception + { + setSystemProperty("javax.net.debug", "ssl"); + super.setUp(); + setSystemProperty("javax.net.ssl.trustStore", TRUSTSTORE); + setSystemProperty("javax.net.ssl.trustStorePassword", TRUSTSTORE_PASSWORD); + setSystemProperty("javax.net.ssl.keystore", KEYSTORE); + setSystemProperty("javax.net.ssl.keyStorePassword", KEYSTORE_PASSWORD); + + } + + @Override + protected void customizeConfiguration() throws ConfigurationException, IOException + { + super.customizeConfiguration(); + getRestTestHelper().setUseSslAuth(true); + Map<String, Object> newAttributes = new HashMap<String, Object>(); + newAttributes.put(Port.PROTOCOLS, Collections.singleton(Protocol.HTTP)); + newAttributes.put(Port.TRANSPORTS, Collections.singleton(Transport.SSL)); + newAttributes.put(Port.KEY_STORE, TestBrokerConfiguration.ENTRY_NAME_SSL_KEYSTORE); + newAttributes.put(Port.TRUST_STORES, Collections.singleton(TestBrokerConfiguration.ENTRY_NAME_SSL_TRUSTSTORE)); + newAttributes.put(Port.NEED_CLIENT_AUTH,"true"); + + + Map<String, Object> externalProviderAttributes = new HashMap<String, Object>(); + externalProviderAttributes.put(AuthenticationProvider.TYPE, ExternalAuthenticationManagerFactory.PROVIDER_TYPE); + externalProviderAttributes.put(AuthenticationProvider.NAME, EXTERNAL_AUTHENTICATION_PROVIDER); + getBrokerConfiguration().addAuthenticationProviderConfiguration(externalProviderAttributes); + + // set password authentication provider on http port for the tests + getBrokerConfiguration().setObjectAttribute(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, Port.AUTHENTICATION_PROVIDER, + EXTERNAL_AUTHENTICATION_PROVIDER); + + getBrokerConfiguration().setObjectAttributes(TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT, newAttributes); + } + + public void testGetWithHttps() throws Exception + { + Map<String, Object> saslData = getRestTestHelper().getJsonAsMap("/rest/sasl"); + + Asserts.assertAttributesPresent(saslData, "user"); + } +} diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java index bf2044aa74..46acd9e77b 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/PreferencesRestTest.java @@ -1,3 +1,23 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ package org.apache.qpid.systest.rest; import java.io.File; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java index 57398ea929..ce501adeb6 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/QpidRestTestCase.java @@ -35,6 +35,8 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase; public class QpidRestTestCase extends QpidBrokerTestCase { public static final String ANONYMOUS_AUTHENTICATION_PROVIDER = "testAnonymous"; + public static final String EXTERNAL_AUTHENTICATION_PROVIDER = "testExternal"; + public static final String TEST1_VIRTUALHOST = "test"; public static final String TEST2_VIRTUALHOST = "test2"; public static final String TEST3_VIRTUALHOST = "test3"; diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java index 7d99b30049..810b70a2ba 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/RestTestHelper.java @@ -18,6 +18,8 @@ */ package org.apache.qpid.systest.rest; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE; +import static org.apache.qpid.test.utils.TestSSLConstants.KEYSTORE_PASSWORD; import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE; import static org.apache.qpid.test.utils.TestSSLConstants.TRUSTSTORE_PASSWORD; @@ -41,6 +43,7 @@ import java.util.List; import java.util.Map; import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; import javax.net.ssl.TrustManagerFactory; @@ -65,16 +68,19 @@ import org.codehaus.jackson.type.TypeReference; public class RestTestHelper { private static final Logger LOGGER = Logger.getLogger(RestTestHelper.class); + private static final String CERT_ALIAS_APP1 = "app1"; private int _httpPort; private boolean _useSsl; + private String _username; private String _password; private File _passwdFile; + private boolean _useSslAuth; public RestTestHelper(int httpPort) { @@ -110,7 +116,30 @@ public class RestTestHelper { URL url = getManagementURL(path); HttpURLConnection httpCon = (HttpURLConnection) url.openConnection(); - if(_useSsl) + + if(_useSslAuth) + { + try + { + // We have to use a SSLSocketFactory from a new SSLContext so that we don't re-use + // the JVM's defaults that may have been initialised in previous tests. + + SSLContext sslContext = SSLContextFactory.buildClientContext( + TRUSTSTORE, TRUSTSTORE_PASSWORD, + KeyStore.getDefaultType(), + TrustManagerFactory.getDefaultAlgorithm(), + KEYSTORE, KEYSTORE_PASSWORD, KeyStore.getDefaultType(), KeyManagerFactory.getDefaultAlgorithm(), CERT_ALIAS_APP1); + + SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); + + ((HttpsURLConnection) httpCon).setSSLSocketFactory(sslSocketFactory); + } + catch (GeneralSecurityException e) + { + throw new RuntimeException(e); + } + } + else if(_useSsl) { try { @@ -475,4 +504,10 @@ public class RestTestHelper connection.connect(); return readConnectionInputStream(connection); } + + public void setUseSslAuth(final boolean useSslAuth) + { + _useSslAuth = useSslAuth; + _useSsl = true; + } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java index 1c05f17e25..61f4a1a8e2 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/systest/rest/SaslRestTest.java @@ -55,6 +55,8 @@ public class SaslRestTest extends QpidRestTestCase public void startBrokerNow() throws Exception { super.startBroker(); + + getRestTestHelper().setUsernameAndPassword(null,null); } public void testGetMechanismsWithBrokerPlainPasswordPrincipalDatabase() throws Exception @@ -71,7 +73,7 @@ public class SaslRestTest extends QpidRestTestCase { assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism)); } - assertNull("Unexpected user was returned", saslData.get("user")); + assertNull("Unexpected user was returned: " + saslData.get("user"), saslData.get("user")); } public void testGetMechanismsWithBrokerBase64MD5FilePrincipalDatabase() throws Exception @@ -89,7 +91,8 @@ public class SaslRestTest extends QpidRestTestCase { assertTrue("Mechanism " + mechanism + " is not found", mechanisms.contains(mechanism)); } - assertNull("Unexpected user was returned", saslData.get("user")); + + assertNull("Unexpected user was returned: " + saslData.get("user"), saslData.get("user")); } public void testPlainSaslAuthenticationForValidCredentials() throws Exception diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java index 1ee5b997f2..760884e654 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/client/message/JMSDestinationTest.java @@ -20,18 +20,17 @@ */ package org.apache.qpid.test.client.message; -import org.apache.qpid.client.AMQAnyDestination; import org.apache.qpid.client.AMQDestination; import org.apache.qpid.client.AMQTopic; import org.apache.qpid.client.CustomJMSXProperty; import org.apache.qpid.configuration.ClientProperties; -import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.management.common.mbeans.ManagedQueue; import org.apache.qpid.test.utils.JMXTestUtils; import org.apache.qpid.test.utils.QpidBrokerTestCase; import javax.jms.Connection; import javax.jms.Destination; +import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageListener; @@ -41,7 +40,7 @@ import javax.jms.Session; import javax.jms.Topic; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.TabularData; -import java.nio.BufferOverflowException; + import java.util.Iterator; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; @@ -88,15 +87,15 @@ public class JMSDestinationTest extends QpidBrokerTestCase _connection.start(); - Message message = consumer.receive(10000); + Message receivedMessage = consumer.receive(10000); - assertNotNull("Message should not be null", message); + assertNotNull("Message should not be null", receivedMessage); - Destination destination = message.getJMSDestination(); + Destination receivedDestination = receivedMessage.getJMSDestination(); - assertNotNull("JMSDestination should not be null", destination); + assertNotNull("JMSDestination should not be null", receivedDestination); - assertEquals("Incorrect Destination type", queue.getClass(), destination.getClass()); + assertEquals("Incorrect Destination type", queue.getClass(), receivedDestination.getClass()); } /** @@ -115,15 +114,14 @@ public class JMSDestinationTest extends QpidBrokerTestCase _connection.start(); - Message message = consumer.receive(10000); - - assertNotNull("Message should not be null", message); + Message receivedMessage = consumer.receive(10000); - Destination destination = message.getJMSDestination(); + assertNotNull("Message should not be null", receivedMessage); - assertNotNull("JMSDestination should not be null", destination); + Destination receivedDestination = receivedMessage.getJMSDestination(); - assertEquals("Incorrect Destination type", topic.getClass(), destination.getClass()); + assertNotNull("JMSDestination should not be null", receivedDestination); + assertEquals("Incorrect Destination type", topic.getClass(), receivedDestination.getClass()); } /** @@ -191,11 +189,11 @@ public class JMSDestinationTest extends QpidBrokerTestCase assertNotNull("Message should not be null", message); - Destination destination = message.getJMSDestination(); + Destination receivedDestination = message.getJMSDestination(); - assertNotNull("JMSDestination should not be null", destination); + assertNotNull("JMSDestination should not be null", receivedDestination); - assertEquals("Incorrect Destination type", queue.getClass(), destination.getClass()); + assertEquals("Incorrect Destination type", queue.getClass(), receivedDestination.getClass()); } finally @@ -238,11 +236,11 @@ public class JMSDestinationTest extends QpidBrokerTestCase assertNotNull("Message should not be null", _message); - Destination destination = _message.getJMSDestination(); + Destination receivedDestination = _message.getJMSDestination(); - assertNotNull("JMSDestination should not be null", destination); + assertNotNull("JMSDestination should not be null", receivedDestination); - assertEquals("Incorrect Destination type", queue.getClass(), destination.getClass()); + assertEquals("Incorrect Destination type", queue.getClass(), receivedDestination.getClass()); } /** @@ -305,17 +303,7 @@ public class JMSDestinationTest extends QpidBrokerTestCase // b) we can actually send without a BufferOverFlow. MessageProducer producer = session08.createProducer(queue); - - try - { - producer.send(message); - } - catch (BufferOverflowException bofe) - { - // Print the stack trace so we can validate where the execption occured. - bofe.printStackTrace(); - fail("BufferOverflowException thrown during send"); - } + producer.send(message); message = consumer.receive(1000); @@ -327,45 +315,45 @@ public class JMSDestinationTest extends QpidBrokerTestCase } - /** - * Send a message to a custom exchange and then verify - * the message received has the proper destination set - * - * @throws Exception - */ - public void testGetDestinationWithCustomExchange() throws Exception + public void testQueueWithBindingUrlUsingCustomExchange() throws Exception { - - AMQDestination dest = new AMQAnyDestination(new AMQShortString("my-exchange"), - new AMQShortString("direct"), - new AMQShortString("test"), - false, - false, - new AMQShortString("test"), - false, - new AMQShortString[]{new AMQShortString("test")}); - - // to force the creation of my-exchange. - sendMessage(_session, dest, 1); - - MessageProducer prod = _session.createProducer(dest); + String exchangeName = "exch_" + getTestQueueName(); + String queueName = "queue_" + getTestQueueName(); + String address = String.format("direct://%s/%s/%s?routingkey='%s'", exchangeName, queueName, queueName, queueName); + sendReceive(address); + } + + public void testQueueWithBindingUrlUsingAmqDirectExchange() throws Exception + { + String queueName = getTestQueueName(); + String address = String.format("direct://amq.direct/%s/%s?routingkey='%s'", queueName, queueName, queueName); + sendReceive(address); + } + + public void testQueueWithBindingUrlUsingDefaultExchange() throws Exception + { + String queueName = getTestQueueName(); + String address = String.format("direct:///%s/%s?routingkey='%s'", queueName, queueName, queueName); + sendReceive(address); + } + + private void sendReceive(String address) throws JMSException, Exception + { + Destination dest = _session.createQueue(address); MessageConsumer consumer = _session.createConsumer(dest); - + _connection.start(); sendMessage(_session, dest, 1); - - Message message = consumer.receive(10000); - assertNotNull("Message should not be null", message); + Message receivedMessage = consumer.receive(10000); - Destination destination = message.getJMSDestination(); + assertNotNull("Message should not be null", receivedMessage); - assertNotNull("JMSDestination should not be null", destination); + Destination receivedDestination = receivedMessage.getJMSDestination(); - assertEquals("Incorrect Destination name", "my-exchange", dest.getExchangeName().asString()); - assertEquals("Incorrect Destination type", "direct", dest.getExchangeClass().asString()); - assertEquals("Incorrect Routing Key", "test", dest.getRoutingKey().asString()); + assertNotNull("JMSDestination should not be null", receivedDestination); + assertEquals("JMSDestination should match that sent", address, receivedDestination.toString()); } } diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java index 734e3f2268..77df6c58d9 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/DynamicQueueExchangeCreateTest.java @@ -31,6 +31,7 @@ import org.apache.qpid.test.utils.QpidBrokerTestCase; import org.apache.qpid.url.BindingURL; import javax.jms.Connection; +import javax.jms.InvalidDestinationException; import javax.jms.JMSException; import javax.jms.Queue; import javax.jms.Session; @@ -158,6 +159,28 @@ public class DynamicQueueExchangeCreateTest extends QpidBrokerTestCase assertFalse("exchange should not exist", _jmxUtils.doesManagedObjectExist(exchangeObjectName2)); } + public void testQueueNotBoundDuringConsumerCreation() throws Exception + { + setSystemProperty(ClientProperties.QPID_BIND_QUEUES_PROP_NAME, "false"); + setSystemProperty(ClientProperties.VERIFY_QUEUE_ON_SEND, "true"); + + Connection connection = getConnection(); + + Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); + + Queue queue = session.createQueue(getTestQueueName()); + session.createConsumer(queue); + + try + { + session.createProducer(queue).send(session.createMessage()); + fail("JMSException should be thrown as the queue does not exist"); + } + catch (InvalidDestinationException ide) + { + //PASS + } + } private void checkExceptionErrorCode(JMSException original, AMQConstant code) { Exception linked = original.getLinkedException(); diff --git a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java index e893a58282..3ffa73b9b7 100644 --- a/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java +++ b/qpid/java/systests/src/main/java/org/apache/qpid/test/unit/client/protocol/AMQProtocolSessionTest.java @@ -154,11 +154,6 @@ public class AMQProtocolSessionTest extends QpidBrokerTestCase } @Override - public void setPeerPrincipal(Principal principal) - { - } - - @Override public Principal getPeerPrincipal() { return null; |
