http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/FactoryFinder.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/FactoryFinder.java 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/FactoryFinder.java
new file mode 100644
index 0000000..ffd0726
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/FactoryFinder.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class FactoryFinder
+{
+   /**
+    * The strategy that the FactoryFinder uses to find load and instantiate 
Objects
+    * can be changed out by calling the
+    * {@link 
org.apache.activemq6.utils.FactoryFinder#setObjectFactory(org.hornetq.utils.FactoryFinder.ObjectFactory)}
+    * method with a custom implementation of ObjectFactory.
+    * <p/>
+    * The default ObjectFactory is typically changed out when running in a 
specialized container
+    * environment where service discovery needs to be done via the container 
system.  For example,
+    * in an OSGi scenario.
+    */
+   public interface ObjectFactory
+   {
+      /**
+       * @param path the full service path
+       * @return
+       */
+      Object create(String path) throws IllegalAccessException, 
InstantiationException, IOException, ClassNotFoundException;
+
+   }
+
+   /**
+    * The default implementation of Object factory which works well in 
standalone applications.
+    */
+   protected static class StandaloneObjectFactory implements ObjectFactory
+   {
+      final ConcurrentHashMap<String, Class> classMap = new 
ConcurrentHashMap<String, Class>();
+
+      public Object create(final String path) throws InstantiationException, 
IllegalAccessException, ClassNotFoundException, IOException
+      {
+         Class clazz = classMap.get(path);
+         if (clazz == null)
+         {
+            clazz = loadClass(loadProperties(path));
+            classMap.put(path, clazz);
+         }
+         return clazz.newInstance();
+      }
+
+      static Class loadClass(Properties properties) throws 
ClassNotFoundException, IOException
+      {
+
+         String className = properties.getProperty("class");
+         if (className == null)
+         {
+            throw new IOException("Expected property is missing: class");
+         }
+         Class clazz = null;
+         ClassLoader loader = Thread.currentThread().getContextClassLoader();
+         if (loader != null)
+         {
+            try
+            {
+               clazz = loader.loadClass(className);
+            }
+            catch (ClassNotFoundException e)
+            {
+               // ignore
+            }
+         }
+         if (clazz == null)
+         {
+            clazz = FactoryFinder.class.getClassLoader().loadClass(className);
+         }
+
+         return clazz;
+      }
+
+      public Properties loadProperties(String uri) throws IOException
+      {
+         // lets try the thread context class loader first
+         ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+         if (classLoader == null)
+         {
+            classLoader = StandaloneObjectFactory.class.getClassLoader();
+         }
+         InputStream in = classLoader.getResourceAsStream(uri);
+         if (in == null)
+         {
+            in = FactoryFinder.class.getClassLoader().getResourceAsStream(uri);
+            if (in == null)
+            {
+               throw new IOException("Could not find factory class for 
resource: " + uri);
+            }
+         }
+
+         // lets load the file
+         BufferedInputStream reader = null;
+         try
+         {
+            reader = new BufferedInputStream(in);
+            Properties properties = new Properties();
+            properties.load(reader);
+            return properties;
+         }
+         finally
+         {
+            try
+            {
+               reader.close();
+            }
+            catch (Exception e)
+            {
+            }
+         }
+      }
+   }
+
+   // ================================================================
+   // Class methods and properties
+   // ================================================================
+   private static ObjectFactory objectFactory = new StandaloneObjectFactory();
+
+   public static ObjectFactory getObjectFactory()
+   {
+      return objectFactory;
+   }
+
+   public static void setObjectFactory(ObjectFactory objectFactory)
+   {
+      FactoryFinder.objectFactory = objectFactory;
+   }
+
+   // ================================================================
+   // Instance methods and properties
+   // ================================================================
+   private final String path;
+
+   public FactoryFinder(String path)
+   {
+      this.path = path;
+   }
+
+   /**
+    * Creates a new instance of the given key
+    *
+    * @param key is the key to add to the path to find a text file containing
+    *            the factory name
+    * @return a newly created instance
+    */
+   public Object newInstance(String key) throws IllegalAccessException, 
InstantiationException, IOException, ClassNotFoundException
+   {
+      return objectFactory.create(path + key);
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQThreadFactory.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQThreadFactory.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQThreadFactory.java
new file mode 100644
index 0000000..68341d3
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQThreadFactory.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ *
+ * A HornetQThreadFactory
+ *
+ * @author <a href="mailto:[email protected]";>Tim Fox</a>
+ *
+ */
+public final class HornetQThreadFactory implements ThreadFactory
+{
+   private final ThreadGroup group;
+
+   private final AtomicInteger threadCount = new AtomicInteger(0);
+
+   private final int threadPriority;
+
+   private final boolean daemon;
+
+   private final ClassLoader tccl;
+
+   public HornetQThreadFactory(final String groupName, final boolean daemon, 
final ClassLoader tccl)
+   {
+      group = new ThreadGroup(groupName + "-" + System.identityHashCode(this));
+
+      this.threadPriority = Thread.NORM_PRIORITY;
+
+      this.tccl = tccl;
+
+      this.daemon = daemon;
+   }
+
+   public Thread newThread(final Runnable command)
+   {
+      // always create a thread in a privileged block.
+      return AccessController.doPrivileged(new PrivilegedAction<Thread>()
+      {
+         @Override
+         public Thread run()
+         {
+            final Thread t = new Thread(group, command, "Thread-" + 
threadCount.getAndIncrement() + " (" + group.getName() + ")");
+            t.setDaemon(daemon);
+            t.setPriority(threadPriority);
+            t.setContextClassLoader(tccl);
+
+            return t;
+         }
+      });
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilBundle.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilBundle.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilBundle.java
new file mode 100644
index 0000000..42fc4c6
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilBundle.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+
+import org.apache.activemq6.api.core.HornetQIllegalStateException;
+import org.jboss.logging.annotations.Cause;
+import org.jboss.logging.annotations.Message;
+import org.jboss.logging.annotations.MessageBundle;
+import org.jboss.logging.Messages;
+
+/**
+ * @author <a href="mailto:[email protected]";>Andy Taylor</a>
+ *         3/12/12
+ *
+ * Logger Code 20
+ *
+ * each message id must be 6 digits long starting with 20, the 3rd digit 
should be 9
+ *
+ * so 209000 to 209999
+ */
+@MessageBundle(projectCode = "HQ")
+public interface HornetQUtilBundle
+{
+   HornetQUtilBundle BUNDLE = Messages.getBundle(HornetQUtilBundle.class);
+
+   @Message(id = 209000, value = "invalid property: {0}" , format = 
Message.Format.MESSAGE_FORMAT)
+   HornetQIllegalStateException invalidProperty(String part);
+
+   @Message(id = 209001, value = "Invalid type: {0}", format = 
Message.Format.MESSAGE_FORMAT)
+   IllegalStateException invalidType(Byte type);
+
+   @Message(id = 209002, value = "the specified string is too long ({0})", 
format = Message.Format.MESSAGE_FORMAT)
+   IllegalStateException stringTooLong(Integer length);
+
+   @Message(id = 209003, value = "Error instantiating codec {0}", format = 
Message.Format.MESSAGE_FORMAT)
+   IllegalArgumentException errorCreatingCodec(@Cause Exception e, String 
codecClassName);
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilLogger.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilLogger.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilLogger.java
new file mode 100644
index 0000000..5149f2a
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/HornetQUtilLogger.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import org.jboss.logging.BasicLogger;
+import org.jboss.logging.Logger;
+import org.jboss.logging.annotations.LogMessage;
+import org.jboss.logging.annotations.Message;
+import org.jboss.logging.annotations.MessageLogger;
+
+/**
+ * @author <a href="mailto:[email protected]";>Andy Taylor</a>
+ *         3/15/12
+ *
+ * Logger Code 20
+ *
+ * each message id must be 6 digits long starting with 20, the 3rd digit 
donates the level so
+ *
+ * INF0  1
+ * WARN  2
+ * DEBUG 3
+ * ERROR 4
+ * TRACE 5
+ * FATAL 6
+ *
+ * so an INFO message would be 201000 to 201999
+ */
+@MessageLogger(projectCode = "HQ")
+public interface HornetQUtilLogger extends BasicLogger
+{
+   /**
+    * The default logger.
+    */
+   HornetQUtilLogger LOGGER = Logger.getMessageLogger(HornetQUtilLogger.class, 
HornetQUtilLogger.class.getPackage().getName());
+
+   @LogMessage(level = Logger.Level.WARN)
+   @Message(id = 202000, value = "Missing privileges to set Thread Context 
Class Loader on Thread Factory. Using current Thread Context Class Loader",
+            format = Message.Format.MESSAGE_FORMAT)
+   void missingPrivsForClassloader();
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/PasswordMaskingUtil.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/PasswordMaskingUtil.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/PasswordMaskingUtil.java
new file mode 100644
index 0000000..c6b5052
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/PasswordMaskingUtil.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.activemq6.api.core.HornetQException;
+import org.apache.activemq6.api.core.HornetQExceptionType;
+
+/**
+ * A PasswordMarkingUtil
+ *
+ * @author <a href="mailto:[email protected]";>Howard Gao</a>
+ *
+ *
+ */
+public class PasswordMaskingUtil
+{
+   /*
+    * Loading the codec class.
+    *
+    * @param codecDesc This parameter must have the following format:
+    *
+    * <full qualified class name>;key=value;key1=value1;...
+    *
+    * Where only <full qualified class name> is required. key/value pairs are 
optional
+    */
+   public static SensitiveDataCodec<String> getCodec(String codecDesc) throws 
HornetQException
+   {
+      SensitiveDataCodec<String> codecInstance = null;
+
+      // semi colons
+      String[] parts = codecDesc.split(";");
+
+      if (parts.length < 1)
+         throw new HornetQException(HornetQExceptionType.ILLEGAL_STATE, 
"Invalid PasswordCodec value: " + codecDesc);
+
+      final String codecClassName = parts[0];
+
+      // load class
+      codecInstance = AccessController.doPrivileged(new 
PrivilegedAction<SensitiveDataCodec<String>>()
+      {
+         public SensitiveDataCodec<String> run()
+         {
+            ClassLoader loader = 
Thread.currentThread().getContextClassLoader();
+            try
+            {
+               Class<?> clazz = loader.loadClass(codecClassName);
+               return (SensitiveDataCodec<String>)clazz.newInstance();
+            }
+            catch (Exception e)
+            {
+               throw HornetQUtilBundle.BUNDLE.errorCreatingCodec(e, 
codecClassName);
+            }
+         }
+      });
+
+      if (parts.length > 1)
+      {
+         Map<String, String> props = new HashMap<String, String>();
+
+         for (int i = 1; i < parts.length; i++)
+         {
+            String[] keyVal = parts[i].split("=");
+            if (keyVal.length != 2)
+               throw HornetQUtilBundle.BUNDLE.invalidProperty(parts[i]);
+            props.put(keyVal[0], keyVal[1]);
+         }
+         codecInstance.init(props);
+      }
+
+      return codecInstance;
+   }
+
+   public static SensitiveDataCodec<String> getDefaultCodec()
+   {
+      return new DefaultSensitiveStringCodec();
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounter.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounter.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounter.java
new file mode 100644
index 0000000..bbf887f
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounter.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+/**
+ * @author Clebert Suconic
+ */
+
+public interface ReferenceCounter
+{
+   int increment();
+
+   int decrement();
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounterUtil.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounterUtil.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounterUtil.java
new file mode 100644
index 0000000..eed841a
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReferenceCounterUtil.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Clebert Suconic
+ */
+
+public class ReferenceCounterUtil implements ReferenceCounter
+{
+   private final Runnable runnable;
+
+   /** If executor is null the runnable will be called within the same thread, 
otherwise the executor will be used */
+   private final Executor executor;
+
+   private final AtomicInteger uses = new AtomicInteger(0);
+
+
+   public ReferenceCounterUtil(Runnable runnable)
+   {
+      this(runnable, null);
+   }
+
+   public ReferenceCounterUtil(Runnable runnable, Executor executor)
+   {
+      this.runnable = runnable;
+      this.executor = executor;
+   }
+
+   @Override
+   public int increment()
+   {
+      return uses.incrementAndGet();
+   }
+
+   @Override
+   public int decrement()
+   {
+      int value = uses.decrementAndGet();
+      if (value == 0)
+      {
+         if (executor != null)
+         {
+            executor.execute(runnable);
+         }
+         else
+         {
+            runnable.run();
+         }
+      }
+
+      return value;
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReusableLatch.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReusableLatch.java 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReusableLatch.java
new file mode 100644
index 0000000..deecfd1
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/ReusableLatch.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.AbstractQueuedSynchronizer;
+
+/**
+ *
+ * <p>This class will use the framework provided to by 
AbstractQueuedSynchronizer.</p>
+ * <p>AbstractQueuedSynchronizer is the framework for any sort of concurrent 
synchronization, such as Semaphores, events, etc, based on AtomicIntegers.</p>
+ *
+ * <p>This class works just like CountDownLatch, with the difference you can 
also increase the counter</p>
+ *
+ * <p>It could be used for sync points when one process is feeding the latch 
while another will wait when everything is done. (e.g. waiting IO completions 
to finish)</p>
+ *
+ * <p>On HornetQ we have the requirement of increment and decrement a counter 
until the user fires a ready event (commit). At that point we just act as a 
regular countDown.</p>
+ *
+ * <p>Note: This latch is reusable. Once it reaches zero, you can call up 
again, and reuse it on further waits.</p>
+ *
+ * <p>For example: prepareTransaction will wait for the current completions, 
and further adds will be called on the latch. Later on when commit is called 
you can reuse the same latch.</p>
+ *
+ * @author Clebert Suconic
+ * */
+public class ReusableLatch
+{
+   /**
+    * Look at the doc and examples provided by AbstractQueuedSynchronizer for 
more information
+    * @see AbstractQueuedSynchronizer*/
+   @SuppressWarnings("serial")
+   private static class CountSync extends AbstractQueuedSynchronizer
+   {
+      public CountSync(int count)
+      {
+         setState(count);
+      }
+
+      public int getCount()
+      {
+         return getState();
+      }
+
+      public void setCount(final int count)
+      {
+         setState(count);
+      }
+
+      @Override
+      public int tryAcquireShared(final int numberOfAqcquires)
+      {
+         return getState() == 0 ? 1 : -1;
+      }
+
+      public void add()
+      {
+         for (;;)
+         {
+            int actualState = getState();
+            int newState = actualState + 1;
+            if (compareAndSetState(actualState, newState))
+            {
+               return;
+            }
+         }
+      }
+
+      @Override
+      public boolean tryReleaseShared(final int numberOfReleases)
+      {
+         for (;;)
+         {
+            int actualState = getState();
+            if (actualState == 0)
+            {
+               return true;
+            }
+
+            int newState = actualState - numberOfReleases;
+
+            if (newState < 0)
+            {
+               newState = 0;
+            }
+
+            if (compareAndSetState(actualState, newState))
+            {
+               return newState == 0;
+            }
+         }
+      }
+   }
+
+   private final CountSync control;
+
+   public ReusableLatch()
+   {
+      this(0);
+   }
+
+   public ReusableLatch(final int count)
+   {
+      control = new CountSync(count);
+   }
+
+   public int getCount()
+   {
+      return control.getCount();
+   }
+
+   public void setCount(final int count)
+   {
+      control.setCount(count);
+   }
+
+   public void countUp()
+   {
+      control.add();
+   }
+
+   public void countDown()
+   {
+      control.releaseShared(1);
+   }
+
+
+   public void countDown(final int count)
+   {
+      control.releaseShared(count);
+   }
+
+   public void await() throws InterruptedException
+   {
+      control.acquireSharedInterruptibly(1);
+   }
+
+   public boolean await(final long milliseconds) throws InterruptedException
+   {
+      return control.tryAcquireSharedNanos(1, 
TimeUnit.MILLISECONDS.toNanos(milliseconds));
+   }
+
+   public boolean await(final long timeWait, TimeUnit timeUnit) throws 
InterruptedException
+   {
+      return control.tryAcquireSharedNanos(1, timeUnit.toNanos(timeWait));
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/SensitiveDataCodec.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/SensitiveDataCodec.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/SensitiveDataCodec.java
new file mode 100644
index 0000000..0bf6c52
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/SensitiveDataCodec.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.util.Map;
+
+/**
+ * A SensitiveDataCodec
+ *
+ * This interface is used for implementing a value decoder.
+ *
+ * It takes in a mask value and decode it.
+ *
+ * @author <a href="mailto:[email protected]";>Howard Gao</a>
+ *
+ *
+ */
+public interface SensitiveDataCodec<T>
+{
+   T decode(Object mask) throws Exception;
+
+   void init(Map<String, String> params);
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/TypedProperties.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/TypedProperties.java
 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/TypedProperties.java
new file mode 100644
index 0000000..6e5d54d
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/TypedProperties.java
@@ -0,0 +1,1212 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.nio.ByteBuffer;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.apache.activemq6.api.core.HornetQBuffer;
+import org.apache.activemq6.api.core.HornetQPropertyConversionException;
+import org.apache.activemq6.api.core.SimpleString;
+
+import static org.apache.activemq6.utils.DataConstants.BOOLEAN;
+import static org.apache.activemq6.utils.DataConstants.BYTE;
+import static org.apache.activemq6.utils.DataConstants.BYTES;
+import static org.apache.activemq6.utils.DataConstants.CHAR;
+import static org.apache.activemq6.utils.DataConstants.DOUBLE;
+import static org.apache.activemq6.utils.DataConstants.FLOAT;
+import static org.apache.activemq6.utils.DataConstants.INT;
+import static org.apache.activemq6.utils.DataConstants.LONG;
+import static org.apache.activemq6.utils.DataConstants.NULL;
+import static org.apache.activemq6.utils.DataConstants.SHORT;
+import static org.apache.activemq6.utils.DataConstants.STRING;
+
+/**
+ * Property Value Conversion.
+ * <p>
+ * This implementation follows section 3.5.4 of the <i>Java Message 
Service</i> specification
+ * (Version 1.1 April 12, 2002).
+ * <p>
+ * TODO - should have typed property getters and do conversions herein
+ *
+ * @author <a href="mailto:[email protected]";>Tim Fox</a>
+ * @author <a href="mailto:[email protected]";>Clebert Suconic</a>
+ */
+public final class TypedProperties
+{
+
+   private static final SimpleString HQ_PROPNAME = new SimpleString("_HQ_");
+
+   private Map<SimpleString, PropertyValue> properties;
+
+   private volatile int size;
+
+   private boolean internalProperties;
+
+   public TypedProperties()
+   {
+   }
+
+   public int getMemoryOffset()
+   {
+      // The estimate is basically the encode size + 2 object references for 
each entry in the map
+      // Note we don't include the attributes or anything else since they 
already included in the memory estimate
+      // of the ServerMessage
+
+      return properties == null ? 0 : size + 2 * DataConstants.SIZE_INT * 
properties.size();
+   }
+
+   public TypedProperties(final TypedProperties other)
+   {
+      properties = other.properties == null ? null : new HashMap<SimpleString, 
PropertyValue>(other.properties);
+      size = other.size;
+   }
+
+   public boolean hasInternalProperties()
+   {
+      return internalProperties;
+   }
+
+   public void putBooleanProperty(final SimpleString key, final boolean value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new BooleanValue(value));
+   }
+
+   public void putByteProperty(final SimpleString key, final byte value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new ByteValue(value));
+   }
+
+   public void putBytesProperty(final SimpleString key, final byte[] value)
+   {
+      checkCreateProperties();
+      doPutValue(key, value == null ? new NullValue() : new BytesValue(value));
+   }
+
+   public void putShortProperty(final SimpleString key, final short value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new ShortValue(value));
+   }
+
+   public void putIntProperty(final SimpleString key, final int value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new IntValue(value));
+   }
+
+   public void putLongProperty(final SimpleString key, final long value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new LongValue(value));
+   }
+
+   public void putFloatProperty(final SimpleString key, final float value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new FloatValue(value));
+   }
+
+   public void putDoubleProperty(final SimpleString key, final double value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new DoubleValue(value));
+   }
+
+   public void putSimpleStringProperty(final SimpleString key, final 
SimpleString value)
+   {
+      checkCreateProperties();
+      doPutValue(key, value == null ? new NullValue() : new 
StringValue(value));
+   }
+
+   public void putNullValue(final SimpleString key)
+   {
+      checkCreateProperties();
+      doPutValue(key, new NullValue());
+   }
+
+   public void putCharProperty(final SimpleString key, final char value)
+   {
+      checkCreateProperties();
+      doPutValue(key, new CharValue(value));
+   }
+
+   public void putTypedProperties(final TypedProperties otherProps)
+   {
+      if (otherProps == null || otherProps.properties == null)
+      {
+         return;
+      }
+
+      checkCreateProperties();
+      Set<Entry<SimpleString, PropertyValue>> otherEntries = 
otherProps.properties.entrySet();
+      for (Entry<SimpleString, PropertyValue> otherEntry : otherEntries)
+      {
+         doPutValue(otherEntry.getKey(), otherEntry.getValue());
+      }
+   }
+
+   public Object getProperty(final SimpleString key)
+   {
+      return doGetProperty(key);
+   }
+
+   public Boolean getBooleanProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         return Boolean.valueOf(null);
+      }
+      else if (value instanceof Boolean)
+      {
+         return (Boolean) value;
+      }
+      else if (value instanceof SimpleString)
+      {
+         return Boolean.valueOf(((SimpleString) value).toString());
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid conversion");
+      }
+   }
+
+   public Byte getByteProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         return Byte.valueOf(null);
+      }
+      else if (value instanceof Byte)
+      {
+         return (Byte) value;
+      }
+      else if (value instanceof SimpleString)
+      {
+         return Byte.parseByte(((SimpleString) value).toString());
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid conversion");
+      }
+   }
+
+   public Character getCharProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         throw new NullPointerException("Invalid conversion");
+      }
+
+      if (value instanceof Character)
+      {
+         return ((Character) value);
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid conversion");
+      }
+   }
+
+   public byte[] getBytesProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         return null;
+      }
+      else if (value instanceof byte[])
+      {
+         return (byte[]) value;
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid conversion");
+      }
+   }
+
+   public Double getDoubleProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         return Double.valueOf(null);
+      }
+      else if (value instanceof Float)
+      {
+         return ((Float) value).doubleValue();
+      }
+      else if (value instanceof Double)
+      {
+         return (Double) value;
+      }
+      else if (value instanceof SimpleString)
+      {
+         return Double.parseDouble(((SimpleString) value).toString());
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid conversion");
+      }
+   }
+
+   public Integer getIntProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         return Integer.valueOf(null);
+      }
+      else if (value instanceof Integer)
+      {
+         return (Integer) value;
+      }
+      else if (value instanceof Byte)
+      {
+         return ((Byte) value).intValue();
+      }
+      else if (value instanceof Short)
+      {
+         return ((Short) value).intValue();
+      }
+      else if (value instanceof SimpleString)
+      {
+         return Integer.parseInt(((SimpleString) value).toString());
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid conversion");
+      }
+   }
+
+   public Long getLongProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         return Long.valueOf(null);
+      }
+      else if (value instanceof Long)
+      {
+         return (Long) value;
+      }
+      else if (value instanceof Byte)
+      {
+         return ((Byte) value).longValue();
+      }
+      else if (value instanceof Short)
+      {
+         return ((Short) value).longValue();
+      }
+      else if (value instanceof Integer)
+      {
+         return ((Integer) value).longValue();
+      }
+      else if (value instanceof SimpleString)
+      {
+         return Long.parseLong(((SimpleString) value).toString());
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid conversion");
+      }
+   }
+
+   public Short getShortProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+      {
+         return Short.valueOf(null);
+      }
+      else if (value instanceof Byte)
+      {
+         return ((Byte) value).shortValue();
+      }
+      else if (value instanceof Short)
+      {
+         return (Short) value;
+      }
+      else if (value instanceof SimpleString)
+      {
+         return Short.parseShort(((SimpleString) value).toString());
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException("Invalid Conversion.");
+      }
+   }
+
+   public Float getFloatProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+      if (value == null)
+         return Float.valueOf(null);
+      if (value instanceof Float)
+      {
+         return ((Float) value);
+      }
+      if (value instanceof SimpleString)
+      {
+         return Float.parseFloat(((SimpleString) value).toString());
+      }
+      throw new HornetQPropertyConversionException("Invalid conversion: " + 
key);
+   }
+
+   public SimpleString getSimpleStringProperty(final SimpleString key) throws 
HornetQPropertyConversionException
+   {
+      Object value = doGetProperty(key);
+
+      if (value == null)
+      {
+         return null;
+      }
+
+      if (value instanceof SimpleString)
+      {
+         return (SimpleString) value;
+      }
+      else if (value instanceof Boolean)
+      {
+         return new SimpleString(value.toString());
+      }
+      else if (value instanceof Character)
+      {
+         return new SimpleString(value.toString());
+      }
+      else if (value instanceof Byte)
+      {
+         return new SimpleString(value.toString());
+      }
+      else if (value instanceof Short)
+      {
+         return new SimpleString(value.toString());
+      }
+      else if (value instanceof Integer)
+      {
+         return new SimpleString(value.toString());
+      }
+      else if (value instanceof Long)
+      {
+         return new SimpleString(value.toString());
+      }
+      else if (value instanceof Float)
+      {
+         return new SimpleString(value.toString());
+      }
+      else if (value instanceof Double)
+      {
+         return new SimpleString(value.toString());
+      }
+      throw new HornetQPropertyConversionException("Invalid conversion");
+   }
+
+   public Object removeProperty(final SimpleString key)
+   {
+      return doRemoveProperty(key);
+   }
+
+   public boolean containsProperty(final SimpleString key)
+   {
+      if (size == 0)
+      {
+         return false;
+
+      }
+      else
+      {
+         return properties.containsKey(key);
+      }
+   }
+
+   public Set<SimpleString> getPropertyNames()
+   {
+      if (size == 0)
+      {
+         return Collections.emptySet();
+      }
+      else
+      {
+         return properties.keySet();
+      }
+   }
+
+   public synchronized void decode(final HornetQBuffer buffer)
+   {
+      byte b = buffer.readByte();
+
+      if (b == DataConstants.NULL)
+      {
+         properties = null;
+      }
+      else
+      {
+         int numHeaders = buffer.readInt();
+
+         properties = new HashMap<SimpleString, PropertyValue>(numHeaders);
+         size = 0;
+
+         for (int i = 0; i < numHeaders; i++)
+         {
+            int len = buffer.readInt();
+            byte[] data = new byte[len];
+            buffer.readBytes(data);
+            SimpleString key = new SimpleString(data);
+
+            byte type = buffer.readByte();
+
+            PropertyValue val;
+
+            switch (type)
+            {
+               case NULL:
+               {
+                  val = new NullValue();
+                  doPutValue(key, val);
+                  break;
+               }
+               case CHAR:
+               {
+                  val = new CharValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case BOOLEAN:
+               {
+                  val = new BooleanValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case BYTE:
+               {
+                  val = new ByteValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case BYTES:
+               {
+                  val = new BytesValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case SHORT:
+               {
+                  val = new ShortValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case INT:
+               {
+                  val = new IntValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case LONG:
+               {
+                  val = new LongValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case FLOAT:
+               {
+                  val = new FloatValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case DOUBLE:
+               {
+                  val = new DoubleValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               case STRING:
+               {
+                  val = new StringValue(buffer);
+                  doPutValue(key, val);
+                  break;
+               }
+               default:
+               {
+                  throw HornetQUtilBundle.BUNDLE.invalidType(type);
+               }
+            }
+         }
+      }
+   }
+
+   public synchronized void encode(final HornetQBuffer buffer)
+   {
+      if (properties == null)
+      {
+         buffer.writeByte(DataConstants.NULL);
+      }
+      else
+      {
+         buffer.writeByte(DataConstants.NOT_NULL);
+
+         buffer.writeInt(properties.size());
+
+         for (Map.Entry<SimpleString, PropertyValue> entry : 
properties.entrySet())
+         {
+            SimpleString s = entry.getKey();
+            byte[] data = s.getData();
+            buffer.writeInt(data.length);
+            buffer.writeBytes(data);
+
+            entry.getValue().write(buffer);
+         }
+      }
+   }
+
+   public int getEncodeSize()
+   {
+      if (properties == null)
+      {
+         return DataConstants.SIZE_BYTE;
+      }
+      else
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + size;
+      }
+   }
+
+   public void clear()
+   {
+      if (properties != null)
+      {
+         properties.clear();
+      }
+   }
+
+   @Override
+   public String toString()
+   {
+      StringBuilder sb = new StringBuilder("TypedProperties[");
+
+
+      if (properties != null)
+      {
+
+         Iterator<Entry<SimpleString, PropertyValue>> iter = 
properties.entrySet().iterator();
+
+         while (iter.hasNext())
+         {
+            Entry<SimpleString, PropertyValue> iterItem = iter.next();
+            sb.append(iterItem.getKey() + "=");
+
+            // it seems weird but it's right!!
+            // The first getValue is from the EntrySet
+            // The second is to convert the PropertyValue into the actual value
+            Object theValue = iterItem.getValue().getValue();
+
+
+            if (theValue == null)
+            {
+               sb.append("NULL-value");
+            }
+            else if (theValue instanceof byte[])
+            {
+               sb.append("[" + ByteUtil.maxString(ByteUtil.bytesToHex((byte 
[])theValue, 2), 150) + ")");
+
+               if (iterItem.getKey().toString().startsWith("_HQ_ROUTE_TO"))
+               {
+                  sb.append(",bytesAsLongs(");
+                  try
+                  {
+                     ByteBuffer buff = ByteBuffer.wrap((byte[]) theValue);
+                     while (buff.hasRemaining())
+                     {
+                        long bindingID = buff.getLong();
+                        sb.append(bindingID);
+                        if (buff.hasRemaining())
+                        {
+                           sb.append(",");
+                        }
+                     }
+                  }
+                  catch (Throwable e)
+                  {
+                     sb.append("error-converting-longs=" + e.getMessage());
+                  }
+                  sb.append("]");
+               }
+            }
+            else
+            {
+               sb.append(theValue.toString());
+            }
+
+
+            if (iter.hasNext())
+            {
+               sb.append(",");
+            }
+         }
+      }
+
+      return sb.append("]").toString();
+   }
+
+   // Private 
------------------------------------------------------------------------------------
+
+   private void checkCreateProperties()
+   {
+      if (properties == null)
+      {
+         properties = new HashMap<SimpleString, PropertyValue>();
+      }
+   }
+
+   private synchronized void doPutValue(final SimpleString key, final 
PropertyValue value)
+   {
+      if (key.startsWith(HQ_PROPNAME))
+      {
+         internalProperties = true;
+      }
+
+      PropertyValue oldValue = properties.put(key, value);
+      if (oldValue != null)
+      {
+         size += value.encodeSize() - oldValue.encodeSize();
+      }
+      else
+      {
+         size += SimpleString.sizeofString(key) + value.encodeSize();
+      }
+   }
+
+   private synchronized Object doRemoveProperty(final SimpleString key)
+   {
+      if (properties == null)
+      {
+         return null;
+      }
+
+      PropertyValue val = properties.remove(key);
+
+      if (val == null)
+      {
+         return null;
+      }
+      else
+      {
+         size -= SimpleString.sizeofString(key) + val.encodeSize();
+
+         return val.getValue();
+      }
+   }
+
+   private synchronized Object doGetProperty(final Object key)
+   {
+      if (size == 0)
+      {
+         return null;
+      }
+
+      PropertyValue val = properties.get(key);
+
+      if (val == null)
+      {
+         return null;
+      }
+      else
+      {
+         return val.getValue();
+      }
+   }
+
+   // Inner classes 
------------------------------------------------------------------------------
+
+   private abstract static class PropertyValue
+   {
+      abstract Object getValue();
+
+      abstract void write(HornetQBuffer buffer);
+
+      abstract int encodeSize();
+
+      @Override
+      public String toString()
+      {
+         return "" + getValue();
+      }
+   }
+
+   private static final class NullValue extends PropertyValue
+   {
+      public NullValue()
+      {
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return null;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.NULL);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE;
+      }
+
+   }
+
+   private static final class BooleanValue extends PropertyValue
+   {
+      final boolean val;
+
+      public BooleanValue(final boolean val)
+      {
+         this.val = val;
+      }
+
+      public BooleanValue(final HornetQBuffer buffer)
+      {
+         val = buffer.readBoolean();
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.BOOLEAN);
+         buffer.writeBoolean(val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_BOOLEAN;
+      }
+
+   }
+
+   private static final class ByteValue extends PropertyValue
+   {
+      final byte val;
+
+      public ByteValue(final byte val)
+      {
+         this.val = val;
+      }
+
+      public ByteValue(final HornetQBuffer buffer)
+      {
+         val = buffer.readByte();
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.BYTE);
+         buffer.writeByte(val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_BYTE;
+      }
+   }
+
+   private static final class BytesValue extends PropertyValue
+   {
+      final byte[] val;
+
+      public BytesValue(final byte[] val)
+      {
+         this.val = val;
+      }
+
+      public BytesValue(final HornetQBuffer buffer)
+      {
+         int len = buffer.readInt();
+         val = new byte[len];
+         buffer.readBytes(val);
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.BYTES);
+         buffer.writeInt(val.length);
+         buffer.writeBytes(val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + val.length;
+      }
+
+   }
+
+   private static final class ShortValue extends PropertyValue
+   {
+      final short val;
+
+      public ShortValue(final short val)
+      {
+         this.val = val;
+      }
+
+      public ShortValue(final HornetQBuffer buffer)
+      {
+         val = buffer.readShort();
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.SHORT);
+         buffer.writeShort(val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_SHORT;
+      }
+   }
+
+   private static final class IntValue extends PropertyValue
+   {
+      final int val;
+
+      public IntValue(final int val)
+      {
+         this.val = val;
+      }
+
+      public IntValue(final HornetQBuffer buffer)
+      {
+         val = buffer.readInt();
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.INT);
+         buffer.writeInt(val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_INT;
+      }
+   }
+
+   private static final class LongValue extends PropertyValue
+   {
+      final long val;
+
+      public LongValue(final long val)
+      {
+         this.val = val;
+      }
+
+      public LongValue(final HornetQBuffer buffer)
+      {
+         val = buffer.readLong();
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.LONG);
+         buffer.writeLong(val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_LONG;
+      }
+   }
+
+   private static final class FloatValue extends PropertyValue
+   {
+      final float val;
+
+      public FloatValue(final float val)
+      {
+         this.val = val;
+      }
+
+      public FloatValue(final HornetQBuffer buffer)
+      {
+         val = Float.intBitsToFloat(buffer.readInt());
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.FLOAT);
+         buffer.writeInt(Float.floatToIntBits(val));
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_FLOAT;
+      }
+
+   }
+
+   private static final class DoubleValue extends PropertyValue
+   {
+      final double val;
+
+      public DoubleValue(final double val)
+      {
+         this.val = val;
+      }
+
+      public DoubleValue(final HornetQBuffer buffer)
+      {
+         val = Double.longBitsToDouble(buffer.readLong());
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.DOUBLE);
+         buffer.writeLong(Double.doubleToLongBits(val));
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_DOUBLE;
+      }
+   }
+
+   private static final class CharValue extends PropertyValue
+   {
+      final char val;
+
+      public CharValue(final char val)
+      {
+         this.val = val;
+      }
+
+      public CharValue(final HornetQBuffer buffer)
+      {
+         val = (char) buffer.readShort();
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.CHAR);
+         buffer.writeShort((short) val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + DataConstants.SIZE_CHAR;
+      }
+   }
+
+   private static final class StringValue extends PropertyValue
+   {
+      final SimpleString val;
+
+      public StringValue(final SimpleString val)
+      {
+         this.val = val;
+      }
+
+      public StringValue(final HornetQBuffer buffer)
+      {
+         val = buffer.readSimpleString();
+      }
+
+      @Override
+      public Object getValue()
+      {
+         return val;
+      }
+
+      @Override
+      public void write(final HornetQBuffer buffer)
+      {
+         buffer.writeByte(DataConstants.STRING);
+         buffer.writeSimpleString(val);
+      }
+
+      @Override
+      public int encodeSize()
+      {
+         return DataConstants.SIZE_BYTE + SimpleString.sizeofString(val);
+      }
+   }
+
+   public boolean isEmpty()
+   {
+      return properties.isEmpty();
+   }
+
+   public Map<String, Object> getMap()
+   {
+      Map<String, Object> m = new HashMap<String, Object>();
+      for (Entry<SimpleString, PropertyValue> entry : properties.entrySet())
+      {
+         Object val = entry.getValue().getValue();
+         if (val instanceof SimpleString)
+         {
+            m.put(entry.getKey().toString(), ((SimpleString) val).toString());
+         }
+         else
+         {
+            m.put(entry.getKey().toString(), val);
+         }
+      }
+      return m;
+   }
+
+   /**
+    * Helper for {@link MapMessage#setObjectProperty(String, Object)}
+    *
+    * @param key
+    * @param value
+    * @param properties
+    */
+   public static void setObjectProperty(final SimpleString key, final Object 
value, final TypedProperties properties)
+   {
+      if (value == null)
+      {
+         properties.putNullValue(key);
+      }
+      else if (value instanceof Boolean)
+      {
+         properties.putBooleanProperty(key, (Boolean) value);
+      }
+      else if (value instanceof Byte)
+      {
+         properties.putByteProperty(key, (Byte) value);
+      }
+      else if (value instanceof Character)
+      {
+         properties.putCharProperty(key, (Character) value);
+      }
+      else if (value instanceof Short)
+      {
+         properties.putShortProperty(key, (Short) value);
+      }
+      else if (value instanceof Integer)
+      {
+         properties.putIntProperty(key, (Integer) value);
+      }
+      else if (value instanceof Long)
+      {
+         properties.putLongProperty(key, (Long) value);
+      }
+      else if (value instanceof Float)
+      {
+         properties.putFloatProperty(key, (Float) value);
+      }
+      else if (value instanceof Double)
+      {
+         properties.putDoubleProperty(key, (Double) value);
+      }
+      else if (value instanceof String)
+      {
+         properties.putSimpleStringProperty(key, new SimpleString((String) 
value));
+      }
+      else if (value instanceof SimpleString)
+      {
+         properties.putSimpleStringProperty(key, (SimpleString) value);
+      }
+      else if (value instanceof byte[])
+      {
+         properties.putBytesProperty(key, (byte[]) value);
+      }
+      else
+      {
+         throw new HornetQPropertyConversionException(value.getClass() + " is 
not a valid property type");
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/UTF8Util.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/UTF8Util.java 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/UTF8Util.java
new file mode 100644
index 0000000..fb087e5
--- /dev/null
+++ b/activemq6-commons/src/main/java/org/apache/activemq6/utils/UTF8Util.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2005-2014 Red Hat, Inc.
+ * Red Hat licenses this file to you under the Apache License, version
+ * 2.0 (the "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.  See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+package org.apache.activemq6.utils;
+
+import java.lang.ref.SoftReference;
+
+import org.apache.activemq6.api.core.HornetQBuffer;
+
+/**
+ *
+ * A UTF8Util
+ *
+ * This class will write UTFs directly to the ByteOutput (through the 
MessageBuffer interface)
+ *
+ * @author <a href="mailto:[email protected]";>Clebert Suconic</a>
+ *
+ * Created Feb 20, 2009 1:37:18 PM
+ *
+ *
+ */
+public final class UTF8Util
+{
+   private UTF8Util()
+   {
+      // utility class
+   }
+
+   private static final boolean isTrace = 
HornetQUtilLogger.LOGGER.isTraceEnabled();
+
+   private static final ThreadLocal<SoftReference<StringUtilBuffer>> 
currenBuffer =
+            new ThreadLocal<SoftReference<StringUtilBuffer>>();
+
+   public static void saveUTF(final HornetQBuffer out, final String str)
+   {
+      StringUtilBuffer buffer = UTF8Util.getThreadLocalBuffer();
+
+      if (str.length() > 0xffff)
+      {
+         throw HornetQUtilBundle.BUNDLE.stringTooLong(str.length());
+      }
+
+      final int len = UTF8Util.calculateUTFSize(str, buffer);
+
+      if (len > 0xffff)
+      {
+         throw HornetQUtilBundle.BUNDLE.stringTooLong(len);
+      }
+
+      out.writeShort((short)len);
+
+      if (len > buffer.byteBuffer.length)
+      {
+         buffer.resizeByteBuffer(len);
+      }
+
+      if (len == (long)str.length())
+      {
+         for (int byteLocation = 0; byteLocation < len; byteLocation++)
+         {
+            buffer.byteBuffer[byteLocation] = 
(byte)buffer.charBuffer[byteLocation];
+         }
+         out.writeBytes(buffer.byteBuffer, 0, len);
+      }
+      else
+      {
+         if (UTF8Util.isTrace)
+         {
+            // This message is too verbose for debug, that's why we are using 
trace here
+            HornetQUtilLogger.LOGGER.trace("Saving string with utfSize=" + len 
+ " stringSize=" + str.length());
+         }
+
+         int stringLength = str.length();
+
+         int charCount = 0;
+
+         for (int i = 0; i < stringLength; i++)
+         {
+            char charAtPos = buffer.charBuffer[i];
+            if (charAtPos >= 1 && charAtPos < 0x7f)
+            {
+               buffer.byteBuffer[charCount++] = (byte)charAtPos;
+            }
+            else if (charAtPos >= 0x800)
+            {
+               buffer.byteBuffer[charCount++] = (byte)(0xE0 | charAtPos >> 12 
& 0x0F);
+               buffer.byteBuffer[charCount++] = (byte)(0x80 | charAtPos >> 6 & 
0x3F);
+               buffer.byteBuffer[charCount++] = (byte)(0x80 | charAtPos >> 0 & 
0x3F);
+            }
+            else
+            {
+               buffer.byteBuffer[charCount++] = (byte)(0xC0 | charAtPos >> 6 & 
0x1F);
+               buffer.byteBuffer[charCount++] = (byte)(0x80 | charAtPos >> 0 & 
0x3F);
+            }
+         }
+         out.writeBytes(buffer.byteBuffer, 0, len);
+      }
+   }
+
+   public static String readUTF(final HornetQBuffer input)
+   {
+      StringUtilBuffer buffer = UTF8Util.getThreadLocalBuffer();
+
+      final int size = input.readUnsignedShort();
+
+      if (size > buffer.byteBuffer.length)
+      {
+         buffer.resizeByteBuffer(size);
+      }
+
+      if (size > buffer.charBuffer.length)
+      {
+         buffer.resizeCharBuffer(size);
+      }
+
+      if (UTF8Util.isTrace)
+      {
+         // This message is too verbose for debug, that's why we are using 
trace here
+         HornetQUtilLogger.LOGGER.trace("Reading string with utfSize=" + size);
+      }
+
+      int count = 0;
+      int byte1, byte2, byte3;
+      int charCount = 0;
+
+      input.readBytes(buffer.byteBuffer, 0, size);
+
+      while (count < size)
+      {
+         byte1 = buffer.byteBuffer[count++];
+
+         if (byte1 > 0 && byte1 <= 0x7F)
+         {
+            buffer.charBuffer[charCount++] = (char)byte1;
+         }
+         else
+         {
+            int c = byte1 & 0xff;
+            switch (c >> 4)
+            {
+               case 0xc:
+               case 0xd:
+                  byte2 = buffer.byteBuffer[count++];
+                  buffer.charBuffer[charCount++] = (char)((c & 0x1F) << 6 | 
byte2 & 0x3F);
+                  break;
+               case 0xe:
+                  byte2 = buffer.byteBuffer[count++];
+                  byte3 = buffer.byteBuffer[count++];
+                  buffer.charBuffer[charCount++] = (char)((c & 0x0F) << 12 | 
(byte2 & 0x3F) << 6 | (byte3 & 0x3F) << 0);
+                  break;
+               default:
+                  throw new InternalError("unhandled utf8 byte " + c);
+            }
+         }
+      }
+
+      return new String(buffer.charBuffer, 0, charCount);
+
+   }
+
+   public static StringUtilBuffer getThreadLocalBuffer()
+   {
+      SoftReference<StringUtilBuffer> softReference = 
UTF8Util.currenBuffer.get();
+      StringUtilBuffer value;
+      if (softReference == null)
+      {
+         value = new StringUtilBuffer();
+         softReference = new SoftReference<StringUtilBuffer>(value);
+         UTF8Util.currenBuffer.set(softReference);
+      }
+      else
+      {
+         value = softReference.get();
+      }
+
+      if (value == null)
+      {
+         value = new StringUtilBuffer();
+         softReference = new SoftReference<StringUtilBuffer>(value);
+         UTF8Util.currenBuffer.set(softReference);
+      }
+
+      return value;
+   }
+
+   public static void clearBuffer()
+   {
+      SoftReference<StringUtilBuffer> ref = UTF8Util.currenBuffer.get();
+      if (ref.get() != null)
+      {
+         ref.clear();
+      }
+   }
+
+   public static int calculateUTFSize(final String str, final StringUtilBuffer 
stringBuffer)
+   {
+      int calculatedLen = 0;
+
+      int stringLength = str.length();
+
+      if (stringLength > stringBuffer.charBuffer.length)
+      {
+         stringBuffer.resizeCharBuffer(stringLength);
+      }
+
+      str.getChars(0, stringLength, stringBuffer.charBuffer, 0);
+
+      for (int i = 0; i < stringLength; i++)
+      {
+         char c = stringBuffer.charBuffer[i];
+
+         if (c >= 1 && c < 0x7f)
+         {
+            calculatedLen++;
+         }
+         else if (c >= 0x800)
+         {
+            calculatedLen += 3;
+         }
+         else
+         {
+            calculatedLen += 2;
+         }
+      }
+      return calculatedLen;
+   }
+
+   public static class StringUtilBuffer
+   {
+
+      public char[] charBuffer;
+
+      public byte[] byteBuffer;
+
+      public void resizeCharBuffer(final int newSize)
+      {
+         if (newSize > charBuffer.length)
+         {
+            charBuffer = new char[newSize];
+         }
+      }
+
+      public void resizeByteBuffer(final int newSize)
+      {
+         if (newSize > byteBuffer.length)
+         {
+            byteBuffer = new byte[newSize];
+         }
+      }
+
+      public StringUtilBuffer()
+      {
+         this(1024, 1024);
+      }
+
+      public StringUtilBuffer(final int sizeChar, final int sizeByte)
+      {
+         charBuffer = new char[sizeChar];
+         byteBuffer = new byte[sizeByte];
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUID.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUID.java 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUID.java
new file mode 100644
index 0000000..35c2a0f
--- /dev/null
+++ b/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUID.java
@@ -0,0 +1,270 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, [email protected]
+ *
+ * Licensed under the License specified in the file licenses/LICENSE.txt which 
is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.activemq6.utils;
+
+
+/**
+ * UUID represents Universally Unique Identifiers (aka Global UID in Windows
+ * world). UUIDs are usually generated via UUIDGenerator (or in case of 'Null
+ * UUID', 16 zero bytes, via static method getNullUUID()), or received from
+ * external systems.
+ * <p>
+ * By default class caches the string presentations of UUIDs so that 
description
+ * is only created the first time it's needed. For memory stingy applications
+ * this caching can be turned off (note though that if uuid.toString() is never
+ * called, desc is never calculated so only loss is the space allocated for the
+ * desc pointer... which can of course be commented out to save memory).
+ * <p>
+ * Similarly, hash code is calculated when it's needed for the first time, and
+ * from thereon that value is just returned. This means that using UUIDs as 
keys
+ * should be reasonably efficient.
+ * <p>
+ * UUIDs can be compared for equality, serialized, cloned and even sorted.
+ * Equality is a simple bit-wise comparison. Ordering (for sorting) is done by
+ * first ordering based on type (in the order of numeric values of types),
+ * secondarily by time stamp (only for time-based time stamps), and finally by
+ * straight numeric byte-by-byte comparison (from most to least significant
+ * bytes).
+ */
+
+public final class UUID
+{
+   private static final String kHexChars = "0123456789abcdefABCDEF";
+
+   public static final byte INDEX_CLOCK_HI = 6;
+
+   public static final byte INDEX_CLOCK_MID = 4;
+
+   public static final byte INDEX_CLOCK_LO = 0;
+
+   public static final byte INDEX_TYPE = 6;
+
+   // Clock seq. & variant are multiplexed...
+   public static final byte INDEX_CLOCK_SEQUENCE = 8;
+
+   public static final byte INDEX_VARIATION = 8;
+
+   public static final byte TYPE_NULL = 0;
+
+   public static final byte TYPE_TIME_BASED = 1;
+
+   public static final byte TYPE_DCE = 2; // Not used
+
+   public static final byte TYPE_NAME_BASED = 3;
+
+   public static final byte TYPE_RANDOM_BASED = 4;
+
+   /*
+    * 'Standard' namespaces defined (suggested) by UUID specs:
+    */
+   public static final String NAMESPACE_DNS = 
"6ba7b810-9dad-11d1-80b4-00c04fd430c8";
+
+   public static final String NAMESPACE_URL = 
"6ba7b811-9dad-11d1-80b4-00c04fd430c8";
+
+   public static final String NAMESPACE_OID = 
"6ba7b812-9dad-11d1-80b4-00c04fd430c8";
+
+   public static final String NAMESPACE_X500 = 
"6ba7b814-9dad-11d1-80b4-00c04fd430c8";
+
+   /*
+    * By default let's cache desc, can be turned off. For hash code there's no
+    * point in turning it off (since the int is already part of the instance
+    * memory allocation); if you want to save those 4 bytes (or possibly bit
+    * more if alignment is bad) just comment out hash caching.
+    */
+   private static boolean sDescCaching = true;
+
+   private final byte[] mId;
+
+   // Both string presentation and hash value may be cached...
+   private transient String mDesc = null;
+
+   private transient int mHashCode = 0;
+
+   /**
+    * @param type UUID type
+    * @param data 16 byte UUID contents
+    */
+   public UUID(final int type, final byte[] data)
+   {
+      mId = data;
+      // Type is multiplexed with time_hi:
+      mId[UUID.INDEX_TYPE] &= (byte) 0x0F;
+      mId[UUID.INDEX_TYPE] |= (byte) (type << 4);
+      // Variant masks first two bits of the clock_seq_hi:
+      mId[UUID.INDEX_VARIATION] &= (byte) 0x3F;
+      mId[UUID.INDEX_VARIATION] |= (byte) 0x80;
+   }
+
+   public byte[] asBytes()
+   {
+      return mId;
+   }
+
+   /**
+    * Could use just the default hash code, but we can probably create a better
+    * identity hash (ie. same contents generate same hash) manually, without
+    * sacrificing speed too much. Although multiplications with modulos would
+    * generate better hashing, let's use just shifts, and do 2 bytes at a time.
+    * <p/>
+    * Of course, assuming UUIDs are randomized enough, even simpler approach
+    * might be good enough?
+    * <p/>
+    * Is this a good hash? ... one of these days I better read more about basic
+    * hashing techniques I swear!
+    */
+   private static final int[] kShifts = {3, 7, 17, 21, 29, 4, 9};
+
+   @Override
+   public int hashCode()
+   {
+      if (mHashCode == 0)
+      {
+         // Let's handle first and last byte separately:
+         int result = mId[0] & 0xFF;
+
+         result |= result << 16;
+         result |= result << 8;
+
+         for (int i = 1; i < 15; i += 2)
+         {
+            int curr = (mId[i] & 0xFF) << 8 | mId[i + 1] & 0xFF;
+            int shift = UUID.kShifts[i >> 1];
+
+            if (shift > 16)
+            {
+               result ^= curr << shift | curr >>> 32 - shift;
+            }
+            else
+            {
+               result ^= curr << shift;
+            }
+         }
+
+         // and then the last byte:
+         int last = mId[15] & 0xFF;
+         result ^= last << 3;
+         result ^= last << 13;
+
+         result ^= last << 27;
+         // Let's not accept hash 0 as it indicates 'not hashed yet':
+         if (result == 0)
+         {
+            mHashCode = -1;
+         }
+         else
+         {
+            mHashCode = result;
+         }
+      }
+      return mHashCode;
+   }
+
+   @Override
+   public String toString()
+   {
+      /*
+       * Could be synchronized, but there isn't much harm in just taking our
+       * chances (ie. in the worst case we'll form the string more than once...
+       * but result is the same)
+       */
+
+      if (mDesc == null)
+      {
+         StringBuffer b = new StringBuffer(36);
+
+         for (int i = 0; i < 16; ++i)
+         {
+            // Need to bypass hyphens:
+            switch (i)
+            {
+               case 4:
+               case 6:
+               case 8:
+               case 10:
+                  b.append('-');
+                  break;
+               default:
+                  // no-op
+            }
+            int hex = mId[i] & 0xFF;
+            b.append(UUID.kHexChars.charAt(hex >> 4));
+            b.append(UUID.kHexChars.charAt(hex & 0x0f));
+         }
+         if (!UUID.sDescCaching)
+         {
+            return b.toString();
+         }
+         mDesc = b.toString();
+      }
+      return mDesc;
+   }
+
+   /**
+    * Creates a 128bit number from the String representation of {@link UUID}.
+    *
+    * @param uuid
+    * @return byte array that can be used to recreate a UUID instance from the 
given String
+    * representation
+    */
+   public static byte[] stringToBytes(String uuid)
+   {
+      byte[] data = new byte[16];
+      int dataIdx = 0;
+      try
+      {
+         for (int i = 0; i < uuid.length(); )
+         {
+            while (uuid.charAt(i) == '-')
+            {
+               i++;
+            }
+            char c1 = uuid.charAt(i);
+            char c2 = uuid.charAt(i + 1);
+            i += 2;
+            int c1Bytes = Character.digit(c1, 16);
+            int c2Bytes = Character.digit(c2, 16);
+            data[dataIdx++] = (byte) ((c1Bytes << 4) + c2Bytes);
+         }
+      }
+      catch (RuntimeException e)
+      {
+         throw new IllegalArgumentException(e);
+      }
+      return data;
+   }
+
+   /**
+    * Checking equality of UUIDs is easy; just compare the 128-bit number.
+    */
+   @Override
+   public boolean equals(final Object o)
+   {
+      if (!(o instanceof UUID))
+      {
+         return false;
+      }
+      byte[] otherId = ((UUID) o).mId;
+      byte[] thisId = mId;
+      for (int i = 0; i < 16; ++i)
+      {
+         if (otherId[i] != thisId[i])
+         {
+            return false;
+         }
+      }
+      return true;
+   }
+}

http://git-wip-us.apache.org/repos/asf/activemq-6/blob/23e8edd9/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUIDGenerator.java
----------------------------------------------------------------------
diff --git 
a/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUIDGenerator.java 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUIDGenerator.java
new file mode 100644
index 0000000..0cabf23
--- /dev/null
+++ 
b/activemq6-commons/src/main/java/org/apache/activemq6/utils/UUIDGenerator.java
@@ -0,0 +1,371 @@
+/* JUG Java Uuid Generator
+ *
+ * Copyright (c) 2002- Tatu Saloranta, [email protected]
+ *
+ * Licensed under the License specified in the file licenses/LICENSE.txt which 
is
+ * included with the source code.
+ * You may not use this file except in compliance with the License.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.activemq6.utils;
+
+import java.lang.reflect.Method;
+import java.net.NetworkInterface;
+import java.net.SocketException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.activemq6.api.core.SimpleString;
+
+public final class UUIDGenerator
+{
+   private static final UUIDGenerator sSingleton = new UUIDGenerator();
+
+   // Windows has some fake adapters that will return the same HARDWARE 
ADDRESS on any computer. We need to ignore those
+   private static final byte[][] BLACK_LIST = new byte[][]{{2, 0, 84, 85, 78, 
1}};
+
+   /**
+    * Random-generator, used by various UUID-generation methods:
+    */
+   private Random mRnd = null;
+
+   private final Object mTimerLock = new Object();
+
+   private UUIDTimer mTimer = null;
+
+   private byte[] address;
+
+   /**
+    * Constructor is private to enforce singleton access.
+    */
+   private UUIDGenerator()
+   {
+   }
+
+   /**
+    * Method used for accessing the singleton generator instance.
+    */
+   public static UUIDGenerator getInstance()
+   {
+      return UUIDGenerator.sSingleton;
+   }
+
+   /*
+    * ///////////////////////////////////////////////////// // Configuration
+    * /////////////////////////////////////////////////////
+    */
+
+   /**
+    * Method for getting the shared random number generator used for generating
+    * the UUIDs. This way the initialization cost is only taken once; access
+    * need not be synchronized (or in cases where it has to, SecureRandom takes
+    * care of it); it might even be good for getting really 'random' stuff to
+    * get shared access...
+    */
+   public Random getRandomNumberGenerator()
+   {
+      /*
+       * Could be synchronized, but since side effects are trivial (ie.
+       * possibility of generating more than one SecureRandom, of which all but
+       * one are dumped) let's not add synchronization overhead:
+       */
+      if (mRnd == null)
+      {
+         mRnd = new SecureRandom();
+      }
+      return mRnd;
+   }
+
+   public UUID generateTimeBasedUUID(final byte[] byteAddr)
+   {
+      byte[] contents = new byte[16];
+      int pos = 10;
+      for (int i = 0; i < 6; ++i)
+      {
+         contents[pos + i] = byteAddr[i];
+      }
+
+      synchronized (mTimerLock)
+      {
+         if (mTimer == null)
+         {
+            mTimer = new UUIDTimer(getRandomNumberGenerator());
+         }
+
+         mTimer.getTimestamp(contents);
+      }
+
+      return new UUID(UUID.TYPE_TIME_BASED, contents);
+   }
+
+   public byte[] generateDummyAddress()
+   {
+      Random rnd = getRandomNumberGenerator();
+      byte[] dummy = new byte[6];
+      rnd.nextBytes(dummy);
+      /* Need to set the broadcast bit to indicate it's not a real
+       * address.
+       */
+      dummy[0] |= (byte) 0x01;
+
+      if (HornetQUtilLogger.LOGGER.isDebugEnabled())
+      {
+         HornetQUtilLogger.LOGGER.debug("using dummy address " + 
UUIDGenerator.asString(dummy));
+      }
+      return dummy;
+   }
+
+   /**
+    * If running java 6 or above, returns {@link 
NetworkInterface#getHardwareAddress()}, else return {@code null}.
+    * The first hardware address is returned when iterating all the 
NetworkInterfaces
+    */
+   public static byte[] getHardwareAddress()
+   {
+      Method getHardwareAddressMethod;
+      Method isUpMethod;
+      Method isLoopbackMethod;
+      Method isVirtualMethod;
+      try
+      {
+         getHardwareAddressMethod = 
NetworkInterface.class.getMethod("getHardwareAddress");
+         isUpMethod = NetworkInterface.class.getMethod("isUp");
+         isLoopbackMethod = NetworkInterface.class.getMethod("isLoopback");
+         isVirtualMethod = NetworkInterface.class.getMethod("isVirtual");
+         // check if we have enough security permissions to create and 
shutdown an executor
+         ExecutorService executor = Executors.newFixedThreadPool(0);
+         executor.shutdownNow();
+      }
+      catch (Throwable t)
+      {
+         // not on Java 6 or not enough security permission
+         return null;
+      }
+
+      try
+      {
+         List<NetworkInterface> ifaces = getAllNetworkInterfaces();
+
+         if (ifaces.size() == 0)
+         {
+            return null;
+         }
+
+         byte[] address = findFirstMatchingHardwareAddress(ifaces,
+                                                           
getHardwareAddressMethod,
+                                                           isUpMethod,
+                                                           isLoopbackMethod,
+                                                           isVirtualMethod);
+         if (address != null)
+         {
+            if (HornetQUtilLogger.LOGGER.isDebugEnabled())
+            {
+               HornetQUtilLogger.LOGGER.debug("using hardware address " + 
UUIDGenerator.asString(address));
+            }
+            return address;
+         }
+         return null;
+      }
+      catch (Exception e)
+      {
+         return null;
+      }
+   }
+
+   public SimpleString generateSimpleStringUUID()
+   {
+      return new SimpleString(generateStringUUID());
+   }
+
+   public UUID generateUUID()
+   {
+      byte[] address = getAddressBytes();
+
+      UUID uid = generateTimeBasedUUID(address);
+
+      return uid;
+   }
+
+   public String generateStringUUID()
+   {
+      byte[] address = getAddressBytes();
+
+      if (address == null)
+      {
+         return java.util.UUID.randomUUID().toString();
+      }
+      else
+      {
+         return generateTimeBasedUUID(address).toString();
+      }
+   }
+
+   public static byte[] getZeroPaddedSixBytes(final byte[] bytes)
+   {
+      if (bytes == null)
+      {
+         return null;
+      }
+      if (bytes.length > 0 && bytes.length <= 6)
+      {
+         if (bytes.length == 6)
+         {
+            return bytes;
+         }
+         else
+         {
+            // pad with zeroes to have a 6-byte array
+            byte[] paddedAddress = new byte[6];
+            System.arraycopy(bytes, 0, paddedAddress, 0, bytes.length);
+            for (int i = bytes.length; i < 6; i++)
+            {
+               paddedAddress[i] = 0;
+            }
+            return paddedAddress;
+         }
+      }
+      return null;
+   }
+
+   // Private -------------------------------------------------------
+
+   private static boolean isBlackList(final byte[] address)
+   {
+      for (byte[] blackList : UUIDGenerator.BLACK_LIST)
+      {
+         if (Arrays.equals(address, blackList))
+         {
+            return true;
+         }
+      }
+      return false;
+   }
+
+   private byte[] getAddressBytes()
+   {
+      if (address == null)
+      {
+         address = UUIDGenerator.getHardwareAddress();
+         if (address == null)
+         {
+            address = generateDummyAddress();
+         }
+      }
+
+      return address;
+   }
+
+   private static String asString(final byte[] bytes)
+   {
+      if (bytes == null)
+      {
+         return null;
+      }
+
+      StringBuilder s = new StringBuilder();
+      for (int i = 0; i < bytes.length - 1; i++)
+      {
+         s.append(Integer.toHexString(bytes[i]));
+         s.append(":");
+      }
+      s.append(bytes[bytes.length - 1]);
+      return s.toString();
+   }
+
+   private static List<NetworkInterface> getAllNetworkInterfaces()
+   {
+      Enumeration<NetworkInterface> networkInterfaces;
+      try
+      {
+         networkInterfaces = NetworkInterface.getNetworkInterfaces();
+
+         List<NetworkInterface> ifaces = new ArrayList<NetworkInterface>();
+         while (networkInterfaces.hasMoreElements())
+         {
+            ifaces.add(networkInterfaces.nextElement());
+         }
+         return ifaces;
+      }
+      catch (SocketException e)
+      {
+         return Collections.emptyList();
+      }
+   }
+
+   private static byte[] 
findFirstMatchingHardwareAddress(List<NetworkInterface> ifaces,
+                                                          final Method 
getHardwareAddressMethod,
+                                                          final Method 
isUpMethod,
+                                                          final Method 
isLoopbackMethod,
+                                                          final Method 
isVirtualMethod)
+   {
+      ExecutorService executor = Executors.newFixedThreadPool(ifaces.size());
+      Collection<Callable<byte[]>> tasks = new 
ArrayList<Callable<byte[]>>(ifaces.size());
+
+      for (final NetworkInterface networkInterface : ifaces)
+      {
+         tasks.add(new Callable<byte[]>()
+         {
+            public byte[] call() throws Exception
+            {
+               boolean up = (Boolean) isUpMethod.invoke(networkInterface);
+               boolean loopback = (Boolean) 
isLoopbackMethod.invoke(networkInterface);
+               boolean virtual = (Boolean) 
isVirtualMethod.invoke(networkInterface);
+
+               if (loopback || virtual || !up)
+               {
+                  throw new Exception("not suitable interface");
+               }
+
+               Object res = getHardwareAddressMethod.invoke(networkInterface);
+               if (res != null && res instanceof byte[])
+               {
+
+                  byte[] address = (byte[]) res;
+                  byte[] paddedAddress = 
UUIDGenerator.getZeroPaddedSixBytes(address);
+
+                  if (UUIDGenerator.isBlackList(address))
+                  {
+                     throw new Exception("black listed address");
+                  }
+
+                  if (paddedAddress != null)
+                  {
+                     return paddedAddress;
+                  }
+               }
+
+               throw new Exception("invalid network interface");
+            }
+         });
+      }
+      try
+      {
+         // we wait 5 seconds to get the first matching hardware address. 
After that, we give up and return null
+         byte[] address = executor.invokeAny(tasks, 5, TimeUnit.SECONDS);
+         return address;
+      }
+      catch (Exception e)
+      {
+         return null;
+      }
+      finally
+      {
+         executor.shutdownNow();
+      }
+   }
+}

Reply via email to