diff options
| author | Rajith Muditha Attapattu <rajith@apache.org> | 2007-09-14 20:43:16 +0000 |
|---|---|---|
| committer | Rajith Muditha Attapattu <rajith@apache.org> | 2007-09-14 20:43:16 +0000 |
| commit | 8f6c5c6124db155ebad4533d66e1d2135ab21396 (patch) | |
| tree | 817e5dab8d5d1680e1cbd1cf201cea395c7d1a89 /java | |
| parent | b4ae4c1493c29e38f096eb8c973d7681dff55778 (diff) | |
| download | qpid-python-8f6c5c6124db155ebad4533d66e1d2135ab21396.tar.gz | |
Took out the URL parsing logic from the AMQConnectionURL and moved in two Parser classes.
The Connection Type (0-8 or 0-10) is decided based on the URL scheme if AMQConnection is created by passing a URL.
In other cases it will be based on a jvm switch. Other constructors in AMQConnection internally constructs an 0-8 URL and call the constrcutor with a URL.
In that case it is difficult to figure out the type of connection with out additional information.
The additional information commes in the form of the following jvm arguments
SwitchCon - enables this switch
0-10 - creates an 0-10 connection and the absence of it creates an 0-8 connection
This was done to minimize any impact on the test code.
currently only one code path can be tested at a given time.
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/trunk/qpid@575789 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java')
12 files changed, 807 insertions, 252 deletions
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java index c04380ba8c..b97b1fa253 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQBrokerDetails.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -23,6 +23,7 @@ package org.apache.qpid.client; import java.net.URI; import java.net.URISyntaxException; import java.util.HashMap; +import java.util.Map; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.url.URLHelper; @@ -34,8 +35,8 @@ public class AMQBrokerDetails implements BrokerDetails private int _port; private String _transport; - private HashMap<String, String> _options; - + private Map<String, String> _options; + private SSLConfiguration _sslConfiguration; public AMQBrokerDetails() @@ -214,12 +215,12 @@ public class AMQBrokerDetails implements BrokerDetails } - public String getOption(String key) + public String getProperty(String key) { return _options.get(key); } - public void setOption(String key, String value) + public void setProperty(String key, String value) { _options.put(key, value); } @@ -243,17 +244,17 @@ public class AMQBrokerDetails implements BrokerDetails public void setTimeout(long timeout) { - setOption(OPTIONS_CONNECT_TIMEOUT, Long.toString(timeout)); + setProperty(OPTIONS_CONNECT_TIMEOUT, Long.toString(timeout)); } - + public SSLConfiguration getSSLConfiguration() { - return _sslConfiguration; + return _sslConfiguration; } - + public void setSSLConfiguration(SSLConfiguration sslConfig) { - _sslConfiguration = sslConfig; + _sslConfiguration = sslConfig; } public String toString() @@ -320,23 +321,23 @@ public class AMQBrokerDetails implements BrokerDetails return optionsURL.toString(); } - + // Do we need to do a more in-depth comparison? - private boolean compareSSLConfigurations(SSLConfiguration other) + private boolean compareSSLConfigurations(SSLConfiguration other) { - boolean retval = false; - if (_sslConfiguration == null && - other == null) - { - retval = true; - } - else if (_sslConfiguration != null && - other != null) - { - retval = true; - } - - return retval; + boolean retval = false; + if (_sslConfiguration == null && + other == null) + { + retval = true; + } + else if (_sslConfiguration != null && + other != null) + { + retval = true; + } + + return retval; } public static String checkTransport(String broker) @@ -350,4 +351,14 @@ public class AMQBrokerDetails implements BrokerDetails return broker; } } + + public Map<String, String> getProperties() + { + return _options; + } + + public void setProperties(Map<String, String> props) + { + _options = props; + } } diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java index 3b330c9725..dd35929c6f 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnection.java @@ -228,19 +228,30 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect this(new AMQConnectionURL(connection), sslConfig); } - // 0-10 stuff - public AMQConnection(QpidURL connectionURL) throws AMQException - { - - } - /** * @todo Some horrible stuff going on here with setting exceptions to be non-null to detect if an exception * was thrown during the connection! Intention not clear. Use a flag anyway, not exceptions... Will fix soon. */ public AMQConnection(ConnectionURL connectionURL, SSLConfiguration sslConfig) throws AMQException { - if (Boolean.getBoolean("0-10")) + /* This JVM arg is only used for test code + Unless u pass a url it is difficult to determine which version to use + Most of the test code use an AMQConnection constructor that doesn't use + the url. So you need this switch to say which code path to test. + + Another complication is that when a constructor is called with out a url + they would construct a 0-8 url and pass into the construtor that takes a url. + + In such an instance u need the jvm argument to force an 0-10 connection + Once the 0-10 code base stabilises, 0-10 will be the default. + */ + + if (Boolean.getBoolean("SwitchCon")) + { + connectionURL.setURLVersion((Boolean.getBoolean("0-10")? ConnectionURL.URL_0_10:ConnectionURL.URL_0_8)); + } + + if (connectionURL.getURLVersion() == ConnectionURL.URL_0_10) { _delegate = new AMQConnectionDelegate_0_10(this); } @@ -287,8 +298,8 @@ public class AMQConnection extends Closeable implements Connection, QueueConnect _temporaryTopicExchangeName = connectionURL.getTemporaryTopicExchangeName(); } - _failoverPolicy = new FailoverPolicy(connectionURL); + _failoverPolicy = new FailoverPolicy(connectionURL); _protocolHandler = new AMQProtocolHandler(this); // We are not currently connected diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java index bfac194d5d..c7cc0ad394 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionFactory.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -125,21 +125,21 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF } _defaultPassword = password; } - + /** * Getter for SSLConfiguration * @return SSLConfiguration if set, otherwise null */ public final SSLConfiguration getSSLConfiguration() { - return _sslConfig; + return _sslConfig; } - + /** * Setter for SSLConfiguration * @param sslConfig config to store */ public final void setSSLConfiguration(SSLConfiguration sslConfig) { - _sslConfig = sslConfig; + _sslConfig = sslConfig; } /** @@ -234,7 +234,7 @@ public class AMQConnectionFactory implements ConnectionFactory, QueueConnectionF _virtualPath = path; } - static String getUniqueClientID() + public static String getUniqueClientID() { try { diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java index eff6360d91..8c42ec6629 100644 --- a/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java +++ b/java/client/src/main/java/org/apache/qpid/client/AMQConnectionURL.java @@ -20,26 +20,19 @@ */ package org.apache.qpid.client; -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.jms.BrokerDetails; -import org.apache.qpid.jms.ConnectionURL; -import org.apache.qpid.url.URLHelper; -import org.apache.qpid.url.URLSyntaxException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.net.URI; -import java.net.URISyntaxException; import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.StringTokenizer; +import java.util.Map; +import org.apache.qpid.client.url.URLParser_0_8; import org.apache.qpid.framing.AMQShortString; import org.apache.qpid.jms.BrokerDetails; import org.apache.qpid.jms.ConnectionURL; import org.apache.qpid.url.URLHelper; import org.apache.qpid.url.URLSyntaxException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class AMQConnectionURL implements ConnectionURL { @@ -47,8 +40,8 @@ public class AMQConnectionURL implements ConnectionURL private String _url; private String _failoverMethod; - private HashMap<String, String> _failoverOptions; - private HashMap<String, String> _options; + private Map<String, String> _failoverOptions; + private Map<String, String> _options; private List<BrokerDetails> _brokers; private String _clientName; private String _username; @@ -58,209 +51,40 @@ public class AMQConnectionURL implements ConnectionURL private AMQShortString _defaultTopicExchangeName; private AMQShortString _temporaryTopicExchangeName; private AMQShortString _temporaryQueueExchangeName; + private byte _urlVersion; public AMQConnectionURL(String fullURL) throws URLSyntaxException { + if (fullURL == null) throw new IllegalArgumentException("URL cannot be null"); _url = fullURL; _options = new HashMap<String, String>(); _brokers = new LinkedList<BrokerDetails>(); _failoverOptions = new HashMap<String, String>(); - // Connection URL format - // amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';vm://:3/virtualpath?option=\'value\'',failover='method?option=\'value\',option='value''" - // Options are of course optional except for requiring a single broker in the broker list. - try + if (!Boolean.getBoolean("SwitchCon")) { - URI connection = new URI(fullURL); - - if ((connection.getScheme() == null) || !(connection.getScheme().equalsIgnoreCase(AMQ_PROTOCOL))) - { - throw new URISyntaxException(fullURL, "Not an AMQP URL"); - } - - if ((connection.getHost() == null) || connection.getHost().equals("")) - { - String uid = AMQConnectionFactory.getUniqueClientID(); - if (uid == null) - { - throw URLHelper.parseError(-1, "Client Name not specified", fullURL); - } - else - { - setClientName(uid); - } - - } - else - { - setClientName(connection.getHost()); - } - - String userInfo = connection.getUserInfo(); - - if (userInfo == null) - { - // Fix for Java 1.5 which doesn't parse UserInfo for non http URIs - userInfo = connection.getAuthority(); - - if (userInfo != null) - { - int atIndex = userInfo.indexOf('@'); - - if (atIndex != -1) - { - userInfo = userInfo.substring(0, atIndex); - } - else - { - userInfo = null; - } - } - - } - - if (userInfo == null) - { - throw URLHelper.parseError(AMQ_PROTOCOL.length() + 3, "User information not found on url", fullURL); - } - else - { - parseUserInfo(userInfo); - } - - String virtualHost = connection.getPath(); - - if ((virtualHost != null) && (!virtualHost.equals(""))) + // We need to decided the version based on URL + if (fullURL.startsWith("qpid")) { - setVirtualHost(virtualHost); + //URLParser + _urlVersion = URL_0_10; } else { - int authLength = connection.getAuthority().length(); - int start = AMQ_PROTOCOL.length() + 3; - int testIndex = start + authLength; - if ((testIndex < fullURL.length()) && (fullURL.charAt(testIndex) == '?')) - { - throw URLHelper.parseError(start, testIndex - start, "Virtual host found", fullURL); - } - else - { - throw URLHelper.parseError(-1, "Virtual host not specified", fullURL); - } - + URLParser_0_8 urlParser = new URLParser_0_8(this); + _urlVersion = URL_0_8; } - - URLHelper.parseOptions(_options, connection.getQuery()); - - processOptions(); - } - catch (URISyntaxException uris) - { - if (uris instanceof URLSyntaxException) - { - throw (URLSyntaxException) uris; - } - - int slash = fullURL.indexOf("\\"); - - if (slash == -1) - { - throw URLHelper.parseError(uris.getIndex(), uris.getReason(), uris.getInput()); - } - else - { - if ((slash != 0) && (fullURL.charAt(slash - 1) == ':')) - { - throw URLHelper.parseError(slash - 2, fullURL.indexOf('?') - slash + 2, - "Virtual host looks like a windows path, forward slash not allowed in URL", fullURL); - } - else - { - throw URLHelper.parseError(slash, "Forward slash not allowed in URL", fullURL); - } - } - } } - private void parseUserInfo(String userinfo) throws URLSyntaxException + public byte getURLVersion() { - // user info = user:pass - - int colonIndex = userinfo.indexOf(':'); - - if (colonIndex == -1) - { - throw URLHelper.parseError(AMQ_PROTOCOL.length() + 3, userinfo.length(), - "Null password in user information not allowed.", _url); - } - else - { - setUsername(userinfo.substring(0, colonIndex)); - setPassword(userinfo.substring(colonIndex + 1)); - } - + return _urlVersion; } - private void processOptions() throws URLSyntaxException + public void setURLVersion(byte version) { - if (_options.containsKey(OPTIONS_BROKERLIST)) - { - String brokerlist = _options.get(OPTIONS_BROKERLIST); - - // brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value' - StringTokenizer st = new StringTokenizer(brokerlist, "" + URLHelper.BROKER_SEPARATOR); - - while (st.hasMoreTokens()) - { - String broker = st.nextToken(); - - _brokers.add(new AMQBrokerDetails(broker)); - } - - _options.remove(OPTIONS_BROKERLIST); - } - - if (_options.containsKey(OPTIONS_FAILOVER)) - { - String failover = _options.get(OPTIONS_FAILOVER); - - // failover='method?option='value',option='value'' - - int methodIndex = failover.indexOf('?'); - - if (methodIndex > -1) - { - _failoverMethod = failover.substring(0, methodIndex); - URLHelper.parseOptions(_failoverOptions, failover.substring(methodIndex + 1)); - } - else - { - _failoverMethod = failover; - } - - _options.remove(OPTIONS_FAILOVER); - } - - if (_options.containsKey(OPTIONS_DEFAULT_TOPIC_EXCHANGE)) - { - _defaultTopicExchangeName = new AMQShortString(_options.get(OPTIONS_DEFAULT_TOPIC_EXCHANGE)); - } - - if (_options.containsKey(OPTIONS_DEFAULT_QUEUE_EXCHANGE)) - { - _defaultQueueExchangeName = new AMQShortString(_options.get(OPTIONS_DEFAULT_QUEUE_EXCHANGE)); - } - - if (_options.containsKey(OPTIONS_TEMPORARY_QUEUE_EXCHANGE)) - { - _temporaryQueueExchangeName = new AMQShortString(_options.get(OPTIONS_TEMPORARY_QUEUE_EXCHANGE)); - } - - if (_options.containsKey(OPTIONS_TEMPORARY_TOPIC_EXCHANGE)) - { - _temporaryTopicExchangeName = new AMQShortString(_options.get(OPTIONS_TEMPORARY_TOPIC_EXCHANGE)); - } + _urlVersion = version; } public String getURL() @@ -268,11 +92,26 @@ public class AMQConnectionURL implements ConnectionURL return _url; } + public Map<String,String> getOptions() + { + return _options; + } + public String getFailoverMethod() { return _failoverMethod; } + public void setFailoverMethod(String failoverMethod) + { + _failoverMethod = failoverMethod; + } + + public Map<String,String> getFailoverOptions() + { + return _failoverOptions; + } + public String getFailoverOption(String key) { return _failoverOptions.get(key); @@ -368,21 +207,41 @@ public class AMQConnectionURL implements ConnectionURL return _defaultQueueExchangeName; } + public void setDefaultQueueExchangeName(AMQShortString defaultQueueExchangeName) + { + _defaultQueueExchangeName = defaultQueueExchangeName; + } + public AMQShortString getDefaultTopicExchangeName() { return _defaultTopicExchangeName; } + public void setDefaultTopicExchangeName(AMQShortString defaultTopicExchangeName) + { + _defaultTopicExchangeName = defaultTopicExchangeName; + } + public AMQShortString getTemporaryQueueExchangeName() { return _temporaryQueueExchangeName; } + public void setTemporaryQueueExchangeName(AMQShortString temporaryQueueExchangeName) + { + _temporaryQueueExchangeName = temporaryQueueExchangeName; + } + public AMQShortString getTemporaryTopicExchangeName() { return _temporaryTopicExchangeName; } + public void setTemporaryTopicExchangeName(AMQShortString temporaryTopicExchangeName) + { + _temporaryTopicExchangeName = temporaryTopicExchangeName; + } + public String toString() { StringBuffer sb = new StringBuffer(); diff --git a/java/client/src/main/java/org/apache/qpid/client/url/URLParser_0_10.java b/java/client/src/main/java/org/apache/qpid/client/url/URLParser_0_10.java new file mode 100644 index 0000000000..ee47ad2a94 --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/url/URLParser_0_10.java @@ -0,0 +1,419 @@ +/* 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.client.url; + +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.qpid.client.AMQBrokerDetails; +import org.apache.qpid.jms.BrokerDetails; + +/** + * The format Qpid URL is based on the AMQP one. + * The grammar is as follows: + * <p> qpid_url = "qpid:" [client_props "@"] port_addr_list ["/" future-parameters] + * <p> port_addr_list = [port_addr ","]* port_addr + * <p> port_addr = tcp_port_addr | tls_prot_addr | future_prot_addr + * <p> tcp_port_addr = tcp_id tcp_addr + * <p> tcp_id = "tcp:" | "" + * <p> tcp_addr = host [":" port] + * <p> host = <as per http://www.apps.ietf.org/> + * <p> port = number + * <p> tls_prot_addr = tls_id tls_addr + * <p> tls_id = "tls:" | "" + * <p> tls_addr = host [":" port] + * <p> future_prot_addr = future_prot_id future_prot_addr + * <p> future_prot_id = <placeholder, must end in ":". Example "sctp:"> + * <p> future_prot_addr = <placeholder, protocl-specific address> + * <p> future_parameters = <placeholder, not used in failover addresses> + * <p> client_props = [client_prop ";"]* client_prop + * <p> client_prop = prop "=" val + * <p> prop = chars as per <as per http://www.apps.ietf.org/> + * <p> val = valid as per <as per http://www.apps.ietf.org/> + * <p/> + * Ex: qpid:virtualhost=tcp:host-foo,test,client_id=foo@tcp:myhost.com:5672,virtualhost=prod; + * keystore=/opt/keystore@client_id2@tls:mysecurehost.com:5672 + */ +public class URLParser_0_10 +{ + private static final char[] URL_START_SEQ = new char[]{'q', 'p', 'i', 'd', ':'}; + private static final char PROPERTY_EQUALS_CHAR = '='; + private static final char PROPERTY_SEPARATOR_CHAR = ';'; + private static final char ADDRESS_SEPERATOR_CHAR = ','; + + //private static final char CLIENT_ID_TRANSPORT_SEPARATOR_CHAR = ':'; + private static final char TRANSPORT_HOST_SEPARATOR_CHAR = ':'; + private static final char HOST_PORT_SEPARATOR_CHAR = ':'; + private static final char AT_CHAR = '@'; + private static final char END_OF_URL_MARKER = '^'; + + enum URLParserState + { + QPID_URL_START, + ADDRESS_START, + PROPERTY_NAME, + PROPERTY_EQUALS, + PROPERTY_VALUE, + PROPERTY_SEPARATOR, + AT_CHAR, + TRANSPORT, + TRANSPORT_HOST_SEPARATOR, + HOST, + HOST_PORT_SEPARATOR, + PORT, + ADDRESS_END, + ADDRESS_SEPERATOR, + QPID_URL_END, + ERROR + } + + //-- Constructors + + private char[] _url; + private List<BrokerDetails> _brokerDetailList = new ArrayList<BrokerDetails>(); + private String _error; + private int _index = 0; + private BrokerDetails _currentBroker; + private String _currentPropName; + private boolean _endOfURL = false; + private URLParserState _currentParserState; + + public URLParser_0_10(String url) throws MalformedURLException + { + _url = (url + "END_OF_URL_MARKER").toCharArray(); + _endOfURL = false; + _currentParserState = URLParserState.QPID_URL_START; + URLParserState prevState = _currentParserState; // for error handling + try + { + while (_currentParserState != URLParserState.ERROR && _currentParserState != URLParserState.QPID_URL_END) + { + prevState = _currentParserState; + _currentParserState = next(); + } + + if (_currentParserState == URLParserState.ERROR) + { + _error = + "Invalid URL format [current_state = " + prevState + ", broker details parsed so far " + _currentBroker + " ] error at (" + _index + ") due to " + _error; + MalformedURLException ex; + ex = new MalformedURLException(_error); + throw ex; + } + } + catch (ArrayIndexOutOfBoundsException e) + { + _error = "Invalid URL format [current_state = " + prevState + ", broker details parsed so far " + _currentBroker + " ] error at (" + _index + ")"; + MalformedURLException ex = new MalformedURLException(_error); + throw ex; + } + } + + //-- interface QpidURL + public List<BrokerDetails> getAllBrokerDetails() + { + return _brokerDetailList; + } + + public String getURL() + { + return new String(_url); + } + + private URLParserState next() + { + switch (_currentParserState) + { + case QPID_URL_START: + return checkSequence(URL_START_SEQ, URLParserState.ADDRESS_START); + case ADDRESS_START: + return startAddress(); + case PROPERTY_NAME: + return extractPropertyName(); + case PROPERTY_EQUALS: + _index++; // skip the equal sign + return URLParserState.PROPERTY_VALUE; + case PROPERTY_VALUE: + return extractPropertyValue(); + case PROPERTY_SEPARATOR: + _index++; // skip "," + return URLParserState.PROPERTY_NAME; + case AT_CHAR: + _index++; // skip the @ sign + return URLParserState.TRANSPORT; + case TRANSPORT: + return extractTransport(); + case TRANSPORT_HOST_SEPARATOR: + _index++; // skip ":" + return URLParserState.HOST; + case HOST: + return extractHost(); + case HOST_PORT_SEPARATOR: + _index++; // skip ":" + return URLParserState.PORT; + case PORT: + return extractPort(); + case ADDRESS_END: + return endAddress(); + case ADDRESS_SEPERATOR: + _index++; // skip "," + return URLParserState.ADDRESS_START; + default: + return URLParserState.ERROR; + } + } + + private URLParserState checkSequence(char[] expected, URLParserState nextPart) + { + for (char expectedChar : expected) + { + if (expectedChar != _url[_index]) + { + _error = "Excepted (" + expectedChar + ") at position " + _index + ", got (" + _url[_index] + ")"; + return URLParserState.ERROR; + } + _index++; + } + return nextPart; + } + + private URLParserState startAddress() + { + _currentBroker = new AMQBrokerDetails(); + + for (int j = _index; j < _url.length; j++) + { + if (_url[j] == PROPERTY_EQUALS_CHAR) + { + return URLParserState.PROPERTY_NAME; + } + else if (_url[j] == ADDRESS_SEPERATOR_CHAR) + { + return URLParserState.TRANSPORT; + } + } + return URLParserState.TRANSPORT; + } + + private URLParserState endAddress() + { + _brokerDetailList.add(_currentBroker); + if (_endOfURL) + { + return URLParserState.QPID_URL_END; + } + else + { + return URLParserState.ADDRESS_SEPERATOR; + } + } + + private URLParserState extractPropertyName() + { + StringBuilder b = new StringBuilder(); + char next = _url[_index]; + while (next != PROPERTY_EQUALS_CHAR && next != AT_CHAR) + { + b.append(next); + next = _url[++_index]; + } + _currentPropName = b.toString(); + if (_currentPropName.trim().equals("")) + { + _error = "Property name cannot be empty"; + return URLParserState.ERROR; + } + else if (next == PROPERTY_EQUALS_CHAR) + { + return URLParserState.PROPERTY_EQUALS; + } + else + { + return URLParserState.AT_CHAR; + } + } + + private URLParserState extractPropertyValue() + { + StringBuilder b = new StringBuilder(); + char next = _url[_index]; + while (next != PROPERTY_SEPARATOR_CHAR && next != AT_CHAR) + { + b.append(next); + next = _url[++_index]; + } + String propValue = b.toString(); + if (propValue.trim().equals("")) + { + _error = "Property values cannot be empty"; + return URLParserState.ERROR; + } + else + { + _currentBroker.setProperty(_currentPropName, propValue); + if (next == PROPERTY_SEPARATOR_CHAR) + { + return URLParserState.PROPERTY_SEPARATOR; + } + else + { + return URLParserState.AT_CHAR; + } + } + } + + private URLParserState extractTransport() + { + String transport = buildUntil(TRANSPORT_HOST_SEPARATOR_CHAR); + if (transport.trim().equals("")) + { + _error = "Transport cannot be empty"; + return URLParserState.ERROR; + } + else if (!(transport.trim().equals(BrokerDetails.PROTOCOL_TCP) || transport.trim() + .equals(BrokerDetails.PROTOCOL_TLS))) + { + _error = "Transport cannot be " + transport + " value must be tcp or tls"; + return URLParserState.ERROR; + } + else + { + _currentBroker.setTransport(transport); + return URLParserState.TRANSPORT_HOST_SEPARATOR; + } + } + + private URLParserState extractHost() + { + char nextSep = 'c'; + String host; + URLParserState nextState; + + for (int i = _index; i < _url.length; i++) + { + if (_url[i] == HOST_PORT_SEPARATOR_CHAR) + { + nextSep = HOST_PORT_SEPARATOR_CHAR; + break; + } + else if (_url[i] == ADDRESS_SEPERATOR_CHAR) + { + nextSep = ADDRESS_SEPERATOR_CHAR; + break; + } + } + + if (nextSep == HOST_PORT_SEPARATOR_CHAR) + { + host = buildUntil(HOST_PORT_SEPARATOR_CHAR); + nextState = URLParserState.HOST_PORT_SEPARATOR; + } + else if (nextSep == ADDRESS_SEPERATOR_CHAR) + { + host = buildUntil(ADDRESS_SEPERATOR_CHAR); + nextState = URLParserState.ADDRESS_END; + } + else + { + host = buildUntil(END_OF_URL_MARKER); + nextState = URLParserState.ADDRESS_END; + _endOfURL = true; + } + + if (host.trim().equals("")) + { + _error = "Host cannot be empty"; + return URLParserState.ERROR; + } + else + { + _currentBroker.setHost(host); + return nextState; + } + } + + + private URLParserState extractPort() + { + + StringBuilder b = new StringBuilder(); + try + { + char next = _url[_index]; + while (next != ADDRESS_SEPERATOR_CHAR) + { + b.append(next); + next = _url[++_index]; + } + } + catch (ArrayIndexOutOfBoundsException e) + { + _endOfURL = true; + } + String portStr = b.toString(); + if (portStr.trim().equals("")) + { + _error = "Host cannot be empty"; + return URLParserState.ERROR; + } + else + { + try + { + int port = Integer.parseInt(portStr); + _currentBroker.setPort(port); + return URLParserState.ADDRESS_END; + } + catch (NumberFormatException e) + { + _error = "Illegal number for port"; + return URLParserState.ERROR; + } + } + } + + private String buildUntil(char c) + { + StringBuilder b = new StringBuilder(); + char next = _url[_index]; + while (next != c) + { + b.append(next); + next = _url[++_index]; + } + return b.toString(); + } + + public static void main(String[] args) + { + String testurl = "qpid:password=pass;username=name@tcp:test1,tcp:fooBroker,keystore=/usr/foo@tls:tlsBroker"; + try + { + URLParser_0_10 impl = new URLParser_0_10(testurl); + for (BrokerDetails d : impl.getAllBrokerDetails()) + { + System.out.println(d); + } + } + catch (Exception e) + { + e.printStackTrace(); + } + } +} diff --git a/java/client/src/main/java/org/apache/qpid/client/url/URLParser_0_8.java b/java/client/src/main/java/org/apache/qpid/client/url/URLParser_0_8.java new file mode 100644 index 0000000000..5cde4d196a --- /dev/null +++ b/java/client/src/main/java/org/apache/qpid/client/url/URLParser_0_8.java @@ -0,0 +1,223 @@ +package org.apache.qpid.client.url; + +import java.net.URI; +import java.net.URISyntaxException; +import java.util.StringTokenizer; + +import org.apache.qpid.client.AMQBrokerDetails; +import org.apache.qpid.client.AMQConnectionFactory; +import org.apache.qpid.client.AMQConnectionURL; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.url.URLHelper; +import org.apache.qpid.url.URLSyntaxException; + +public class URLParser_0_8 +{ + private AMQConnectionURL _url; + + public URLParser_0_8(AMQConnectionURL url)throws URLSyntaxException + { + _url = url; + parseURL(_url.getURL()); + } + + private void parseURL(String fullURL) throws URLSyntaxException + { + // Connection URL format + // amqp://[user:pass@][clientid]/virtualhost?brokerlist='tcp://host:port?option=\'value\',option=\'value\';vm://:3/virtualpath?option=\'value\'',failover='method?option=\'value\',option='value''" + // Options are of course optional except for requiring a single broker in the broker list. + try + { + URI connection = new URI(fullURL); + + if ((connection.getScheme() == null) || !(connection.getScheme().equalsIgnoreCase(AMQConnectionURL.AMQ_PROTOCOL))) + { + throw new URISyntaxException(fullURL, "Not an AMQP URL"); + } + + if ((connection.getHost() == null) || connection.getHost().equals("")) + { + String uid = AMQConnectionFactory.getUniqueClientID(); + if (uid == null) + { + throw URLHelper.parseError(-1, "Client Name not specified", fullURL); + } + else + { + _url.setClientName(uid); + } + + } + else + { + _url.setClientName(connection.getHost()); + } + + String userInfo = connection.getUserInfo(); + + if (userInfo == null) + { + // Fix for Java 1.5 which doesn't parse UserInfo for non http URIs + userInfo = connection.getAuthority(); + + if (userInfo != null) + { + int atIndex = userInfo.indexOf('@'); + + if (atIndex != -1) + { + userInfo = userInfo.substring(0, atIndex); + } + else + { + userInfo = null; + } + } + + } + + if (userInfo == null) + { + throw URLHelper.parseError(AMQConnectionURL.AMQ_PROTOCOL.length() + 3, "User information not found on url", fullURL); + } + else + { + parseUserInfo(userInfo); + } + + String virtualHost = connection.getPath(); + + if ((virtualHost != null) && (!virtualHost.equals(""))) + { + _url.setVirtualHost(virtualHost); + } + else + { + int authLength = connection.getAuthority().length(); + int start = AMQConnectionURL.AMQ_PROTOCOL.length() + 3; + int testIndex = start + authLength; + if ((testIndex < fullURL.length()) && (fullURL.charAt(testIndex) == '?')) + { + throw URLHelper.parseError(start, testIndex - start, "Virtual host found", fullURL); + } + else + { + throw URLHelper.parseError(-1, "Virtual host not specified", fullURL); + } + + } + + URLHelper.parseOptions(_url.getOptions(), connection.getQuery()); + + processOptions(); + } + catch (URISyntaxException uris) + { + if (uris instanceof URLSyntaxException) + { + throw (URLSyntaxException) uris; + } + + int slash = fullURL.indexOf("\\"); + + if (slash == -1) + { + throw URLHelper.parseError(uris.getIndex(), uris.getReason(), uris.getInput()); + } + else + { + if ((slash != 0) && (fullURL.charAt(slash - 1) == ':')) + { + throw URLHelper.parseError(slash - 2, fullURL.indexOf('?') - slash + 2, + "Virtual host looks like a windows path, forward slash not allowed in URL", fullURL); + } + else + { + throw URLHelper.parseError(slash, "Forward slash not allowed in URL", fullURL); + } + } + + } + } + + private void parseUserInfo(String userinfo) throws URLSyntaxException + { + // user info = user:pass + + int colonIndex = userinfo.indexOf(':'); + + if (colonIndex == -1) + { + throw URLHelper.parseError(AMQConnectionURL.AMQ_PROTOCOL.length() + 3, userinfo.length(), + "Null password in user information not allowed.", _url.getURL()); + } + else + { + _url.setUsername(userinfo.substring(0, colonIndex)); + _url.setPassword(userinfo.substring(colonIndex + 1)); + } + + } + + private void processOptions() throws URLSyntaxException + { + if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_BROKERLIST)) + { + String brokerlist = _url.getOptions().get(AMQConnectionURL.OPTIONS_BROKERLIST); + + // brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value' + StringTokenizer st = new StringTokenizer(brokerlist, "" + URLHelper.BROKER_SEPARATOR); + + while (st.hasMoreTokens()) + { + String broker = st.nextToken(); + + _url.addBrokerDetails(new AMQBrokerDetails(broker)); + } + + _url.getOptions().remove(AMQConnectionURL.OPTIONS_BROKERLIST); + } + + if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_FAILOVER)) + { + String failover = _url.getOptions().get(AMQConnectionURL.OPTIONS_FAILOVER); + + // failover='method?option='value',option='value'' + + int methodIndex = failover.indexOf('?'); + + if (methodIndex > -1) + { + _url.setFailoverMethod(failover.substring(0, methodIndex)); + URLHelper.parseOptions(_url.getFailoverOptions(), failover.substring(methodIndex + 1)); + } + else + { + _url.setFailoverMethod(failover); + } + + _url.getOptions().remove(AMQConnectionURL.OPTIONS_FAILOVER); + } + + if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_DEFAULT_TOPIC_EXCHANGE)) + { + _url.setDefaultTopicExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_DEFAULT_TOPIC_EXCHANGE))); + } + + if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_DEFAULT_QUEUE_EXCHANGE)) + { + _url.setDefaultQueueExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_DEFAULT_QUEUE_EXCHANGE))); + } + + if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_TEMPORARY_QUEUE_EXCHANGE)) + { + _url.setTemporaryQueueExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_TEMPORARY_QUEUE_EXCHANGE))); + } + + if (_url.getOptions().containsKey(AMQConnectionURL.OPTIONS_TEMPORARY_TOPIC_EXCHANGE)) + { + _url.setTemporaryTopicExchangeName(new AMQShortString(_url.getOptions().get(AMQConnectionURL.OPTIONS_TEMPORARY_TOPIC_EXCHANGE))); + } + } + +} diff --git a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java index 91f7710025..133285fe87 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java +++ b/java/client/src/main/java/org/apache/qpid/jms/BrokerDetails.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -20,6 +20,8 @@ */ package org.apache.qpid.jms; +import java.util.Map; + import org.apache.qpid.client.SSLConfiguration; public interface BrokerDetails @@ -44,6 +46,15 @@ public interface BrokerDetails public static final long DEFAULT_CONNECT_TIMEOUT = 30000L; public static final boolean USE_SSL_DEFAULT = false; + // pulled these properties from the new BrokerDetails class in the qpidity package + public static final String PROTOCOL_TCP = "tcp"; + public static final String PROTOCOL_TLS = "tls"; + + public static final String VIRTUAL_HOST = "virtualhost"; + public static final String CLIENT_ID = "client_id"; + public static final String USERNAME = "username"; + public static final String PASSWORD = "password"; + String getHost(); void setHost(String host); @@ -56,16 +67,30 @@ public interface BrokerDetails void setTransport(String transport); - String getOption(String key); + String getProperty(String key); - void setOption(String key, String value); + void setProperty(String key, String value); + + /** + * Ex: keystore path + * + * @return the Properties associated with this connection. + */ + public Map<String,String> getProperties(); + + /** + * Sets the properties associated with this connection + * + * @param props the new p[roperties. + */ + public void setProperties(Map<String,String> props); long getTimeout(); void setTimeout(long timeout); - + SSLConfiguration getSSLConfiguration(); - + void setSSLConfiguration(SSLConfiguration sslConfiguration); String toString(); diff --git a/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java b/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java index 2d91e290c4..0aafaa2ccf 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java +++ b/java/client/src/main/java/org/apache/qpid/jms/ConnectionURL.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -41,6 +41,12 @@ public interface ConnectionURL public static final String OPTIONS_DEFAULT_QUEUE_EXCHANGE = "defaultQueueExchange"; public static final String OPTIONS_TEMPORARY_TOPIC_EXCHANGE = "temporaryTopicExchange"; public static final String OPTIONS_TEMPORARY_QUEUE_EXCHANGE = "temporaryQueueExchange"; + public static final byte URL_0_8 = 1; + public static final byte URL_0_10 = 2; + + byte getURLVersion(); + + void setURLVersion(byte version); String getURL(); diff --git a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java index 4e0d0b79b5..74a46de63b 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java +++ b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverRoundRobinServers.java @@ -199,7 +199,7 @@ public class FailoverRoundRobinServers implements FailoverMethod int index = _connectionDetails.getAllBrokerDetails().indexOf(broker); - String serverRetries = broker.getOption(BrokerDetails.OPTIONS_RETRY); + String serverRetries = broker.getProperty(BrokerDetails.OPTIONS_RETRY); if (serverRetries != null) { diff --git a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverSingleServer.java b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverSingleServer.java index 68e6d25be0..d59c1fb98d 100644 --- a/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverSingleServer.java +++ b/java/client/src/main/java/org/apache/qpid/jms/failover/FailoverSingleServer.java @@ -7,9 +7,9 @@ * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY @@ -106,7 +106,7 @@ public class FailoverSingleServer implements FailoverMethod } _brokerDetail = broker; - String retries = broker.getOption(BrokerDetails.OPTIONS_RETRY); + String retries = broker.getProperty(BrokerDetails.OPTIONS_RETRY); if (retries != null) { try diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java index e513f25e3d..7bf96b99c1 100644 --- a/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java +++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/BrokerDetails/BrokerDetailsTest.java @@ -34,8 +34,8 @@ public class BrokerDetailsTest extends TestCase AMQBrokerDetails broker = new AMQBrokerDetails(url); - assertTrue(broker.getOption("timeout").equals("200")); - assertTrue(broker.getOption("immediatedelivery").equals("true")); + assertTrue(broker.getProperty("timeout").equals("200")); + assertTrue(broker.getProperty("immediatedelivery").equals("true")); } public void testVMBroker() throws URLSyntaxException diff --git a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java index c08b443acf..2d496d2d54 100644 --- a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java +++ b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java @@ -21,6 +21,7 @@ package org.apache.qpid.url; import java.util.HashMap; +import java.util.Map; public class URLHelper { @@ -28,7 +29,7 @@ public class URLHelper public static char ALTERNATIVE_OPTION_SEPARATOR = ','; public static char BROKER_SEPARATOR = ';'; - public static void parseOptions(HashMap<String, String> optionMap, String options) throws URLSyntaxException + public static void parseOptions(Map<String, String> optionMap, String options) throws URLSyntaxException { // options looks like this // brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value'' @@ -142,7 +143,7 @@ public class URLHelper return new URLSyntaxException(url, error, index, length); } - public static String printOptions(HashMap<String, String> options) + public static String printOptions(Map<String, String> options) { if (options.isEmpty()) { |
