fix for: https://issues.apache.org/jira/browse/AMQNET-393


diff --git a/nant.build b/nant.build
index 9a66023..ae3b149 100644
--- a/nant.build
+++ b/nant.build
@@ -88,6 +88,7 @@
             <include name="${current.build.framework.assembly.dir}/mscorlib.dll" />
             <include name="${current.build.framework.assembly.dir}/System.dll" />
             <include name="${current.build.framework.assembly.dir}/System.Xml.dll" />
+            <include name="${current.build.framework.assembly.dir}/System.Web.dll" />
             <include name="${build.bin.dir}/${project.name}.dll" />
             <include name="${nunit.dll}" />
         </assemblyfileset>
diff --git a/src/main/csharp/Util/URISupport.cs b/src/main/csharp/Util/URISupport.cs
index e17df5a..5a3d686 100644
--- a/src/main/csharp/Util/URISupport.cs
+++ b/src/main/csharp/Util/URISupport.cs
@@ -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

-{

-	/// <summary>

-	/// Class to provide support for Uri query parameters which uses .Net reflection

-	/// to identify and set properties.

-	/// </summary>

-	public class URISupport

-	{

-		/// <summary>

-		/// 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.

-		/// </summary>

-		/// <param name="uriString">

-		/// A string that could be a Composite Uri that uses syntax not compatible

-		/// with the .NET Uri class

-		/// </param>

-		public static Uri CreateCompatibleUri(string uriString)

-		{

-			string sanitized = uriString.Replace("://(", ":(");

-			return new Uri(sanitized);

-		}

-

-		/// <summary>

-		/// Parse a Uri query string of the form ?x=y&amp;z=0

-		/// into a map of name/value pairs.

-		/// </summary>

-		/// <param name="query">The query string to parse. This string should not contain

-		/// Uri escape characters.</param>

-		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, "?")));

-		}

-

-		/// <summary>

-		/// 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.

-		/// </summary>

-		/// <param name="target">The object whose properties will be set.</param>

-		/// <param name="map">Map of key/value pairs.</param>

-		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));

-					}

-				}

-			}

-		}

-

-		/// <summary>

-		/// 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.

-		/// </summary>

-		/// <param name="target">The object whose properties will be set.</param>

-		/// <param name="map">Map of key/value pairs.</param>

-		/// <param name="prefix">Key value prefix.  This is prepended to the property name

-		/// before searching for a matching key value.</param>

-		public static void SetProperties(object target, StringDictionary map, string prefix)

-		{

-			Type type = target.GetType();

-

-			List<String> matches = new List<String>();

-

-			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<String> matches = new List<String>();

-

-			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;

-		}

-

-		/// <summary>

-		/// </summary>

-		/// <param name="uri"></param>

-		/// <param name="rc"></param>

-		/// <param name="ssp"></param>

-		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(); }

-		}

-

-		/// <summary>

-		/// </summary>

-		/// <param name="componentString"></param>

-		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
+{
+	/// <summary>
+	/// Class to provide support for Uri query parameters which uses .Net reflection
+	/// to identify and set properties.
+	/// </summary>
+	public class URISupport
+	{
+		/// <summary>
+		/// 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.
+		/// </summary>
+		/// <param name="uriString">
+		/// A string that could be a Composite Uri that uses syntax not compatible
+		/// with the .NET Uri class
+		/// </param>
+		public static Uri CreateCompatibleUri(string uriString)
+		{
+			string sanitized = uriString.Replace("://(", ":(");
+			return new Uri(sanitized);
+		}
+
+		/// <summary>
+		/// Parse a Uri query string of the form ?x=y&amp;z=0
+		/// into a map of name/value pairs.
+		/// </summary>
+		/// <param name="query">The query string to parse. This string should not contain
+		/// Uri escape characters.</param>
+		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, "?")));
+		}
+
+		/// <summary>
+		/// 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.
+		/// </summary>
+		/// <param name="target">The object whose properties will be set.</param>
+		/// <param name="map">Map of key/value pairs.</param>
+		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));
+					}
+				}
+			}
+		}
+
+		/// <summary>
+		/// 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.
+		/// </summary>
+		/// <param name="target">The object whose properties will be set.</param>
+		/// <param name="map">Map of key/value pairs.</param>
+		/// <param name="prefix">Key value prefix.  This is prepended to the property name
+		/// before searching for a matching key value.</param>
+		public static void SetProperties(object target, StringDictionary map, string prefix)
+		{
+			Type type = target.GetType();
+
+			List<String> matches = new List<String>();
+
+			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<String> matches = new List<String>();
+
+			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;
+		}
+
+		/// <summary>
+		/// </summary>
+		/// <param name="uri"></param>
+		/// <param name="rc"></param>
+		/// <param name="ssp"></param>
+		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(); }
+		}
+
+		/// <summary>
+		/// </summary>
+		/// <param name="componentString"></param>
+		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;
+		}
+	}
+}
diff --git a/src/test/csharp/URISupportTest.cs b/src/test/csharp/URISupportTest.cs
index 825ed9d..f60355b 100644
--- a/src/test/csharp/URISupportTest.cs
+++ b/src/test/csharp/URISupportTest.cs
@@ -21,6 +21,9 @@
 using Apache.NMS.Util;
 
 using NUnit.Framework;
+#if !NETCF
+using System.Web;
+#endif
 
 namespace Apache.NMS.Test
 {
@@ -266,6 +269,28 @@
 	        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
 	}
 }