From commits-return-19209-apmail-activemq-commits-archive=activemq.apache.org@activemq.apache.org Fri Jul 13 20:07:09 2012 Return-Path: X-Original-To: apmail-activemq-commits-archive@www.apache.org Delivered-To: apmail-activemq-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 6D8A2D44A for ; Fri, 13 Jul 2012 20:07:09 +0000 (UTC) Received: (qmail 90541 invoked by uid 500); 13 Jul 2012 20:07:09 -0000 Delivered-To: apmail-activemq-commits-archive@activemq.apache.org Received: (qmail 90492 invoked by uid 500); 13 Jul 2012 20:07:09 -0000 Mailing-List: contact commits-help@activemq.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@activemq.apache.org Delivered-To: mailing list commits@activemq.apache.org Received: (qmail 90485 invoked by uid 99); 13 Jul 2012 20:07:09 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Jul 2012 20:07:09 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED,WEIRD_PORT X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 13 Jul 2012 20:07:06 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 0490723888FE for ; Fri, 13 Jul 2012 20:06:47 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: svn commit: r1361367 - in /activemq/activemq-dotnet/Apache.NMS/trunk: nant.build src/main/csharp/Util/URISupport.cs src/test/csharp/URISupportTest.cs Date: Fri, 13 Jul 2012 20:06:46 -0000 To: commits@activemq.apache.org From: tabish@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20120713200647.0490723888FE@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: tabish Date: Fri Jul 13 20:06:46 2012 New Revision: 1361367 URL: http://svn.apache.org/viewvc?rev=1361367&view=rev Log: fix for: https://issues.apache.org/jira/browse/AMQNET-393 Fixes [AMQNET-AMQNET-393]. (See https://issues.apache.org/jira/browse/AMQNET-AMQNET-393) Modified: activemq/activemq-dotnet/Apache.NMS/trunk/nant.build activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/URISupport.cs activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/URISupportTest.cs Modified: activemq/activemq-dotnet/Apache.NMS/trunk/nant.build URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/nant.build?rev=1361367&r1=1361366&r2=1361367&view=diff ============================================================================== --- activemq/activemq-dotnet/Apache.NMS/trunk/nant.build (original) +++ activemq/activemq-dotnet/Apache.NMS/trunk/nant.build Fri Jul 13 20:06:46 2012 @@ -90,6 +90,7 @@ + Modified: activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/URISupport.cs URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/URISupport.cs?rev=1361367&r1=1361366&r2=1361367&view=diff ============================================================================== --- activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/URISupport.cs (original) +++ activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/URISupport.cs Fri Jul 13 20:06:46 2012 @@ -1,639 +1,638 @@ -/* - * 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. - */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Globalization; -using System.Reflection; -using System.Text; -#if !NETCF -using System.Web; -#endif - -namespace Apache.NMS.Util -{ - /// - /// Class to provide support for Uri query parameters which uses .Net reflection - /// to identify and set properties. - /// - public class URISupport - { - /// - /// Given a string that could be a Composite Uri that uses syntax not compatible - /// with the .NET Uri class such as an ActiveMQ failover Uri formatted as - /// "failover://(tcp://localhost:61616)", the initial '://' must be changed - /// to ':(' so that the Uri class doesn't attempt to parse the '(tcp:' as - /// the Uri's Authority as that is not a valid host name. - /// - /// - /// A string that could be a Composite Uri that uses syntax not compatible - /// with the .NET Uri class - /// - public static Uri CreateCompatibleUri(string uriString) - { - string sanitized = uriString.Replace("://(", ":("); - return new Uri(sanitized); - } - - /// - /// Parse a Uri query string of the form ?x=y&z=0 - /// into a map of name/value pairs. - /// - /// The query string to parse. This string should not contain - /// Uri escape characters. - public static StringDictionary ParseQuery(String query) - { - StringDictionary map = new StringDictionary(); - - if(String.IsNullOrEmpty(query)) - { - return EmptyMap; - } - - // strip the initial "?" - if(query.StartsWith("?")) - { - query = query.Substring(1); - } - - // split the query into parameters - string[] parameters = query.Split('&'); - foreach(string pair in parameters) - { - if(pair.Length > 0) - { - string[] nameValue = pair.Split('='); - - if(nameValue.Length != 2) - { - throw new NMSException(string.Format("Invalid Uri parameter: {0}", query)); - } - - map[nameValue[0]] = nameValue[1]; - } - } - - return map; - } - - public static StringDictionary ParseParameters(Uri uri) - { - return (uri.Query == null - ? EmptyMap - : ParseQuery(StripPrefix(uri.Query, "?"))); - } - - /// - /// Sets the public properties of a target object using a string map. - /// This method uses .Net reflection to identify public properties of - /// the target object matching the keys from the passed map. - /// - /// The object whose properties will be set. - /// Map of key/value pairs. - public static void SetProperties(object target, StringDictionary map) - { - Type type = target.GetType(); - - foreach(string key in map.Keys) - { - PropertyInfo prop = type.GetProperty(key, - BindingFlags.FlattenHierarchy - | BindingFlags.Public - | BindingFlags.Instance - | BindingFlags.IgnoreCase); - - if(null != prop) - { - prop.SetValue(target, Convert.ChangeType(map[key], prop.PropertyType, CultureInfo.InvariantCulture), null); - } - else - { - FieldInfo field = type.GetField(key, - BindingFlags.FlattenHierarchy - | BindingFlags.Public - | BindingFlags.Instance - | BindingFlags.IgnoreCase); - if(null != field) - { - field.SetValue(target, Convert.ChangeType(map[key], field.FieldType, CultureInfo.InvariantCulture)); - } - else - { - throw new NMSException(string.Format("No such property or field: {0} on class: {1}", key, target.GetType().Name)); - } - } - } - } - - /// - /// Sets the public properties of a target object using a string map. - /// This method uses .Net reflection to identify public properties of - /// the target object matching the keys from the passed map. - /// - /// The object whose properties will be set. - /// Map of key/value pairs. - /// Key value prefix. This is prepended to the property name - /// before searching for a matching key value. - public static void SetProperties(object target, StringDictionary map, string prefix) - { - Type type = target.GetType(); - - List matches = new List(); - - foreach(string key in map.Keys) - { - if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) - { - string bareKey = key.Substring(prefix.Length); - PropertyInfo prop = type.GetProperty(bareKey, - BindingFlags.FlattenHierarchy - | BindingFlags.Public - | BindingFlags.Instance - | BindingFlags.IgnoreCase); - - if(null != prop) - { - prop.SetValue(target, Convert.ChangeType(map[key], prop.PropertyType, CultureInfo.InvariantCulture), null); - } - else - { - FieldInfo field = type.GetField(bareKey, - BindingFlags.FlattenHierarchy - | BindingFlags.Public - | BindingFlags.Instance - | BindingFlags.IgnoreCase); - if(null != field) - { - field.SetValue(target, Convert.ChangeType(map[key], field.FieldType, CultureInfo.InvariantCulture)); - } - else - { - throw new NMSException(string.Format("No such property or field: {0} on class: {1}", bareKey, target.GetType().Name)); - } - } - - // store for later removal. - matches.Add(key); - } - } - - // Remove all the properties we set so they are used again later. - foreach(string match in matches) - { - map.Remove(match); - } - } - - public static StringDictionary GetProperties(StringDictionary props, string prefix) - { - - if(props == null) - { - throw new Exception("Properties Object was null"); - } - - StringDictionary result = new StringDictionary(); - - foreach(string key in props.Keys) - { - if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) - { - string bareKey = key.Substring(prefix.Length); - String value = props[key]; - result[bareKey] = value; - } - } - - return result; - } - - public static StringDictionary ExtractProperties(StringDictionary props, string prefix) - { - - if(props == null) - { - throw new Exception("Properties Object was null"); - } - - StringDictionary result = new StringDictionary(); - List matches = new List(); - - foreach(string key in props.Keys) - { - if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) - { - String value = props[key]; - result[key] = value; - matches.Add(key); - } - } - - foreach(string match in matches) - { - props.Remove(match); - } - - return result; - } - - public static String UrlDecode(String s) - { -#if !NETCF - return HttpUtility.HtmlDecode(s); -#else - return Uri.UnescapeDataString(s); -#endif - } - - public static String UrlEncode(String s) - { -#if !NETCF - return HttpUtility.HtmlEncode(s); -#else - return Uri.EscapeUriString(s); -#endif - } - - public static String CreateQueryString(StringDictionary options) - { - if(options != null && options.Count > 0) - { - StringBuilder rc = new StringBuilder(); - bool first = true; - - foreach(String key in options.Keys) - { - string value = options[key]; - - if(first) - { - first = false; - } - else - { - rc.Append("&"); - } - - rc.Append(UrlEncode(key)); - rc.Append("="); - rc.Append(UrlEncode(value)); - } - - return rc.ToString(); - } - else - { - return ""; - } - } - - public static Uri CreateRemainingUri(Uri originalUri, StringDictionary parameters) - { - string s = CreateQueryString(parameters); - - if(String.IsNullOrEmpty(s)) - { - s = null; - } - - return CreateUriWithQuery(originalUri, s); - } - - public class CompositeData - { - private String host; - private String scheme; - private String path; - private Uri[] components; - private StringDictionary parameters; - private String fragment; - - public Uri[] Components - { - get { return components; } - set { components = value; } - } - - public String Fragment - { - get { return fragment; } - set { fragment = value; } - } - - public StringDictionary Parameters - { - get { return parameters; } - set { parameters = value; } - } - - public String Scheme - { - get { return scheme; } - set { scheme = value; } - } - - public String Path - { - get { return path; } - set { path = value; } - } - - public String Host - { - get { return host; } - set { host = value; } - } - - public Uri toUri() - { - StringBuilder sb = new StringBuilder(); - if(scheme != null) - { - sb.Append(scheme); - sb.Append(':'); - } - - if(!string.IsNullOrEmpty(host)) - { - sb.Append(host); - } - else - { - sb.Append('('); - for(int i = 0; i < components.Length; i++) - { - if(i != 0) - { - sb.Append(','); - } - sb.Append(components[i].ToString()); - } - sb.Append(')'); - } - - if(path != null) - { - sb.Append('/'); - sb.Append(path); - } - - if(parameters.Count != 0) - { - sb.Append("?"); - sb.Append(CreateQueryString(parameters)); - } - - if(fragment != null) - { - sb.Append("#"); - sb.Append(fragment); - } - - return new Uri(sb.ToString()); - } - } - - public static String StripPrefix(String value, String prefix) - { - if(value.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) - { - return value.Substring(prefix.Length); - } - - return value; - } - - public static Uri CreateUriWithQuery(Uri uri, string query) - { - if(!String.IsNullOrEmpty(query) && !query.StartsWith("?")) - { - query = "?" + query; - } - - if(String.IsNullOrEmpty(uri.Query)) - { - return new Uri(uri.OriginalString + query); - } - else - { - string originalUri = uri.OriginalString; - - int queryDelimPos = originalUri.LastIndexOf('?'); - int compositeDelimPos = originalUri.LastIndexOf(')'); - - if(queryDelimPos <= compositeDelimPos) - { - // No Query or the Query is part of an inner Composite. - return new Uri(originalUri + query); - } - else - { - // Outer Uri has a Query or not a Composite Uri with a Query - string strippedUri = originalUri.Substring(0, queryDelimPos); - return new Uri(strippedUri + query); - } - } - } - - public static Uri RemoveQuery(Uri original) - { - return CreateUriWithQuery(original, null); - } - - public static CompositeData ParseComposite(Uri uri) - { - CompositeData rc = new CompositeData(); - rc.Scheme = uri.Scheme; - - // Start with original URI - //String ssp = uri.Authority + uri.PathAndQuery; - String ssp = uri.OriginalString; - - ssp = StripPrefix(ssp, rc.Scheme + ":"); - ssp = StripPrefix(ssp, "//"); - - int lastPoundPos = ssp.LastIndexOf("#"); - int lastParendPos = ssp.LastIndexOf(")"); - - // Only include a Fragment that's outside any Composte sections. - if(lastPoundPos > lastParendPos) - { - rc.Fragment = ssp.Substring(lastPoundPos); - ssp = ssp.Substring(0, lastPoundPos); - } - - // Ensure any embedded URIs don't have malformed authority's by changing - // them from '://(' which would cause the .NET Uri class to attempt to validate - // the authority as a hostname with, ':(' which is valid. - ssp = ssp.Replace("://(", ":("); - - // Handle the composite components - ParseComposite(uri, rc, ssp); - return rc; - } - - /// - /// - /// - /// - /// - private static void ParseComposite(Uri uri, CompositeData rc, String ssp) - { - String componentString; - String parms; - - if(!CheckParenthesis(ssp)) - { - throw new NMSException(uri.ToString() + ": Not a matching number of '(' and ')' parenthesis"); - } - - int p; - int intialParen = ssp.IndexOf("("); - - if(intialParen >= 0) - { - rc.Host = ssp.Substring(0, intialParen); - p = rc.Host.IndexOf("/"); - if(p >= 0) - { - rc.Path = rc.Host.Substring(p); - rc.Host = rc.Host.Substring(0, p); - } - - p = ssp.LastIndexOf(")"); - int start = intialParen + 1; - int len = p - start; - componentString = ssp.Substring(start, len); - parms = ssp.Substring(p + 1).Trim(); - } - else - { - componentString = ssp; - parms = ""; - } - - String[] components = SplitComponents(componentString); - rc.Components = new Uri[components.Length]; - for(int i = 0; i < components.Length; i++) - { - rc.Components[i] = new Uri(components[i].Trim()); - } - - p = parms.IndexOf("?"); - if(p >= 0) - { - if(p > 0) - { - rc.Path = StripPrefix(parms.Substring(0, p), "/"); - } - - rc.Parameters = ParseQuery(parms.Substring(p + 1)); - } - else - { - if(parms.Length > 0) - { - rc.Path = StripPrefix(parms, "/"); - } - - rc.Parameters = EmptyMap; - } - } - - private static StringDictionary EmptyMap - { - get { return new StringDictionary(); } - } - - /// - /// - /// - private static String[] SplitComponents(String componentString) - { - ArrayList l = new ArrayList(); - - int last = 0; - int depth = 0; - char[] chars = componentString.ToCharArray(); - for(int i = 0; i < chars.Length; i++) - { - switch(chars[i]) - { - case '(': - depth++; - break; - - case ')': - depth--; - break; - - case ',': - if(depth == 0) - { - String s = componentString.Substring(last, i - last); - l.Add(s); - last = i + 1; - } - break; - - default: - break; - } - } - - String ending = componentString.Substring(last); - if(ending.Length != 0) - { - l.Add(ending); - } - - String[] rc = new String[l.Count]; - l.CopyTo(rc); - return rc; - } - - public static bool CheckParenthesis(String str) - { - bool result = true; - - if(str != null) - { - int open = 0; - int closed = 0; - - int i = 0; - while((i = str.IndexOf('(', i)) >= 0) - { - i++; - open++; - } - - i = 0; - while((i = str.IndexOf(')', i)) >= 0) - { - i++; - closed++; - } - - result = (open == closed); - } - - return result; - } - } -} +/* + * 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. + */ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Globalization; +using System.Reflection; +using System.Text; +#if !NETCF +using System.Web; +#endif + +namespace Apache.NMS.Util +{ + /// + /// Class to provide support for Uri query parameters which uses .Net reflection + /// to identify and set properties. + /// + public class URISupport + { + /// + /// Given a string that could be a Composite Uri that uses syntax not compatible + /// with the .NET Uri class such as an ActiveMQ failover Uri formatted as + /// "failover://(tcp://localhost:61616)", the initial '://' must be changed + /// to ':(' so that the Uri class doesn't attempt to parse the '(tcp:' as + /// the Uri's Authority as that is not a valid host name. + /// + /// + /// A string that could be a Composite Uri that uses syntax not compatible + /// with the .NET Uri class + /// + public static Uri CreateCompatibleUri(string uriString) + { + string sanitized = uriString.Replace("://(", ":("); + return new Uri(sanitized); + } + + /// + /// Parse a Uri query string of the form ?x=y&z=0 + /// into a map of name/value pairs. + /// + /// The query string to parse. This string should not contain + /// Uri escape characters. + public static StringDictionary ParseQuery(String query) + { + StringDictionary map = new StringDictionary(); + + if(String.IsNullOrEmpty(query)) + { + return EmptyMap; + } + + // strip the initial "?" + if(query.StartsWith("?")) + { + query = query.Substring(1); + } + + // split the query into parameters + string[] parameters = query.Split('&'); + foreach(string pair in parameters) + { + if(pair.Length > 0) + { + string[] nameValue = pair.Split('='); + + if(nameValue.Length != 2) + { + throw new NMSException(string.Format("Invalid Uri parameter: {0}", query)); + } + + map[UrlDecode(nameValue[0])] = UrlDecode(nameValue[1]); + } + } + + return map; + } + + public static StringDictionary ParseParameters(Uri uri) + { + return (uri.Query == null + ? EmptyMap + : ParseQuery(StripPrefix(uri.Query, "?"))); + } + + /// + /// Sets the public properties of a target object using a string map. + /// This method uses .Net reflection to identify public properties of + /// the target object matching the keys from the passed map. + /// + /// The object whose properties will be set. + /// Map of key/value pairs. + public static void SetProperties(object target, StringDictionary map) + { + Type type = target.GetType(); + + foreach(string key in map.Keys) + { + PropertyInfo prop = type.GetProperty(key, + BindingFlags.FlattenHierarchy + | BindingFlags.Public + | BindingFlags.Instance + | BindingFlags.IgnoreCase); + + if(null != prop) + { + prop.SetValue(target, Convert.ChangeType(map[key], prop.PropertyType, CultureInfo.InvariantCulture), null); + } + else + { + FieldInfo field = type.GetField(key, + BindingFlags.FlattenHierarchy + | BindingFlags.Public + | BindingFlags.Instance + | BindingFlags.IgnoreCase); + if(null != field) + { + field.SetValue(target, Convert.ChangeType(map[key], field.FieldType, CultureInfo.InvariantCulture)); + } + else + { + throw new NMSException(string.Format("No such property or field: {0} on class: {1}", key, target.GetType().Name)); + } + } + } + } + + /// + /// Sets the public properties of a target object using a string map. + /// This method uses .Net reflection to identify public properties of + /// the target object matching the keys from the passed map. + /// + /// The object whose properties will be set. + /// Map of key/value pairs. + /// Key value prefix. This is prepended to the property name + /// before searching for a matching key value. + public static void SetProperties(object target, StringDictionary map, string prefix) + { + Type type = target.GetType(); + + List matches = new List(); + + foreach(string key in map.Keys) + { + if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) + { + string bareKey = key.Substring(prefix.Length); + PropertyInfo prop = type.GetProperty(bareKey, + BindingFlags.FlattenHierarchy + | BindingFlags.Public + | BindingFlags.Instance + | BindingFlags.IgnoreCase); + + if(null != prop) + { + prop.SetValue(target, Convert.ChangeType(map[key], prop.PropertyType, CultureInfo.InvariantCulture), null); + } + else + { + FieldInfo field = type.GetField(bareKey, + BindingFlags.FlattenHierarchy + | BindingFlags.Public + | BindingFlags.Instance + | BindingFlags.IgnoreCase); + if(null != field) + { + field.SetValue(target, Convert.ChangeType(map[key], field.FieldType, CultureInfo.InvariantCulture)); + } + else + { + throw new NMSException(string.Format("No such property or field: {0} on class: {1}", bareKey, target.GetType().Name)); + } + } + + // store for later removal. + matches.Add(key); + } + } + + // Remove all the properties we set so they are used again later. + foreach(string match in matches) + { + map.Remove(match); + } + } + + public static StringDictionary GetProperties(StringDictionary props, string prefix) + { + if(props == null) + { + throw new Exception("Properties Object was null"); + } + + StringDictionary result = new StringDictionary(); + + foreach(string key in props.Keys) + { + if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) + { + string bareKey = key.Substring(prefix.Length); + String value = props[key]; + result[bareKey] = value; + } + } + + return result; + } + + public static StringDictionary ExtractProperties(StringDictionary props, string prefix) + { + + if(props == null) + { + throw new Exception("Properties Object was null"); + } + + StringDictionary result = new StringDictionary(); + List matches = new List(); + + foreach(string key in props.Keys) + { + if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) + { + String value = props[key]; + result[key] = value; + matches.Add(key); + } + } + + foreach(string match in matches) + { + props.Remove(match); + } + + return result; + } + + public static String UrlDecode(String s) + { +#if !NETCF + return HttpUtility.UrlDecode(s); +#else + return Uri.UnescapeDataString(s); +#endif + } + + public static String UrlEncode(String s) + { +#if !NETCF + return HttpUtility.UrlEncode(s); +#else + return Uri.EscapeUriString(s); +#endif + } + + public static String CreateQueryString(StringDictionary options) + { + if(options != null && options.Count > 0) + { + StringBuilder rc = new StringBuilder(); + bool first = true; + + foreach(String key in options.Keys) + { + string value = options[key]; + + if(first) + { + first = false; + } + else + { + rc.Append("&"); + } + + rc.Append(UrlEncode(key)); + rc.Append("="); + rc.Append(UrlEncode(value)); + } + + return rc.ToString(); + } + else + { + return ""; + } + } + + public static Uri CreateRemainingUri(Uri originalUri, StringDictionary parameters) + { + string s = CreateQueryString(parameters); + + if(String.IsNullOrEmpty(s)) + { + s = null; + } + + return CreateUriWithQuery(originalUri, s); + } + + public class CompositeData + { + private String host; + private String scheme; + private String path; + private Uri[] components; + private StringDictionary parameters; + private String fragment; + + public Uri[] Components + { + get { return components; } + set { components = value; } + } + + public String Fragment + { + get { return fragment; } + set { fragment = value; } + } + + public StringDictionary Parameters + { + get { return parameters; } + set { parameters = value; } + } + + public String Scheme + { + get { return scheme; } + set { scheme = value; } + } + + public String Path + { + get { return path; } + set { path = value; } + } + + public String Host + { + get { return host; } + set { host = value; } + } + + public Uri toUri() + { + StringBuilder sb = new StringBuilder(); + if(scheme != null) + { + sb.Append(scheme); + sb.Append(':'); + } + + if(!string.IsNullOrEmpty(host)) + { + sb.Append(host); + } + else + { + sb.Append('('); + for(int i = 0; i < components.Length; i++) + { + if(i != 0) + { + sb.Append(','); + } + sb.Append(components[i].ToString()); + } + sb.Append(')'); + } + + if(path != null) + { + sb.Append('/'); + sb.Append(path); + } + + if(parameters.Count != 0) + { + sb.Append("?"); + sb.Append(CreateQueryString(parameters)); + } + + if(fragment != null) + { + sb.Append("#"); + sb.Append(fragment); + } + + return new Uri(sb.ToString()); + } + } + + public static String StripPrefix(String value, String prefix) + { + if(value.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase)) + { + return value.Substring(prefix.Length); + } + + return value; + } + + public static Uri CreateUriWithQuery(Uri uri, string query) + { + if(!String.IsNullOrEmpty(query) && !query.StartsWith("?")) + { + query = "?" + query; + } + + if(String.IsNullOrEmpty(uri.Query)) + { + return new Uri(uri.OriginalString + query); + } + else + { + string originalUri = uri.OriginalString; + + int queryDelimPos = originalUri.LastIndexOf('?'); + int compositeDelimPos = originalUri.LastIndexOf(')'); + + if(queryDelimPos <= compositeDelimPos) + { + // No Query or the Query is part of an inner Composite. + return new Uri(originalUri + query); + } + else + { + // Outer Uri has a Query or not a Composite Uri with a Query + string strippedUri = originalUri.Substring(0, queryDelimPos); + return new Uri(strippedUri + query); + } + } + } + + public static Uri RemoveQuery(Uri original) + { + return CreateUriWithQuery(original, null); + } + + public static CompositeData ParseComposite(Uri uri) + { + CompositeData rc = new CompositeData(); + rc.Scheme = uri.Scheme; + + // Start with original URI + //String ssp = uri.Authority + uri.PathAndQuery; + String ssp = uri.OriginalString; + + ssp = StripPrefix(ssp, rc.Scheme + ":"); + ssp = StripPrefix(ssp, "//"); + + int lastPoundPos = ssp.LastIndexOf("#"); + int lastParendPos = ssp.LastIndexOf(")"); + + // Only include a Fragment that's outside any Composte sections. + if(lastPoundPos > lastParendPos) + { + rc.Fragment = ssp.Substring(lastPoundPos); + ssp = ssp.Substring(0, lastPoundPos); + } + + // Ensure any embedded URIs don't have malformed authority's by changing + // them from '://(' which would cause the .NET Uri class to attempt to validate + // the authority as a hostname with, ':(' which is valid. + ssp = ssp.Replace("://(", ":("); + + // Handle the composite components + ParseComposite(uri, rc, ssp); + return rc; + } + + /// + /// + /// + /// + /// + private static void ParseComposite(Uri uri, CompositeData rc, String ssp) + { + String componentString; + String parms; + + if(!CheckParenthesis(ssp)) + { + throw new NMSException(uri.ToString() + ": Not a matching number of '(' and ')' parenthesis"); + } + + int p; + int intialParen = ssp.IndexOf("("); + + if(intialParen >= 0) + { + rc.Host = ssp.Substring(0, intialParen); + p = rc.Host.IndexOf("/"); + if(p >= 0) + { + rc.Path = rc.Host.Substring(p); + rc.Host = rc.Host.Substring(0, p); + } + + p = ssp.LastIndexOf(")"); + int start = intialParen + 1; + int len = p - start; + componentString = ssp.Substring(start, len); + parms = ssp.Substring(p + 1).Trim(); + } + else + { + componentString = ssp; + parms = ""; + } + + String[] components = SplitComponents(componentString); + rc.Components = new Uri[components.Length]; + for(int i = 0; i < components.Length; i++) + { + rc.Components[i] = new Uri(components[i].Trim()); + } + + p = parms.IndexOf("?"); + if(p >= 0) + { + if(p > 0) + { + rc.Path = StripPrefix(parms.Substring(0, p), "/"); + } + + rc.Parameters = ParseQuery(parms.Substring(p + 1)); + } + else + { + if(parms.Length > 0) + { + rc.Path = StripPrefix(parms, "/"); + } + + rc.Parameters = EmptyMap; + } + } + + private static StringDictionary EmptyMap + { + get { return new StringDictionary(); } + } + + /// + /// + /// + private static String[] SplitComponents(String componentString) + { + ArrayList l = new ArrayList(); + + int last = 0; + int depth = 0; + char[] chars = componentString.ToCharArray(); + for(int i = 0; i < chars.Length; i++) + { + switch(chars[i]) + { + case '(': + depth++; + break; + + case ')': + depth--; + break; + + case ',': + if(depth == 0) + { + String s = componentString.Substring(last, i - last); + l.Add(s); + last = i + 1; + } + break; + + default: + break; + } + } + + String ending = componentString.Substring(last); + if(ending.Length != 0) + { + l.Add(ending); + } + + String[] rc = new String[l.Count]; + l.CopyTo(rc); + return rc; + } + + public static bool CheckParenthesis(String str) + { + bool result = true; + + if(str != null) + { + int open = 0; + int closed = 0; + + int i = 0; + while((i = str.IndexOf('(', i)) >= 0) + { + i++; + open++; + } + + i = 0; + while((i = str.IndexOf(')', i)) >= 0) + { + i++; + closed++; + } + + result = (open == closed); + } + + return result; + } + } +} Modified: activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/URISupportTest.cs URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/URISupportTest.cs?rev=1361367&r1=1361366&r2=1361367&view=diff ============================================================================== --- activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/URISupportTest.cs (original) +++ activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/URISupportTest.cs Fri Jul 13 20:06:46 2012 @@ -19,6 +19,9 @@ using System; using System.Collections.Specialized; using Apache.NMS.Util; using NUnit.Framework; +#if !NETCF +using System.Web; +#endif namespace Apache.NMS.Test { @@ -271,6 +274,28 @@ namespace Apache.NMS.Test Assert.AreEqual(source.Scheme, dest.Scheme, "same uri, scheme"); Assert.IsFalse(dest.Query.Equals(source.Query), "same uri, ssp"); } + +#if !NETCF + [Test] + public void TestParseQueryEncoding() { + + String paramName = "name"; + String paramValue = "CN=Test, OU=bla, ..&%/§()%3q743847)/(&%/.. hjUIFHUFH"; + + String uriString = "http://someserver.com:1234/?"; + + //encoding the param with url encode + uriString += paramName + "=" + HttpUtility.UrlEncode(paramValue); + + Uri uri = new Uri(uriString); + + StringDictionary dictionary = URISupport.ParseQuery(uri.Query); + + String value = dictionary[paramName]; + + NUnit.Framework.Assert.AreEqual(paramValue, value); + } +#endif } }