diff options
Diffstat (limited to 'dotnet/Qpid.Client/Client/QpidConnectionInfo.cs')
-rw-r--r-- | dotnet/Qpid.Client/Client/QpidConnectionInfo.cs | 384 |
1 files changed, 367 insertions, 17 deletions
diff --git a/dotnet/Qpid.Client/Client/QpidConnectionInfo.cs b/dotnet/Qpid.Client/Client/QpidConnectionInfo.cs index f0c4c91db8..6c49a6c7ff 100644 --- a/dotnet/Qpid.Client/Client/QpidConnectionInfo.cs +++ b/dotnet/Qpid.Client/Client/QpidConnectionInfo.cs @@ -21,11 +21,341 @@ using System; using System.Collections; using System.Net; +using System.Text; +using System.Text.RegularExpressions; using log4net; using Qpid.Client.qms; namespace Qpid.Client { + + public class URLHelper + { + public static char DEFAULT_OPTION_SEPERATOR = '&'; + public static char ALTERNATIVE_OPTION_SEPARATOR = ','; + public static char BROKER_SEPARATOR = ';'; + + /// <summary> + /// + /// </summary> + /// <param name="optionMap"></param> + /// <param name="options"></param> + public static void parseOptions(IDictionary optionMap, string options) + { + //options looks like this + //brokerlist='tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value'',failover='method?option='value',option='value'' + + if (options == null || options.IndexOf('=') == -1) + { + return; + } + + int optionIndex = options.IndexOf('='); + + String option = options.Substring(0, optionIndex); + + int length = options.Length; + + int nestedQuotes = 0; + + // to store index of final "'" + int valueIndex = optionIndex; + + //Walk remainder of url. + while (nestedQuotes > 0 || valueIndex < length) + { + valueIndex++; + + if (valueIndex >= length) + { + break; + } + + if (options[valueIndex] == '\'') + { + if (valueIndex + 1 < options.Length) + { + if (options[valueIndex + 1] == DEFAULT_OPTION_SEPERATOR || + options[valueIndex + 1] == ALTERNATIVE_OPTION_SEPARATOR || + options[valueIndex + 1] == BROKER_SEPARATOR || + options[valueIndex + 1] == '\'') + { + nestedQuotes--; + // System.out.println( + // options + "\n" + "-" + nestedQuotes + ":" + getPositionString(valueIndex - 2, 1)); + if (nestedQuotes == 0) + { + //We've found the value of an option + break; + } + } + else + { + nestedQuotes++; + // System.out.println( + // options + "\n" + "+" + nestedQuotes + ":" + getPositionString(valueIndex - 2, 1)); + } + } + else + { + // We are at the end of the string + // Check to see if we are corectly closing quotes + if (options[valueIndex] == '\'') + { + nestedQuotes--; + } + + break; + } + } + } + + if (nestedQuotes != 0 || valueIndex < (optionIndex + 2)) + { + int sepIndex = 0; + + //Try and identify illegal separator character + if (nestedQuotes > 1) + { + for (int i = 0; i < nestedQuotes; i++) + { + sepIndex = options.IndexOf('\'', sepIndex); + sepIndex++; + } + } + + if (sepIndex >= options.Length || sepIndex == 0) + { + parseError(valueIndex, "Unterminated option", options); + } + else + { + parseError(sepIndex, "Unterminated option. Possible illegal option separator:'" + + options[sepIndex] + "'", options); + } + } + + // optionIndex +2 to skip "='" + int sublen = valueIndex - (optionIndex + 2); + String value = options.Substring(optionIndex + 2, sublen); + + optionMap.Add(option, value); + + if (valueIndex < (options.Length - 1)) + { + //Recurse to get remaining options + parseOptions(optionMap, options.Substring(valueIndex + 2)); + } + } + + + public static void parseError(int index, String error, String url) + { + parseError(index, 1, error, url); + } + + public static void parseError(int index, int length, String error, String url) + { + throw new UrlSyntaxException(url, error, index, length); + } + + public static String printOptions(Hashtable options) + { + if (options.Count == 0) + { + return ""; + } + else + { + StringBuilder sb = new StringBuilder(); + sb.Append('?'); + foreach (String key in options.Keys) + { + sb.Append(key); + + sb.Append("='"); + + sb.Append(options[key]); + + sb.Append("'"); + sb.Append(DEFAULT_OPTION_SEPERATOR); + } + + sb.Remove(sb.Length - 1, 1); + // sb.deleteCharAt(sb.length() - 1); + + return sb.ToString(); + } + } + + } + + public class QpidConnectionUrl + { + internal static ConnectionInfo FromUrl(string fullURL) + { + //_url = fullURL; + ConnectionInfo connectionInfo = new QpidConnectionInfo(); + + + // _options = new HashMap<String, String>(); + // _brokers = new LinkedList(); + // _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 + { + Uri connection = new Uri(fullURL); + + if (connection.Scheme == null || !(connection.Scheme.Equals(ConnectionUrlConstants.AMQ_PROTOCOL))) + { + throw new UrlSyntaxException(fullURL, "Not an AMQP URL"); + } + + if (connection.Host != null && connection.Host.Length > 0 && !connection.Host.Equals("default")) + { + connectionInfo.SetClientName(connection.Host); + } + + String userInfo = connection.UserInfo; + if (userInfo == null || userInfo.Length == 0) + { + URLHelper.parseError(ConnectionUrlConstants.AMQ_PROTOCOL.Length + 3, + "User information not found on url", fullURL); + } + else + { + parseUserInfo(userInfo, fullURL, connectionInfo); + } + String virtualHost = connection.AbsolutePath; // XXX: is AbsolutePath corrrect? + + if (virtualHost != null && (!virtualHost.Equals(""))) + { + connectionInfo.SetVirtualHost(virtualHost); + } + else + { + int authLength = connection.Authority.Length; + int start = ConnectionUrlConstants.AMQ_PROTOCOL.Length + 3; + int testIndex = start + authLength; + if (testIndex < fullURL.Length && fullURL[testIndex] == '?') + { + URLHelper.parseError(start, testIndex - start, "Virtual host found", fullURL); + } + else + { + URLHelper.parseError(-1, "Virtual host not specified", fullURL); + } + + } + + QpidConnectionInfo qci = (QpidConnectionInfo)connectionInfo; + string query = connection.Query; + if (query[0] == '?') query = query.Substring(1); + URLHelper.parseOptions(qci.GetOptions(), query); + + processOptions(connectionInfo); + + //Fragment is #string (not used) + //System.out.println(connection.getFragment()); + return connectionInfo; + } + catch (UriFormatException uris) + { + throw uris; + // if (uris is UrlSyntaxException) + // { + // throw uris; + // } + // + // int slash = fullURL.IndexOf("\\"); + // + // if (slash == -1) + // { + // URLHelper.parseError(uris.GetIndex(), uris.getReason(), uris.getInput()); + // } + // else + // { + // if (slash != 0 && fullURL.charAt(slash - 1) == ':') + // { + // URLHelper.parseError(slash - 2, fullURL.indexOf('?') - slash + 2, "Virtual host looks like a windows path, forward slash not allowed in URL", fullURL); + // } + // else + // { + // URLHelper.parseError(slash, "Forward slash not allowed in URL", fullURL); + // } + // } + } + } + + private static void parseUserInfo(String userinfo, string fullUrl, ConnectionInfo connectionInfo) + { + //user info = user:pass + + int colonIndex = userinfo.IndexOf(':'); + + if (colonIndex == -1) + { + URLHelper.parseError(ConnectionUrlConstants.AMQ_PROTOCOL.Length + 3, + userinfo.Length, "Null password in user information not allowed.", fullUrl); + } + else + { + connectionInfo.setUsername(userinfo.Substring(0, colonIndex)); + connectionInfo.SetPassword(userinfo.Substring(colonIndex + 1)); + } + } + + private static void processOptions(ConnectionInfo connectionInfo) + { + string brokerlist = connectionInfo.GetOption(ConnectionUrlConstants.OPTIONS_BROKERLIST); + if (brokerlist != null) + { + //brokerlist tcp://host:port?option='value',option='value';vm://:3/virtualpath?option='value' + Regex splitter = new Regex("" + URLHelper.BROKER_SEPARATOR); + + foreach (string broker in splitter.Split(brokerlist)) + { + connectionInfo.AddBrokerInfo(new AmqBrokerInfo(broker)); + } + + connectionInfo.SetOption(ConnectionUrlConstants.OPTIONS_BROKERLIST, null); + // _options.remove(OPTIONS_BROKERLIST); + } + + string failover = connectionInfo.GetOption(ConnectionUrlConstants.OPTIONS_FAILOVER); + if (failover != null) + { + // failover='method?option='value',option='value'' + + int methodIndex = failover.IndexOf('?'); + + if (methodIndex > -1) + { + connectionInfo.SetFailoverMethod(failover.Substring(0, methodIndex)); + QpidConnectionInfo qpidConnectionInfo = (QpidConnectionInfo)connectionInfo; + URLHelper.parseOptions(qpidConnectionInfo.GetFailoverOptions(), + failover.Substring(methodIndex + 1)); + } + else + { + connectionInfo.SetFailoverMethod(failover); + } + + connectionInfo.SetOption(ConnectionUrlConstants.OPTIONS_FAILOVER, null); + // _options.remove(OPTIONS_FAILOVER); + } + } + + internal static ConnectionInfo FromUri(Uri uri) + { + return null; // FIXME + + } + } + public class QpidConnectionInfo : ConnectionInfo { private static readonly ILog _logger = LogManager.GetLogger(typeof(QpidConnectionInfo)); @@ -40,7 +370,22 @@ namespace Qpid.Client IList _brokerInfos = new ArrayList(); // List<BrokerInfo> string _clientName = String.Format("{0}{1:G}", Dns.GetHostName(), DateTime.Now.Ticks); - public string asUrl() + public IDictionary GetFailoverOptions() + { + return _failoverOptions; + } + + public IDictionary GetOptions() + { + return _options; + } + + public static ConnectionInfo FromUrl(String url) + { + return QpidConnectionUrl.FromUrl(url); + } + + public string AsUrl() { string result = "amqp://"; foreach (BrokerInfo info in _brokerInfos) @@ -48,25 +393,30 @@ namespace Qpid.Client result += info.ToString(); } return result; - + } - public string getFailoverMethod() + public string GetFailoverMethod() { return _failoverMethod; } - public string getFailoverOption(string key) + public void SetFailoverMethod(string failoverMethod) + { + _failoverMethod = failoverMethod; + } + + public string GetFailoverOption(string key) { - return (string) _failoverOptions[key]; + return (string)_failoverOptions[key]; } - public int getBrokerCount() + public int GetBrokerCount() { return _brokerInfos.Count; } - public BrokerInfo GetBrokerDetails(int index) + public BrokerInfo GetBrokerInfo(int index) { return (BrokerInfo)_brokerInfos[index]; } @@ -94,7 +444,7 @@ namespace Qpid.Client _clientName = clientName; } - public string getUsername() + public string GetUsername() { return _username; } @@ -104,39 +454,39 @@ namespace Qpid.Client _username = username; } - public string getPassword() + public string GetPassword() { return _password; } - public void setPassword(string password) + public void SetPassword(string password) { _password = password; } - public string getVirtualHost() + public string GetVirtualHost() { return _virtualHost; } - public void setVirtualHost(string virtualHost) + public void SetVirtualHost(string virtualHost) { _virtualHost = virtualHost; } - public string getOption(string key) + public string GetOption(string key) { - return (string) _options[key]; + return (string)_options[key]; } - public void setOption(string key, string value) + public void SetOption(string key, string value) { _options[key] = value; } - + public override string ToString() { - return asUrl(); + return AsUrl(); } } } |