You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2011/02/01 22:14:36 UTC

svn commit: r1066209 - in /activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src: main/csharp/ main/csharp/Transactions/ main/csharp/Util/ test/csharp/ test/csharp/Transactions/

Author: tabish
Date: Tue Feb  1 21:14:36 2011
New Revision: 1066209

URL: http://svn.apache.org/viewvc?rev=1066209&view=rev
Log:
https://issues.apache.org/jira/browse/AMQNET-290

Enhance the code that sets properties on object via Uri parameters to allow it to make compound assignments which simplifies the code in the ConnectionFactory and allows derived classes to add new parameters without have to change the Uri options parsing code in ConnectionFactory.

Adds some additional tests and fix some issues found during testing.

Added:
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/IntrospectionSupport.cs   (with props)
Modified:
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/ConnectionFactory.cs
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxConnectionFactory.cs
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxRecoveryPolicy.cs
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/NetTxConnectionFactoryTest.cs
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/ConnectionFactory.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/ConnectionFactory.cs?rev=1066209&r1=1066208&r2=1066209&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/ConnectionFactory.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/ConnectionFactory.cs Tue Feb  1 21:14:36 2011
@@ -193,16 +193,8 @@ namespace Apache.NMS.ActiveMQ
 					StringDictionary connection = URISupport.ExtractProperties(properties, "connection.");
 					StringDictionary nms = URISupport.ExtractProperties(properties, "nms.");
 
-					if(connection != null)
-					{
-						URISupport.SetProperties(this, connection, "connection.");
-					}
-
-					if(nms != null)
-					{
-						URISupport.SetProperties(this.PrefetchPolicy, nms, "nms.PrefetchPolicy.");
-						URISupport.SetProperties(this.RedeliveryPolicy, nms, "nms.RedeliveryPolicy.");
-					}
+			        IntrospectionSupport.SetProperties(this, connection, "connection.");
+                    IntrospectionSupport.SetProperties(this, nms, "nms.");
 
 					brokerUri = URISupport.CreateRemainingUri(brokerUri, properties);
 				}

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxConnectionFactory.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxConnectionFactory.cs?rev=1066209&r1=1066208&r2=1066209&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxConnectionFactory.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxConnectionFactory.cs Tue Feb  1 21:14:36 2011
@@ -64,18 +64,7 @@ namespace Apache.NMS.ActiveMQ
         {
             NetTxConnection connection = new NetTxConnection(this.BrokerUri, transport, this.ClientIdGenerator);
 
-            Uri brokerUri = this.BrokerUri;
-
-            // Set properties on the Receovery Policy using parameters prefixed with "nms.RecoveryPolicy."
-            if(!String.IsNullOrEmpty(brokerUri.Query) && !brokerUri.OriginalString.EndsWith(")"))
-            {
-                string query = brokerUri.Query.Substring(brokerUri.Query.LastIndexOf(")") + 1);
-                StringDictionary options = URISupport.ParseQuery(query);
-                options = URISupport.GetProperties(options, "nms.RecoveryPolicy.");
-                URISupport.SetProperties(this.recoveryPolicy, options);
-            }
-
-            connection.RecoveryPolicy = this.recoveryPolicy;
+            connection.RecoveryPolicy = this.recoveryPolicy.Clone() as NetTxRecoveryPolicy;
 
             return connection;
         }

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxRecoveryPolicy.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxRecoveryPolicy.cs?rev=1066209&r1=1066208&r2=1066209&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxRecoveryPolicy.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/NetTxRecoveryPolicy.cs Tue Feb  1 21:14:36 2011
@@ -28,7 +28,7 @@ namespace Apache.NMS.ActiveMQ
     /// Policy class used to configure the options associated with TX
     /// recovery.
     /// </summary>
-    public class NetTxRecoveryPolicy
+    public class NetTxRecoveryPolicy : ICloneable
     {
         private static readonly FactoryFinder<RecoveryLoggerFactoryAttribute, IRecoveryLoggerFactory> FACTORY_FINDER =
             new FactoryFinder<RecoveryLoggerFactoryAttribute, IRecoveryLoggerFactory>();
@@ -115,6 +115,11 @@ namespace Apache.NMS.ActiveMQ
                 throw new NMSException("Failed to find Factory for Recovery Logger type: " + scheme);
             }
         }
+
+        public Object Clone()
+        {
+            return this.MemberwiseClone();
+        }        
     }
 }
 

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs?rev=1066209&r1=1066208&r2=1066209&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Transactions/RecoveryFileLogger.cs Tue Feb  1 21:14:36 2011
@@ -56,7 +56,15 @@ namespace Apache.NMS.ActiveMQ.Transactio
         /// </summary>
         public string Location
         {
-            get { return this.location; }
+            get
+            {
+                if(String.IsNullOrEmpty(this.location))
+                {
+                    return Directory.GetCurrentDirectory();
+                }
+
+                return this.location;
+            }
             set { this.location = value; }
         }
 
@@ -74,32 +82,25 @@ namespace Apache.NMS.ActiveMQ.Transactio
         {
             this.resourceManagerId = resourceManagerId;
 
-            if(String.IsNullOrEmpty(location))
+            // Test if the location configured is valid.
+            if(!Directory.Exists(Location))
             {
-                this.location = Directory.GetCurrentDirectory();
-            }
-            else
-            {
-                // Test if the location configured is valid.
-                if(!Directory.Exists(location))
+                if(AutoCreateLocation)
                 {
-                    if(AutoCreateLocation)
+                    try
                     {
-                        try
-                        {
-                            Directory.CreateDirectory(Location);
-                        }
-                        catch(Exception ex)
-                        {
-                            Tracer.Error("Failed to create log directory: " + ex.Message);
-                            throw NMSExceptionSupport.Create(ex);
-                        }
+                        Directory.CreateDirectory(Location);
                     }
-                    else
+                    catch(Exception ex)
                     {
-                        throw new NMSException("Configured Recovery Log Location does not exist: " + location);
+                        Tracer.Error("Failed to create log directory: " + ex.Message);
+                        throw NMSExceptionSupport.Create(ex);
                     }
                 }
+                else
+                {
+                    throw new NMSException("Configured Recovery Log Location does not exist: " + location);
+                }
             }
         }
 

Added: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/IntrospectionSupport.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/IntrospectionSupport.cs?rev=1066209&view=auto
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/IntrospectionSupport.cs (added)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/IntrospectionSupport.cs Tue Feb  1 21:14:36 2011
@@ -0,0 +1,184 @@
+/*
+ * 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.Reflection;
+using System.Globalization;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+
+using Apache.NMS;
+using Apache.NMS.Util;
+
+namespace Apache.NMS.ActiveMQ.Util
+{
+    /// <summary>
+    /// Utility class used to provide conveince methods that apply named property
+    /// settings to objects.
+    /// </summary>
+    public class IntrospectionSupport
+    {
+        /// <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)
+        {
+            SetProperties(target, map, "");
+        }
+
+        /// <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)
+        {
+            Tracer.DebugFormat("SetProperties called with target: {0}, and prefix: {1}",
+                               target.GetType().Name, prefix);
+
+            foreach(string key in map.Keys)
+            {
+                if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
+                {
+                    string propertyName = key.Substring(prefix.Length);
+
+                    // Process all member assignments at this level before processing
+                    // any deeper member assignments.
+                    if(!propertyName.Contains("."))
+                    {
+                        MemberInfo member = FindPropertyInfo(target, propertyName);
+
+                        if(member == null)
+                        {
+                            throw new NMSException(string.Format("No such property or field: {0} on class: {1}", propertyName, target.GetType().Name));
+                        }
+
+                        try
+                        {
+                            if(member.MemberType == MemberTypes.Property)
+                            {
+                                PropertyInfo property = member as PropertyInfo;
+                                property.SetValue(target, Convert.ChangeType(map[key], property.PropertyType, CultureInfo.InvariantCulture), null);
+                            }
+                            else
+                            {
+                                FieldInfo field = member as FieldInfo;
+                                field.SetValue(target, Convert.ChangeType(map[key], field.FieldType, CultureInfo.InvariantCulture));
+                            }
+                        }
+                        catch(Exception ex)
+                        {
+                            throw NMSExceptionSupport.Create("Error while attempting to apply option.", ex);
+                        }
+                    }
+                }
+            }
+
+            IList<string> propertiesSet = new List<string>();
+
+            // Now process any compound assignments, ensuring that once we recurse into an
+            // object we don't do it again as there could be multiple compunds element assignments
+            // and they'd have already been processed recursively.
+            foreach(string key in map.Keys)
+            {
+                if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
+                {
+                    string propertyName = key.Substring(prefix.Length);
+
+                    if(propertyName.Contains("."))
+                    {
+                        string newTargetName = propertyName.Substring(0, propertyName.IndexOf('.'));
+                        string newPrefix = prefix + newTargetName + ".";
+
+                        if(!propertiesSet.Contains(newPrefix))
+                        {
+                            MemberInfo member = FindPropertyInfo(target, newTargetName);
+                            object newTarget = GetUnderlyingObject(member, target);
+                            SetProperties(newTarget, map, newPrefix);
+                            propertiesSet.Add(newPrefix);
+                        }
+                    }
+                }
+            }
+        }
+
+        private static object GetUnderlyingObject(MemberInfo member, object target)
+        {
+            object result = null;
+
+            if(member.MemberType == MemberTypes.Field)
+            {
+                FieldInfo field = member as FieldInfo;
+
+                if(field.FieldType.IsPrimitive)
+                {
+                    throw new NMSException("The field given is a priomitive type: " + member.Name);
+                }
+
+                result = field.GetValue(target);
+            }
+            else
+            {
+                PropertyInfo property = member as PropertyInfo;
+                MethodInfo getter = property.GetGetMethod();
+
+                if(getter == null)
+                {
+                    throw new NMSException("Cannot access member: " + member.Name);
+                }
+
+                result = getter.Invoke(target, null);
+            }
+
+            if(result == null)
+            {
+                throw new NMSException(String.Format("Could not retrieve the value of member {0}."), member.Name);
+            }
+
+            return result;
+        }
+
+        private static MemberInfo FindPropertyInfo(object target, string name)
+        {
+            BindingFlags flags = BindingFlags.FlattenHierarchy
+                               | BindingFlags.Public
+                               | BindingFlags.Instance
+                               | BindingFlags.IgnoreCase;
+
+            Type type = target.GetType();
+
+            MemberInfo member = type.GetProperty(name, flags);
+
+            if(member == null)
+            {
+                member = type.GetField(name, flags);
+            }
+
+            return member;
+        }
+
+    }
+}
+

Propchange: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/IntrospectionSupport.cs
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/NetTxConnectionFactoryTest.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/NetTxConnectionFactoryTest.cs?rev=1066209&r1=1066208&r2=1066209&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/NetTxConnectionFactoryTest.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/NetTxConnectionFactoryTest.cs Tue Feb  1 21:14:36 2011
@@ -16,10 +16,13 @@
  */
 
 using System;
+using System.IO;
+
 using NUnit.Framework;
 using Apache.NMS.Test;
 using Apache.NMS.Util;
 using Apache.NMS.ActiveMQ;
+using Apache.NMS.ActiveMQ.Transactions;
 
 namespace Apache.NMS.ActiveMQ.Test
 {
@@ -192,6 +195,71 @@ namespace Apache.NMS.ActiveMQ.Test
                 Assert.AreEqual(dispatchAsync, connection.DispatchAsync);
             }
         }
+
+        [Test]
+        public void TestConfigureRecoveryPolicyLoggerType(
+            [Values("tcp://${activemqhost}:61616?nms.RecoveryPolicy.RecoveryLoggerType=file")]
+            string baseConnectionURI)
+        {
+            INetTxConnectionFactory factory = new NetTxConnectionFactory(NMSTestSupport.ReplaceEnvVar(baseConnectionURI));
+
+            using(INetTxConnection connection = factory.CreateNetTxConnection())
+            {
+                NetTxConnection netTxConnection = connection as NetTxConnection;
+
+                Assert.IsNotNull(netTxConnection);
+                NetTxRecoveryPolicy policy = netTxConnection.RecoveryPolicy;
+
+                Assert.AreEqual("file", policy.RecoveryLoggerType);
+
+                RecoveryFileLogger logger = policy.RecoveryLogger as RecoveryFileLogger;
+
+                Assert.IsNotNull(logger);
+                Assert.AreEqual(Directory.GetCurrentDirectory(), logger.Location);
+            }
+        }
+
+        [Test]
+        [TestCase("/var/log/nms/recovery/", true)]
+        [TestCase("/var/temp/log/nms/recovery/", false)]
+        public void TestConfigureRecoveryPolicyLogger(string location, bool autoCreate)
+        {
+            string testuri = string.Format("activemq:tcp://${{activemqhost}}:61616" +
+                                           "?nms.RecoveryPolicy.RecoveryLoggerType=file" +
+                                           "&nms.RecoveryPolicy.RecoveryLogger.Location={0}" +
+                                           "&nms.RecoveryPolicy.RecoveryLogger.AutoCreateLocation={1}",
+                                           location, autoCreate);
+
+            INetTxConnectionFactory factory = new NetTxConnectionFactory(NMSTestSupport.ReplaceEnvVar(testuri));
+
+            using(INetTxConnection connection = factory.CreateNetTxConnection())
+            {
+                NetTxConnection netTxConnection = connection as NetTxConnection;
+
+                Assert.IsNotNull(netTxConnection);
+                NetTxRecoveryPolicy policy = netTxConnection.RecoveryPolicy;
+
+                Assert.AreEqual("file", policy.RecoveryLoggerType);
+
+                RecoveryFileLogger logger = policy.RecoveryLogger as RecoveryFileLogger;
+
+                Assert.IsNotNull(logger);
+                Assert.AreEqual(location, logger.Location);
+                Assert.AreEqual(autoCreate, logger.AutoCreateLocation);
+            }
+        }
+
+        [Test]
+        [ExpectedException( "Apache.NMS.NMSException" )]
+        public void TestConfigureRecoveryPolicyLoggerTypeWithInvalidType(
+            [Values("tcp://${activemqhost}:61616?nms.RecoveryPolicy.RecoveryLoggerType=invalid")]
+            string baseConnectionURI)
+        {
+            INetTxConnectionFactory factory =
+                new NetTxConnectionFactory(NMSTestSupport.ReplaceEnvVar(baseConnectionURI));
+
+            using(IConnection connection = factory.CreateConnection()){}
+        }
     }
 }
 

Modified: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs?rev=1066209&r1=1066208&r2=1066209&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Transactions/RecoveryFileLoggerTest.cs Tue Feb  1 21:14:36 2011
@@ -24,7 +24,7 @@ using NUnit.Framework;
 using Apache.NMS.ActiveMQ.Transactions;
 using Apache.NMS.ActiveMQ.Commands;
 
-namespace Apache.NMS.ActiveMQ.Transactions.Test
+namespace Apache.NMS.ActiveMQ.Test.Transactions
 {
     [TestFixture]
     public class RecoveryFileLoggerTest