[maven-release-plugin] copy for tag 6.1.0
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/JECheck.java b/bdbstore/src/main/java/org/apache/qpid/server/JECheck.java
new file mode 100644
index 0000000..bec905b
--- /dev/null
+++ b/bdbstore/src/main/java/org/apache/qpid/server/JECheck.java
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ */
+
+package org.apache.qpid.server;
+
+public class JECheck
+{
+    public static boolean isAvailable()
+    {
+        try
+        {
+            Class.forName("com.sleepycat.je.Environment");
+            return true;
+        }
+        catch (ClassNotFoundException | NoClassDefFoundError e)
+        {
+            return false;
+        }
+    }
+}
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
index 957fee6..c490908 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAReplicaVirtualHostImpl.java
@@ -50,7 +50,6 @@
 import org.apache.qpid.server.model.port.AmqpPort;
 import org.apache.qpid.server.model.preferences.UserPreferences;
 import org.apache.qpid.server.protocol.LinkRegistry;
-import org.apache.qpid.server.stats.StatisticsCounter;
 import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.transport.AMQPConnection;
@@ -66,7 +65,6 @@
 @ManagedObject( category = false, type = "BDB_HA_REPLICA", register = false )
 public class BDBHAReplicaVirtualHostImpl extends AbstractConfiguredObject<BDBHAReplicaVirtualHostImpl> implements BDBHAReplicaVirtualHost<BDBHAReplicaVirtualHostImpl>
 {
-    private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
     private final Broker<?> _broker;
     private final VirtualHostPrincipal _principal;
 
@@ -108,16 +106,12 @@
     @ManagedAttributeField
     private List<NodeAutoCreationPolicy> _nodeAutoCreationPolicies;
 
-    @ManagedObjectFactoryConstructor
+    @ManagedObjectFactoryConstructor(conditionallyAvailable = true, condition = "org.apache.qpid.server.JECheck#isAvailable()")
     public BDBHAReplicaVirtualHostImpl(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode)
     {
         super(parentsMap(virtualHostNode), attributes);
 
         _broker = virtualHostNode.getParent(Broker.class);
-        _messagesDelivered = new StatisticsCounter("messages-delivered-" + getName());
-        _dataDelivered = new StatisticsCounter("bytes-delivered-" + getName());
-        _messagesReceived = new StatisticsCounter("messages-received-" + getName());
-        _dataReceived = new StatisticsCounter("bytes-received-" + getName());
         _principal = new VirtualHostPrincipal(this);
         setState(State.UNAVAILABLE);
     }
@@ -409,47 +403,6 @@
     }
 
     @Override
-    public void registerMessageReceived(final long messageSize, final long timestamp)
-    {
-        throwUnsupportedForReplica();
-    }
-
-    @Override
-    public void registerMessageDelivered(final long messageSize)
-    {
-        throwUnsupportedForReplica();
-    }
-
-    @Override
-    public StatisticsCounter getMessageDeliveryStatistics()
-    {
-        return _messagesDelivered;
-    }
-
-    @Override
-    public StatisticsCounter getMessageReceiptStatistics()
-    {
-        return _messagesReceived;
-    }
-
-    @Override
-    public StatisticsCounter getDataDeliveryStatistics()
-    {
-        return _dataDelivered;
-    }
-
-    @Override
-    public StatisticsCounter getDataReceiptStatistics()
-    {
-        return _dataReceived;
-    }
-
-    @Override
-    public void resetStatistics()
-    {
-    }
-
-    @Override
     public boolean authoriseCreateConnection(final AMQPConnection<?> connection)
     {
         return false;
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java
index 378b3d8..d181660 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHost.java
@@ -22,6 +22,7 @@
 
 import org.apache.qpid.server.model.DerivedAttribute;
 import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedOperation;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.store.SizeMonitoringSettings;
 import org.apache.qpid.server.virtualhost.NonStandardVirtualHost;
@@ -54,4 +55,7 @@
 
     @ManagedAttribute(mandatory = true, defaultValue = "0")
     Long getStoreOverfullSize();
+
+    @ManagedOperation(description = "Resets statistics on this object and all child objects", changesConfiguredObjectState = false, nonModifying = true)
+    void resetStatistics();
 }
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHostImpl.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHostImpl.java
index 21cee14..9c4f6f1 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHostImpl.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBHAVirtualHostImpl.java
@@ -54,7 +54,7 @@
     @ManagedAttributeField
     private Long _storeOverfullSize;
 
-    @ManagedObjectFactoryConstructor
+    @ManagedObjectFactoryConstructor(conditionallyAvailable = true, condition = "org.apache.qpid.server.JECheck#isAvailable()")
     public BDBHAVirtualHostImpl(final Map<String, Object> attributes, VirtualHostNode<?> virtualHostNode)
     {
         super(attributes, virtualHostNode);
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHost.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHost.java
index 6b3881e..2b44455 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHost.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHost.java
@@ -22,6 +22,7 @@
 
 import org.apache.qpid.server.model.ManagedAttribute;
 import org.apache.qpid.server.model.ManagedContextDefault;
+import org.apache.qpid.server.model.ManagedOperation;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.store.SizeMonitoringSettings;
 import org.apache.qpid.server.store.berkeleydb.BDBEnvironmentContainer;
@@ -46,4 +47,7 @@
 
     @ManagedAttribute(mandatory = true, defaultValue = "0")
     Long getStoreOverfullSize();
+
+    @ManagedOperation(description = "Resets statistics on this object and all child objects", changesConfiguredObjectState = false, nonModifying = true)
+    void resetStatistics();
 }
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImpl.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImpl.java
index a0692fc..83a336d 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImpl.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhost/berkeleydb/BDBVirtualHostImpl.java
@@ -47,7 +47,7 @@
     @ManagedAttributeField
     private Long _storeOverfullSize;
 
-    @ManagedObjectFactoryConstructor
+    @ManagedObjectFactoryConstructor(conditionallyAvailable = true, condition = "org.apache.qpid.server.JECheck#isAvailable()")
     public BDBVirtualHostImpl(final Map<String, Object> attributes,
                               final VirtualHostNode<?> virtualHostNode)
     {
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
index 35bcbdf..b9f5edc 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBHAVirtualHostNodeImpl.java
@@ -154,7 +154,7 @@
 
     private boolean _isClosed;
 
-    @ManagedObjectFactoryConstructor
+    @ManagedObjectFactoryConstructor(conditionallyAvailable = true, condition = "org.apache.qpid.server.JECheck#isAvailable()")
     public BDBHAVirtualHostNodeImpl(Map<String, Object> attributes, Broker<?> broker)
     {
         super(broker, attributes);
@@ -393,7 +393,7 @@
         final SettableFuture<Void> returnVal = SettableFuture.create();
 
         ListenableFuture<Void> superFuture = super.doStop();
-        Futures.addCallback(superFuture, new FutureCallback<Void>()
+        addFutureCallback(superFuture, new FutureCallback<Void>()
         {
             @Override
             public void onSuccess(final Void result)
@@ -424,7 +424,7 @@
                 }
 
             }
-        });
+        }, getTaskExecutor());
         return returnVal;
     }
 
@@ -1330,7 +1330,7 @@
             }
         });
 
-        Futures.addCallback(future, new FutureCallback<Void>()
+        addFutureCallback(future, new FutureCallback<Void>()
         {
             @Override
             public void onSuccess(final Void result)
@@ -1342,7 +1342,7 @@
             {
                 LOGGER.error("Failed to close children when handling intruder", t);
             }
-        });
+        }, getTaskExecutor());
     }
 
     private abstract class VirtualHostNodeGroupTask implements Task<Void, RuntimeException>
diff --git a/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java b/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java
index f51737e..bc3700d 100644
--- a/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java
+++ b/bdbstore/src/main/java/org/apache/qpid/server/virtualhostnode/berkeleydb/BDBVirtualHostNodeImpl.java
@@ -46,7 +46,7 @@
     @ManagedAttributeField
     private String _storePath;
 
-    @ManagedObjectFactoryConstructor
+    @ManagedObjectFactoryConstructor(conditionallyAvailable = true, condition = "org.apache.qpid.server.JECheck#isAvailable()")
     public BDBVirtualHostNodeImpl(Map<String, Object> attributes, Broker<?> parent)
     {
         super(attributes, parent);
diff --git a/broker-codegen/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryGenerator.java b/broker-codegen/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryGenerator.java
index e174e0c..fab6517 100644
--- a/broker-codegen/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryGenerator.java
+++ b/broker-codegen/src/main/java/org/apache/qpid/server/model/ConfiguredObjectFactoryGenerator.java
@@ -24,10 +24,8 @@
 import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.StringWriter;
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashSet;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -211,12 +209,13 @@
 
             for(Element element : typeElement.getEnclosedElements())
             {
-                if(element instanceof ExecutableElement && element.getKind() == ElementKind.METHOD && processedMethods.add(element.getSimpleName().toString()))
+                if(element instanceof ExecutableElement && element.getKind() == ElementKind.METHOD && !processedMethods.contains(element.getSimpleName().toString()))
                 {
                     for(AnnotationMirror annotationMirror : element.getAnnotationMirrors())
                     {
                         if(annotationMirror.getAnnotationType().toString().equals("org.apache.qpid.server.model.ManagedOperation"))
                         {
+                            processedMethods.add(element.getSimpleName().toString());
                             processManagedOperation(pw, className, (ExecutableElement) element, annotationMirror);
                             break;
                         }
@@ -478,10 +477,11 @@
     private String generateObjectFactory(final Filer filer, final ExecutableElement constructorElement)
     {
         TypeElement classElement = (TypeElement) constructorElement.getEnclosingElement();
-        String factoryName = classElement.getQualifiedName().toString() + "Factory";
+        String objectQualifiedClassName = classElement.getQualifiedName().toString();
+        String factoryName = objectQualifiedClassName + "Factory";
         String factorySimpleName = classElement.getSimpleName().toString() + "Factory";
         String objectSimpleName = classElement.getSimpleName().toString();
-        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Generating factory file for " + classElement.getQualifiedName().toString());
+        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, "Generating factory file for " + objectQualifiedClassName);
         final ManagedObjectFactoryConstructor annotation =
                 constructorElement.getAnnotation(ManagedObjectFactoryConstructor.class);
         PackageElement packageElement = (PackageElement) classElement.getEnclosingElement();
@@ -545,13 +545,32 @@
             pw.println("    }");
             if(annotation.conditionallyAvailable())
             {
+                final String condition = annotation.condition();
                 pw.println();
                 pw.println("    @Override");
                 pw.println("    public boolean isAvailable()");
                 pw.println("    {");
-                pw.println("        return " + objectSimpleName + ".isAvailable();");
-                pw.println("    }");
+                if ("".equals(condition))
+                {
+                    pw.println("        return " + objectSimpleName + ".isAvailable();");
+                }
+                else
+                {
+                    if (condition.matches("([\\w][\\w\\d_]+\\.)+[\\w][\\w\\d_\\$]*#[\\w\\d_]+\\s*\\(\\s*\\)"))
+                    {
+                        pw.println("        return " + condition.replace('#', '.') + ";");
 
+                    }
+                    else
+                    {
+                        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
+                                                                 String.format(
+                                                                         "Invalid condition expression for '%s' : %s",
+                                                                         objectQualifiedClassName,
+                                                                         condition));
+                    }
+                }
+                pw.println("    }");
             }
 
             pw.println("}");
diff --git a/broker-codegen/src/main/java/org/apache/qpid/server/model/ManagedObjectFactoryConstructor.java b/broker-codegen/src/main/java/org/apache/qpid/server/model/ManagedObjectFactoryConstructor.java
index f14aed9..042a521 100644
--- a/broker-codegen/src/main/java/org/apache/qpid/server/model/ManagedObjectFactoryConstructor.java
+++ b/broker-codegen/src/main/java/org/apache/qpid/server/model/ManagedObjectFactoryConstructor.java
@@ -30,4 +30,6 @@
 public @interface ManagedObjectFactoryConstructor
 {
     boolean conditionallyAvailable() default false;
+
+    String condition() default "";
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java b/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
index 879ea17..10fbd50 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/exchange/AbstractExchange.java
@@ -736,7 +736,7 @@
 
                 final SettableFuture<Boolean> returnVal = SettableFuture.create();
 
-                Futures.addCallback(b.createAsync(), new FutureCallback<Void>()
+                addFutureCallback(b.createAsync(), new FutureCallback<Void>()
                 {
                     @Override
                     public void onSuccess(final Void result)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
index 2b16dd8..0acb810 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
@@ -629,7 +629,7 @@
             {
                 try
                 {
-                    Futures.addCallback(task.execute(), new FutureCallback<T>()
+                    addFutureCallback(task.execute(), new FutureCallback<T>()
                     {
                         @Override
                         public void onSuccess(final T result)
@@ -642,7 +642,7 @@
                         {
                             returnVal.setException(t);
                         }
-                    });
+                    }, getTaskExecutor());
                 }
                 catch(Throwable t)
                 {
@@ -700,7 +700,7 @@
             public void performAction(final ConfiguredObject<?> child)
             {
                 ListenableFuture<Void> childCloseFuture = child.closeAsync();
-                Futures.addCallback(childCloseFuture, new FutureCallback<Void>()
+                addFutureCallback(childCloseFuture, new FutureCallback<Void>()
                 {
                     @Override
                     public void onSuccess(final Void result)
@@ -713,7 +713,7 @@
                         LOGGER.error("Exception occurred while closing {} : {}",
                                      child.getClass().getSimpleName(), child.getName(), t);
                     }
-                });
+                }, getTaskExecutor());
                 childCloseFutures.add(childCloseFuture);
             }
         });
@@ -1025,14 +1025,14 @@
         ListenableFuture<List<Void>> combinedChildStateFuture = Futures.allAsList(childStateFutures);
 
         final SettableFuture<Void> returnVal = SettableFuture.create();
-        Futures.addCallback(combinedChildStateFuture, new FutureCallback<List<Void>>()
+        addFutureCallback(combinedChildStateFuture, new FutureCallback<List<Void>>()
         {
             @Override
             public void onSuccess(final List<Void> result)
             {
                 try
                 {
-                    Futures.addCallback(attainState(),
+                    addFutureCallback(attainState(),
                                         new FutureCallback<Void>()
                                         {
                                             @Override
@@ -1061,16 +1061,16 @@
                                                     }
                                                 }
                                             }
-                                        },  getTaskExecutor());
+                                        }, getTaskExecutor());
                 }
-                catch(RuntimeException e)
+                catch (RuntimeException e)
                 {
                     try
                     {
                         exceptionHandler.handleException(e, AbstractConfiguredObject.this);
                         returnVal.set(null);
                     }
-                    catch(Throwable t)
+                    catch (Throwable t)
                     {
                         returnVal.setException(t);
                     }
@@ -1083,7 +1083,7 @@
                 // One or more children failed to attain state but the error could not be handled by the handler
                 returnVal.setException(t);
             }
-        });
+        }, getTaskExecutor());
 
         return returnVal;
     }
@@ -1480,7 +1480,7 @@
                 {
                     final SettableFuture<Void> stateTransitionResult = SettableFuture.create();
                     ListenableFuture<Void> stateTransitionFuture = (ListenableFuture<Void>) stateChangingMethod.invoke(this);
-                    Futures.addCallback(stateTransitionFuture, new FutureCallback<Void>()
+                    addFutureCallback(stateTransitionFuture, new FutureCallback<Void>()
                     {
                         @Override
                         public void onSuccess(Void result)
@@ -1511,7 +1511,7 @@
                             _attainStateFuture.set(AbstractConfiguredObject.this);
                             stateTransitionResult.setException(t);
                         }
-                    });
+                    }, getTaskExecutor());
                     returnVal = stateTransitionResult;
                 }
                 catch (IllegalAccessException e)
@@ -2372,7 +2372,7 @@
     protected static <V> ChainedListenableFuture<Void>  doAfter(Executor executor, ListenableFuture<V> first, final Runnable second)
     {
         final ChainedSettableFuture<Void> returnVal = new ChainedSettableFuture<Void>(executor);
-        Futures.addCallback(first, new FutureCallback<V>()
+        addFutureCallback(first, new FutureCallback<V>()
         {
             @Override
             public void onSuccess(final V result)
@@ -2464,7 +2464,7 @@
     protected static <V> ChainedListenableFuture<V> doAfter(final Executor executor, ListenableFuture<V> first, final Callable<ListenableFuture<V>> second)
     {
         final ChainedSettableFuture<V> returnVal = new ChainedSettableFuture<V>(executor);
-        Futures.addCallback(first, new FutureCallback<V>()
+        addFutureCallback(first, new FutureCallback<V>()
         {
             @Override
             public void onSuccess(final V result)
@@ -2472,7 +2472,7 @@
                 try
                 {
                     final ListenableFuture<V> future = second.call();
-                    Futures.addCallback(future, new FutureCallback<V>()
+                    addFutureCallback(future, new FutureCallback<V>()
                     {
                         @Override
                         public void onSuccess(final V result)
@@ -2508,7 +2508,7 @@
     protected static <V,A> ChainedListenableFuture<V> doAfter(final Executor executor, ListenableFuture<A> first, final CallableWithArgument<ListenableFuture<V>,A> second)
     {
         final ChainedSettableFuture<V> returnVal = new ChainedSettableFuture<>(executor);
-        Futures.addCallback(first, new FutureCallback<A>()
+        addFutureCallback(first, new FutureCallback<A>()
         {
             @Override
             public void onSuccess(final A result)
@@ -2516,7 +2516,7 @@
                 try
                 {
                     final ListenableFuture<V> future = second.call(result);
-                    Futures.addCallback(future, new FutureCallback<V>()
+                    addFutureCallback(future, new FutureCallback<V>()
                     {
                         @Override
                         public void onSuccess(final V result)
@@ -2558,7 +2558,7 @@
                                                                      final Runnable after)
     {
         final ChainedSettableFuture<Void> returnVal = new ChainedSettableFuture<Void>(executor);
-        Futures.addCallback(future, new FutureCallback<V>()
+        addFutureCallback(future, new FutureCallback<V>()
         {
             @Override
             public void onSuccess(final V result)
@@ -2591,6 +2591,42 @@
         return returnVal;
     }
 
+    protected static <V> void addFutureCallback(ListenableFuture<V> future, final FutureCallback<V> callback,
+                                                Executor taskExecutor)
+    {
+        final Subject subject = Subject.getSubject(AccessController.getContext());
+
+        Futures.addCallback(future, new FutureCallback<V>()
+        {
+            @Override
+            public void onSuccess(final V result)
+            {
+                Subject.doAs(subject, new PrivilegedAction<Void>()
+                {
+                    @Override
+                    public Void run()
+                    {
+                        callback.onSuccess(result);
+                        return null;
+                    }
+                });
+            }
+
+            @Override
+            public void onFailure(final Throwable t)
+            {
+                Subject.doAs(subject, new PrivilegedAction<Void>()
+                {
+                    @Override
+                    public Void run()
+                    {
+                        callback.onFailure(t);
+                        return null;
+                    }
+                });
+            }
+        }, taskExecutor);
+    }
 
     @Override
     public ListenableFuture<Void> setAttributesAsync(final Map<String, Object> attributes) throws IllegalStateException, AccessControlException, IllegalArgumentException
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java
index d7247ca..4ac1961 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObjectTypeFactory.java
@@ -74,7 +74,7 @@
         final SettableFuture<X> returnVal = SettableFuture.create();
         final X instance = createInstance(attributes, parents);
         final ListenableFuture<Void> createFuture = instance.createAsync();
-        Futures.addCallback(createFuture, new FutureCallback<Void>()
+        AbstractConfiguredObject.addFutureCallback(createFuture, new FutureCallback<Void>()
         {
             @Override
             public void onSuccess(final Void result)
@@ -87,7 +87,7 @@
             {
                 returnVal.setException(t);
             }
-        },MoreExecutors.directExecutor());
+        }, MoreExecutors.directExecutor());
 
         return returnVal;
     }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
index 8411476..0bdd5a5 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AbstractSystemConfig.java
@@ -234,7 +234,7 @@
 
             container.setEventLogger(startupLogger);
             final SettableFuture<Void> returnVal = SettableFuture.create();
-            Futures.addCallback(container.openAsync(), new FutureCallback()
+            addFutureCallback(container.openAsync(), new FutureCallback()
                                 {
                                     @Override
                                     public void onSuccess(final Object result)
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java b/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
index 27000f3..5f604c4 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/AttributeValueConverter.java
@@ -55,6 +55,7 @@
 
 import org.apache.qpid.server.model.preferences.GenericPrincipal;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
+import org.apache.qpid.util.Strings;
 
 abstract class AttributeValueConverter<T>
 {
@@ -151,20 +152,8 @@
             {
                 String interpolated = AbstractConfiguredObject.interpolate(object,
                                                                           (String) value);
-                try
-                {
-                    interpolated = interpolated.replaceAll("\\s","");
-                    if(!interpolated.matches("[A-Za-z0-9+/]*[=]*"))
-                    {
-                        throw new IllegalArgumentException("Cannot convert string '"+ interpolated+ "'to a byte[] - it does not appear to be base64 data");
-                    }
+                return Strings.decodeBase64(interpolated);
 
-                    return DatatypeConverter.parseBase64Binary(interpolated);
-                }
-                catch(ArrayIndexOutOfBoundsException e)
-                {
-                    throw new IllegalArgumentException("Cannot convert string '"+ interpolated+ "'to a byte[] - it does not appear to be base64 data");
-                }
             }
             else
             {
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java b/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
index 9bb675b..8b2acff 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Broker.java
@@ -132,16 +132,18 @@
     @ManagedAttribute( defaultValue = "256" )
     int getConnection_sessionCountLimit();
 
-    @ManagedAttribute( defaultValue = "0")
+    @ManagedAttribute( defaultValue = "0", description = "The default frequency with which Broker and client will exchange heartbeat messages (in seconds). "
+                                                         + "Clients may negotiate a different heartbeat frequency or disable it altogether. "
+                                                         + "A value of 0 disables heart beating.")
     int getConnection_heartBeatDelay();
 
     @ManagedAttribute( defaultValue = "true" )
     boolean getConnection_closeWhenNoRoute();
 
-    @ManagedAttribute( defaultValue = "0" )
+    @ManagedAttribute( defaultValue = "0", description = "Period (in seconds) of the statistic report.")
     int getStatisticsReportingPeriod();
 
-    @ManagedAttribute( defaultValue = "false")
+    @ManagedAttribute( defaultValue = "false", description = "If enabled, statistics are automatically reset to zero after each statistics report is made.")
     boolean getStatisticsReportingResetEnabled();
 
 
@@ -275,11 +277,14 @@
             changesConfiguredObjectState = false)
     Set<Principal> getGroups();
 
-    @ManagedOperation(description = "Removes a user and all associated preferences from the brokers configuration",
+    @ManagedOperation(description = "Removes a user and all associated preferences from the broker's configuration",
             changesConfiguredObjectState = true)
     void purgeUser(@Param(name="origin", description="The AuthenticationProvider the username is associated with")AuthenticationProvider<?> origin,
                    @Param(name="username", description="The unqualified username that should be purged from the broker")String username);
 
+    @ManagedOperation(description = "Resets statistics on this object and all child objects", changesConfiguredObjectState = false, nonModifying = true)
+    void resetStatistics();
+
     //children
     Collection<VirtualHostNode<?>> getVirtualHostNodes();
 
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java
index 452e260..a86f713 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/BrokerImpl.java
@@ -87,7 +87,7 @@
 import org.apache.qpid.util.SystemUtils;
 
 @ManagedObject( category = false, type = "Broker" )
-public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker<BrokerImpl>, StatisticsGatherer
+public class BrokerImpl extends AbstractContainer<BrokerImpl> implements Broker<BrokerImpl>
 {
     private static final Logger LOGGER = LoggerFactory.getLogger(BrokerImpl.class);
 
@@ -836,6 +836,7 @@
         return _dataDelivered;
     }
 
+    @Override
     public void resetStatistics()
     {
         _messagesDelivered.reset();
@@ -846,9 +847,9 @@
         for (VirtualHostNode<?> virtualHostNode : getChildren(VirtualHostNode.class))
         {
             VirtualHost<?> virtualHost = virtualHostNode.getVirtualHost();
-            if (virtualHost != null)
+            if (virtualHost instanceof StatisticsGatherer)
             {
-                virtualHost.resetStatistics();
+                ((StatisticsGatherer)virtualHost).resetStatistics();
             }
         }
     }
@@ -896,13 +897,14 @@
                 for (VirtualHostNode<?> virtualHostNode : getChildren(VirtualHostNode.class))
                 {
                     VirtualHost<?> virtualHost = virtualHostNode.getVirtualHost();
-                    if (virtualHost != null)
+                    if (virtualHost instanceof StatisticsGatherer)
                     {
+                        StatisticsGatherer statGatherer = (StatisticsGatherer) virtualHost;
                         String name = virtualHost.getName();
-                        StatisticsCounter dataDelivered = virtualHost.getDataDeliveryStatistics();
-                        StatisticsCounter messagesDelivered = virtualHost.getMessageDeliveryStatistics();
-                        StatisticsCounter dataReceived = virtualHost.getDataReceiptStatistics();
-                        StatisticsCounter messagesReceived = virtualHost.getMessageReceiptStatistics();
+                        StatisticsCounter dataDelivered = statGatherer.getDataDeliveryStatistics();
+                        StatisticsCounter messagesDelivered = statGatherer.getMessageDeliveryStatistics();
+                        StatisticsCounter dataReceived = statGatherer.getDataReceiptStatistics();
+                        StatisticsCounter messagesReceived = statGatherer.getMessageReceiptStatistics();
                         EventLogger logger = virtualHost.getEventLogger();
                         logger.message(VirtualHostMessages.STATS_DATA(name,
                                                                       DELIVERED,
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ExternalFileBasedAuthenticationManager.java b/broker-core/src/main/java/org/apache/qpid/server/model/ExternalFileBasedAuthenticationManager.java
index 45294a8..f7008c6 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ExternalFileBasedAuthenticationManager.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ExternalFileBasedAuthenticationManager.java
@@ -24,7 +24,7 @@
 {
     String PATH = "path";
 
-    @ManagedAttribute( mandatory = true, description = "File location")
+    @ManagedAttribute( mandatory = true, description = "File location", immutable = true)
     public String getPath();
 
 
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/ManageableMessage.java b/broker-core/src/main/java/org/apache/qpid/server/model/ManageableMessage.java
index 5b4349b..be7ac8a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/ManageableMessage.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/ManageableMessage.java
@@ -51,4 +51,6 @@
     Map<String,Object> getHeaders();
 
     Object getContent();
+
+    String getContentTransferEncoding();
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java b/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
index e1651e9..bed636e 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
@@ -321,14 +321,13 @@
     @ManagedOperation(description = "removes all messages from this queue", changesConfiguredObjectState = false)
     long clearQueue();
 
-    @ManagedOperation(nonModifying = true, secure = true, changesConfiguredObjectState = false)
+    @ManagedOperation(nonModifying = true, secure = true, changesConfiguredObjectState = false,
+                      description = "Gets the message content")
     Content getMessageContent(@Param(name = "messageId") long messageId,
                               @Param(name = "limit", defaultValue = "-1",
                                       description = "Number of bytes to return") long limit,
                               @Param(name = "returnJson", defaultValue = "false",
-                                      description = "If true, converts message content into json format"
-                                                    + " if message mime-type is either amqp/map or amqp/list"
-                                                    + " or jms/map-message. Default is false.") boolean returnJson,
+                                      description = "If true, converts message content into JSON format.") boolean returnJson,
                               @Param(name = "decompressBeforeLimiting", defaultValue = "false",
                                       description = "If true, the operation will attempt to decompress the message"
                                                     + "(should it be compressed) before applying any limit. If"
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java b/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
index 720f96a..ddf4209 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/VirtualHost.java
@@ -33,7 +33,6 @@
 import org.apache.qpid.server.logging.EventLoggerProvider;
 import org.apache.qpid.server.message.MessageDestination;
 import org.apache.qpid.server.queue.QueueEntry;
-import org.apache.qpid.server.stats.StatisticsGatherer;
 import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.store.preferences.UserPreferencesCreator;
@@ -42,7 +41,7 @@
 import org.apache.qpid.server.virtualhost.NodeAutoCreationPolicy;
 
 @ManagedObject( defaultType = "ProvidedStore", description = VirtualHost.CLASS_DESCRIPTION)
-public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject<X>, StatisticsGatherer,
+public interface VirtualHost<X extends VirtualHost<X>> extends ConfiguredObject<X>,
                                                                EventLoggerProvider, NamedAddressSpace,
                                                                UserPreferencesCreator
 {
@@ -202,7 +201,6 @@
 
     Broker<?> getBroker();
 
-    // LQ TODO: I think this is not being processed correctly because it is not annotated on the base. At least is does not show up in the generated overrides
     @Override
     @ManagedOperation(nonModifying = true, changesConfiguredObjectState = false)
     Collection<? extends Connection<?>> getConnections();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProvider.java b/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProvider.java
index cb9727f..e8c1886 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProvider.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProvider.java
@@ -30,6 +30,6 @@
 {
     String PATH="path";
 
-    @ManagedAttribute( mandatory = true, description = "File location" )
+    @ManagedAttribute( mandatory = true, description = "File location", immutable = true)
     String getPath();
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java b/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
index 664b796..0867a94 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/adapter/FileBasedGroupProviderImpl.java
@@ -103,16 +103,6 @@
     }
 
     @Override
-    protected void validateChange(final ConfiguredObject<?> proxyForValidation, final Set<String> changedAttributes)
-    {
-        super.validateChange(proxyForValidation, changedAttributes);
-        if(changedAttributes.contains(PATH))
-        {
-            throw new IllegalArgumentException("Cannot change the path");
-        }
-    }
-
-    @Override
     protected void onOpen()
     {
         super.onOpen();
diff --git a/broker-core/src/main/java/org/apache/qpid/server/model/preferences/GenericPrincipal.java b/broker-core/src/main/java/org/apache/qpid/server/model/preferences/GenericPrincipal.java
index 99660a3..161f3ae 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/model/preferences/GenericPrincipal.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/model/preferences/GenericPrincipal.java
@@ -33,7 +33,7 @@
 
 public class GenericPrincipal implements Principal
 {
-    private static final Pattern PATTERN = Pattern.compile("([a-zA-Z_0-9.%~-]+)@(\\w*)\\('([a-zA-Z_0-9.%~-]*)'\\)");
+    private static final Pattern PATTERN = Pattern.compile("([a-zA-Z_0-9.%~-]+)@([^('@]*)\\('([a-zA-Z_0-9.%~-]*)'\\)");
     public static final String UTF8 = StandardCharsets.UTF_8.name();
 
     private final String _name;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java b/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
index 49e2fab..9321a6a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
@@ -2020,7 +2020,7 @@
 
             ListenableFuture<List<Void>> combinedFuture = Futures.allAsList(removeBindingFutures);
 
-            Futures.addCallback(combinedFuture, new FutureCallback<List<Void>>()
+            addFutureCallback(combinedFuture, new FutureCallback<List<Void>>()
             {
                 @Override
                 public void onSuccess(final List<Void> result)
@@ -2335,7 +2335,7 @@
                 }
 
             }
-            atTail = (node == null) || (getEntries().next(node) == null);
+            atTail = (node == null) || (getNextAvailableEntry(sub) == null);
         }
         return atTail || !subActive;
     }
@@ -3711,10 +3711,7 @@
                                          final long limit,
                                          final boolean decompressBeforeLimiting)
     {
-        String mimeType = messageReference.getMessage().getMessageHeader().getMimeType();
-        if (returnJson && ("amqp/list".equalsIgnoreCase(mimeType)
-                           || "amqp/map".equalsIgnoreCase(mimeType)
-                           || "jms/map-message".equalsIgnoreCase(mimeType)))
+        if (returnJson)
         {
             ServerMessage message = messageReference.getMessage();
             if (message instanceof InternalMessage)
@@ -3731,9 +3728,17 @@
                                                   (InternalMessage) messageConverter.convert(message, getVirtualHost()),
                                                   limit);
                 }
+                else
+                {
+                    throw new IllegalArgumentException(String.format("Unable to convert message %d on queue '%s' to JSON",
+                                                                     message.getMessageNumber(), getName()));
+                }
             }
         }
-        return new MessageContent(messageReference, limit, decompressBeforeLimiting);
+        else
+        {
+            return new MessageContent(messageReference, limit, decompressBeforeLimiting);
+        }
     }
 
     @Override
@@ -3774,6 +3779,7 @@
                 if (_messageNumber == message.getMessageNumber())
                 {
                     _messageInfo = new MessageInfoImpl(entry, _includeHeaders);
+                    return true;
                 }
             }
             return false;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/queue/MessageContentJsonConverter.java b/broker-core/src/main/java/org/apache/qpid/server/queue/MessageContentJsonConverter.java
index cd17d13..cb5aa92 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/queue/MessageContentJsonConverter.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/queue/MessageContentJsonConverter.java
@@ -30,7 +30,14 @@
 import java.util.Map;
 import java.util.UUID;
 
+import com.fasterxml.jackson.core.JsonGenerator;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import com.fasterxml.jackson.databind.ser.std.StdArraySerializers;
+import com.fasterxml.jackson.databind.ser.std.StdSerializer;
+import com.google.common.primitives.Bytes;
+import com.google.common.primitives.Ints;
 
 class MessageContentJsonConverter
 {
@@ -46,6 +53,9 @@
     {
         _messageBody = messageBody;
         _objectMapper = new ObjectMapper();
+        SimpleModule module = new SimpleModule();
+        module.addSerializer(new NoneBase64ByteArraySerializer());
+        _objectMapper.registerModule(module);
         _remaining = limit;
     }
 
@@ -180,4 +190,20 @@
         return copyCollection(copy);
     }
 
+    private static class NoneBase64ByteArraySerializer extends StdSerializer<byte[]>
+    {
+        final StdArraySerializers.IntArraySerializer _underlying = new StdArraySerializers.IntArraySerializer();
+
+        public NoneBase64ByteArraySerializer()
+        {
+            super(byte[].class);
+        }
+
+        @Override
+        public void serialize(final byte[] value, final JsonGenerator jgen, final SerializerProvider provider)
+                throws IOException
+        {
+            _underlying.serialize(Ints.toArray(Bytes.asList(value)), jgen, provider);
+        }
+    }
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
index 6dcb54c..9d748c8 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/AutoGeneratedSelfSignedKeyStoreImpl.java
@@ -75,6 +75,7 @@
 import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.StateTransition;
 import org.apache.qpid.transport.network.security.ssl.SSLUtil;
+import org.apache.qpid.util.Strings;
 
 public class AutoGeneratedSelfSignedKeyStoreImpl
         extends AbstractConfiguredObject<AutoGeneratedSelfSignedKeyStoreImpl>
@@ -196,8 +197,8 @@
 
     private void loadPrivateKeyAndCertificate()
     {
-        byte[] privateKeyEncoded = DatatypeConverter.parseBase64Binary((String) getActualAttributes().get(ENCODED_PRIVATE_KEY));
-        byte[] certificateEncoded = DatatypeConverter.parseBase64Binary((String) getActualAttributes().get(
+        byte[] privateKeyEncoded = Strings.decodeBase64((String) getActualAttributes().get(ENCODED_PRIVATE_KEY));
+        byte[] certificateEncoded = Strings.decodeBase64((String) getActualAttributes().get(
                 ENCODED_CERTIFICATE));
 
 
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java b/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java
index 1e1058f..55e7884 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/SiteSpecificTrustStoreImpl.java
@@ -31,7 +31,6 @@
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -46,14 +45,13 @@
 
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-
-import org.apache.qpid.server.configuration.updater.Task;
-import org.apache.qpid.server.logging.EventLogger;
-import org.apache.qpid.server.logging.messages.TrustStoreMessages;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.qpid.server.configuration.IllegalConfigurationException;
+import org.apache.qpid.server.configuration.updater.Task;
+import org.apache.qpid.server.logging.EventLogger;
+import org.apache.qpid.server.logging.messages.TrustStoreMessages;
 import org.apache.qpid.server.model.AbstractConfiguredObject;
 import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.model.Broker;
@@ -69,6 +67,7 @@
 import org.apache.qpid.server.security.auth.manager.SimpleLDAPAuthenticationManager;
 import org.apache.qpid.transport.network.security.ssl.SSLUtil;
 import org.apache.qpid.transport.util.Functions;
+import org.apache.qpid.util.Strings;
 
 @ManagedObject( category = false )
 public class SiteSpecificTrustStoreImpl
@@ -281,7 +280,7 @@
 
     private void decodeCertificate()
     {
-        byte[] certificateEncoded = DatatypeConverter.parseBase64Binary((String) getActualAttributes().get(CERTIFICATE));
+        byte[] certificateEncoded = Strings.decodeBase64((String) getActualAttributes().get(CERTIFICATE));
 
 
         try(ByteArrayInputStream input = new ByteArrayInputStream(certificateEncoded))
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/HashedUser.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/HashedUser.java
index ee267eb..6907b6c 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/HashedUser.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/database/HashedUser.java
@@ -25,11 +25,11 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 
-
 import javax.xml.bind.DatatypeConverter;
 
 import org.apache.qpid.server.model.AuthenticationProvider;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
+import org.apache.qpid.util.Strings;
 
 
 public class HashedUser implements PasswordPrincipal
@@ -61,7 +61,7 @@
         }
 
         _encodedPassword = encoded_password;
-        byte[] decoded = DatatypeConverter.parseBase64Binary(data[1]);
+        byte[] decoded = Strings.decodeBase64(data[1]);
         _password = new char[decoded.length];
 
         int index = 0;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
index a1145f8..a065f68 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractAuthenticationManager.java
@@ -141,7 +141,7 @@
     private ListenableFuture<Void> performDelete()
     {
         final SettableFuture<Void> futureResult = SettableFuture.create();
-        Futures.addCallback(closeAsync(), new FutureCallback<Void>()
+        addFutureCallback(closeAsync(), new FutureCallback<Void>()
         {
             @Override
             public void onSuccess(final Void result)
@@ -176,7 +176,7 @@
                 setState(State.DELETED);
                 _eventLogger.message(AuthenticationProviderMessages.DELETE(getName()));
             }
-        });
+        }, getTaskExecutor());
 
         return futureResult;
     }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
index 93f946d..da30318 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/AbstractScramAuthenticationManager.java
@@ -50,6 +50,7 @@
 import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer;
 import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServer;
 import org.apache.qpid.server.security.auth.sasl.scram.ScramSaslServerSource;
+import org.apache.qpid.util.Strings;
 
 public abstract class AbstractScramAuthenticationManager<X extends AbstractScramAuthenticationManager<X>>
         extends ConfigModelPasswordManagingAuthenticationProvider<X>
@@ -159,7 +160,7 @@
         final String[] passwordFields = user.getPassword().split(",");
         if (passwordFields.length == 2)
         {
-            byte[] saltedPassword = DatatypeConverter.parseBase64Binary(passwordFields[PasswordField.SALTED_PASSWORD.ordinal()]);
+            byte[] saltedPassword = Strings.decodeBase64(passwordFields[PasswordField.SALTED_PASSWORD.ordinal()]);
 
             try
             {
@@ -320,9 +321,9 @@
         {
             updateStoredPasswordFormatIfNecessary(user);
             final String[] passwordFields = user.getPassword().split(",");
-            salt = DatatypeConverter.parseBase64Binary(passwordFields[PasswordField.SALT.ordinal()]);
-            storedKey = DatatypeConverter.parseBase64Binary(passwordFields[PasswordField.STORED_KEY.ordinal()]);
-            serverKey = DatatypeConverter.parseBase64Binary(passwordFields[PasswordField.SERVER_KEY.ordinal()]);
+            salt = Strings.decodeBase64(passwordFields[PasswordField.SALT.ordinal()]);
+            storedKey = Strings.decodeBase64(passwordFields[PasswordField.STORED_KEY.ordinal()]);
+            serverKey = Strings.decodeBase64(passwordFields[PasswordField.SERVER_KEY.ordinal()]);
             iterationCount = Integer.parseInt(passwordFields[PasswordField.ITERATION_COUNT.ordinal()]);
             exception = null;
         }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java
index edc7593..a2db70a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/manager/MD5AuthenticationProvider.java
@@ -52,6 +52,7 @@
 import org.apache.qpid.server.security.auth.sasl.plain.PlainAdapterSaslServer;
 import org.apache.qpid.server.security.auth.sasl.plain.PlainSaslServer;
 import org.apache.qpid.server.util.ServerScopedRuntimeException;
+import org.apache.qpid.util.Strings;
 
 @ManagedObject( category = false, type = "MD5" )
 public class MD5AuthenticationProvider
@@ -179,7 +180,7 @@
                         if(user != null)
                         {
                             String passwordData = user.getPassword();
-                            byte[] passwordBytes = DatatypeConverter.parseBase64Binary(passwordData);
+                            byte[] passwordBytes = Strings.decodeBase64(passwordData);
                             char[] password;
                             if(_hexify)
                             {
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java b/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
index 26767f7..bca9f02 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/auth/sasl/scram/ScramSaslServer.java
@@ -34,6 +34,8 @@
 import javax.security.sasl.SaslServer;
 import javax.xml.bind.DatatypeConverter;
 
+import org.apache.qpid.util.Strings;
+
 public class ScramSaslServer implements SaslServer
 {
     public final String _mechanism;
@@ -163,7 +165,7 @@
             {
                 throw new SaslException("Cannot parse client final message");
             }
-            if(!Arrays.equals(_gs2Header,DatatypeConverter.parseBase64Binary(parts[0].substring(2))))
+            if(!Arrays.equals(_gs2Header, Strings.decodeBase64(parts[0].substring(2))))
             {
                 throw new SaslException("Client final message channel bind data invalid");
             }
@@ -181,7 +183,7 @@
             }
 
             String clientFinalMessageWithoutProof = clientFinalMessage.substring(0,clientFinalMessage.length()-(1+parts[parts.length-1].length()));
-            byte[] proofBytes = DatatypeConverter.parseBase64Binary(parts[parts.length-1].substring(2));
+            byte[] proofBytes = Strings.decodeBase64(parts[parts.length-1].substring(2));
 
             String authMessage = _clientFirstMessageBare + "," + _serverFirstMessage + "," + clientFinalMessageWithoutProof;
 
diff --git a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
index e30d32a..a69436a 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/security/encryption/AESKeyFileEncrypter.java
@@ -36,6 +36,8 @@
 import javax.crypto.spec.IvParameterSpec;
 import javax.xml.bind.DatatypeConverter;
 
+import org.apache.qpid.util.Strings;
+
 class AESKeyFileEncrypter implements ConfigurationSecretEncrypter
 {
     private static final String CIPHER_NAME = "AES/CBC/PKCS5Padding";
@@ -87,7 +89,7 @@
         {
             throw new IllegalArgumentException("Encrypted value is not valid Base 64 data: '" + encrypted + "'");
         }
-        byte[] encryptedBytes = DatatypeConverter.parseBase64Binary(encrypted);
+        byte[] encryptedBytes = Strings.decodeBase64(encrypted);
         try
         {
             Cipher cipher = Cipher.getInstance(CIPHER_NAME);
diff --git a/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java b/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
index ecfd82a..3c4e806 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/store/JsonFileConfigStore.java
@@ -307,10 +307,10 @@
         save(data);
     }
 
-    private HashMap<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> createChildMap()
+    private Map<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> createChildMap()
     {
         Model model = _parent.getModel();
-        HashMap<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> map = new HashMap<>();
+        Map<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> map = new HashMap<>();
 
         for(ConfiguredObjectRecord record : _objectsById.values())
         {
@@ -356,7 +356,7 @@
                                       Map<UUID, Map<String, SortedSet<ConfiguredObjectRecord>>> childMap)
     {
         ConfiguredObjectRecord record = _objectsById.get(id);
-        Map<String,Object> map = new LinkedHashMap<String, Object>();
+        Map<String,Object> map = new LinkedHashMap<>();
 
         Collection<Class<? extends ConfiguredObject>> parentTypes = _parent.getModel().getParentTypes(type);
         if(parentTypes.size() > 1)
@@ -376,8 +376,7 @@
         map.put("id", id);
         map.putAll(record.getAttributes());
 
-        List<Class<? extends ConfiguredObject>> childClasses =
-                new ArrayList<Class<? extends ConfiguredObject>>(_parent.getModel().getChildTypes(type));
+        List<Class<? extends ConfiguredObject>> childClasses = new ArrayList<>(_parent.getModel().getChildTypes(type));
 
         Collections.sort(childClasses, CATEGORY_CLASS_COMPARATOR);
 
@@ -389,7 +388,7 @@
                 String singularName = entry.getKey().toLowerCase();
                 String attrName = singularName + (singularName.endsWith("s") ? "es" : "s");
                 final SortedSet<ConfiguredObjectRecord> sortedChildren = entry.getValue();
-                List<Map<String,Object>> entities = new ArrayList<Map<String, Object>>();
+                List<Map<String,Object>> entities = new ArrayList<>();
 
                 for(ConfiguredObjectRecord childRecord : sortedChildren)
                 {
diff --git a/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java b/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
index 770991b..0eae7b6 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/util/urlstreamhandler/data/Handler.java
@@ -31,7 +31,7 @@
 import java.net.URLStreamHandler;
 import java.nio.charset.StandardCharsets;
 
-import javax.xml.bind.DatatypeConverter;
+import org.apache.qpid.util.Strings;
 
 public class Handler extends URLStreamHandler
 {
@@ -79,7 +79,7 @@
                 _base64 = parts[0].endsWith(";base64");
                 if(_base64)
                 {
-                    _content = DatatypeConverter.parseBase64Binary(parts[1]);
+                    _content = Strings.decodeBase64(parts[1]);
                 }
                 else
                 {
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
index bc072f2..7f26215 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/AbstractVirtualHost.java
@@ -38,6 +38,7 @@
 import java.security.Principal;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -62,7 +63,6 @@
 import java.util.regex.PatternSyntaxException;
 
 import javax.security.auth.Subject;
-import javax.xml.bind.DatatypeConverter;
 
 import com.google.common.base.Function;
 import com.google.common.util.concurrent.AsyncFunction;
@@ -111,6 +111,7 @@
 import org.apache.qpid.server.security.access.Operation;
 import org.apache.qpid.server.security.auth.AuthenticatedPrincipal;
 import org.apache.qpid.server.stats.StatisticsCounter;
+import org.apache.qpid.server.stats.StatisticsGatherer;
 import org.apache.qpid.server.store.ConfiguredObjectRecord;
 import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.store.Event;
@@ -142,9 +143,10 @@
 import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
 import org.apache.qpid.server.util.HousekeepingExecutor;
 import org.apache.qpid.server.util.MapValueConverter;
+import org.apache.qpid.util.Strings;
 
 public abstract class AbstractVirtualHost<X extends AbstractVirtualHost<X>> extends AbstractConfiguredObject<X>
-        implements VirtualHost<X>, EventListener
+        implements VirtualHost<X>, EventListener, StatisticsGatherer
 {
     private final Collection<ConnectionValidator> _connectionValidators = new ArrayList<>();
 
@@ -519,7 +521,7 @@
         }
         if (virtualHost.getConnectionThreadPoolSize() <= virtualHost.getNumberOfSelectors())
         {
-            throw new IllegalConfigurationException(String.format("Number of Selectors %d on VirtualHost %s must be greater than the connection pool size %d.", virtualHost.getNumberOfSelectors(), getName(), virtualHost.getConnectionThreadPoolSize()));
+            throw new IllegalConfigurationException(String.format("Number of Selectors %d on VirtualHost %s must be less than the connection pool size %d.", virtualHost.getNumberOfSelectors(), getName(), virtualHost.getConnectionThreadPoolSize()));
         }
     }
 
@@ -647,7 +649,7 @@
                 attributes.put(Exchange.ID, UUIDGenerator.generateExchangeUUID(name, getName()));
                 final ListenableFuture<Exchange<?>> future = addExchangeAsync(attributes);
                 final SettableFuture<Void> returnVal = SettableFuture.create();
-                Futures.addCallback(future, new FutureCallback<Exchange<?>>()
+                addFutureCallback(future, new FutureCallback<Exchange<?>>()
                 {
                     @Override
                     public void onSuccess(final Exchange<?> result)
@@ -717,25 +719,43 @@
         {
             if(messageContent instanceof Map || messageContent instanceof List)
             {
+                if(message.getMimeType() != null || message.getEncoding() != null)
+                {
+                    throw new IllegalArgumentException("If the message content is provided as map or list, the mime type and encoding must be left unset");
+                }
                 body = (Serializable)messageContent;
             }
             else if(messageContent instanceof String)
             {
-                if(message.getMimeType() != null || message.getEncoding() != null)
+                String contentTransferEncoding = message.getContentTransferEncoding();
+                if("base64".equalsIgnoreCase(contentTransferEncoding))
                 {
-                    try
+                    body = Strings.decodeBase64((String) messageContent);
+                }
+                else if(contentTransferEncoding == null || contentTransferEncoding.trim().equals("") || contentTransferEncoding.trim().equalsIgnoreCase("identity"))
+                {
+                    String mimeType = message.getMimeType();
+                    if(mimeType != null && !(mimeType = mimeType.trim().toLowerCase()).equals(""))
                     {
-                        body = DatatypeConverter.parseBase64Binary((String)messageContent);
-
+                        if (!(mimeType.startsWith("text/") || Arrays.asList("application/json", "application/xml")
+                                                                    .contains(mimeType)))
+                        {
+                            throw new IllegalArgumentException(message.getMimeType()
+                                                               + " is invalid as a MIME type for this message. "
+                                                               + "Only MIME types of the text type can be used if a string is supplied as the content");
+                        }
+                        else if (mimeType.matches(".*;\\s*charset\\s*=.*"))
+                        {
+                            throw new IllegalArgumentException(message.getMimeType()
+                                                               + " is invalid as a MIME type for this message. "
+                                                               + "If a string is supplied as the content, the MIME type must not include a charset parameter");
+                        }
                     }
-                    catch(IllegalArgumentException e)
-                    {
-                        body = (String) messageContent;
-                    }
+                    body = (String) messageContent;
                 }
                 else
                 {
-                    body = (String) messageContent;
+                    throw new IllegalArgumentException("contentTransferEncoding value '" + contentTransferEncoding + "' is invalid.  The only valid values are base64 and identity");
                 }
             }
             else
@@ -1373,7 +1393,7 @@
                    NoFactoryForTypeException
     {
         final SettableFuture<Exchange<?>> returnVal = SettableFuture.create();
-        Futures.addCallback(getObjectFactory().createAsync(Exchange.class, attributes, this),
+        addFutureCallback(getObjectFactory().createAsync(Exchange.class, attributes, this),
                             new FutureCallback<Exchange>()
                             {
                                 @Override
@@ -1395,7 +1415,7 @@
                                         returnVal.setException(t);
                                     }
                                 }
-                            });
+                            }, getTaskExecutor());
         return returnVal;
 
     }
@@ -1545,6 +1565,7 @@
         return _dataDelivered;
     }
 
+    @Override
     public void resetStatistics()
     {
         _messagesDelivered.reset();
@@ -2609,7 +2630,7 @@
                         final ListenableFuture<Void> childOpenFuture = child.openAsync();
                         childOpenFutures.add(childOpenFuture);
 
-                        Futures.addCallback(childOpenFuture, new FutureCallback<Void>()
+                        addFutureCallback(childOpenFuture, new FutureCallback<Void>()
                         {
                             @Override
                             public void onSuccess(final Void result)
@@ -2623,7 +2644,7 @@
                                               child.getClass().getSimpleName(), child.getName(), t);
                             }
 
-                        });
+                        }, getTaskExecutor());
                     }
                 });
                 return null;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java
index 80ddaba..4e6fa5f 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhost/ProvidedStoreVirtualHost.java
@@ -20,6 +20,7 @@
 package org.apache.qpid.server.virtualhost;
 
 import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedOperation;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.store.SizeMonitoringSettings;
 
@@ -34,4 +35,6 @@
     @ManagedAttribute(mandatory = true, defaultValue = "0")
     Long getStoreOverfullSize();
 
+    @ManagedOperation(description = "Resets statistics on this object and all child objects", changesConfiguredObjectState = false, nonModifying = true)
+    void resetStatistics();
 }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
index dab0cd8..7a063b1 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/AbstractVirtualHostNode.java
@@ -164,7 +164,7 @@
 
         try
         {
-            Futures.addCallback(activate(),
+            addFutureCallback(activate(),
                                 new FutureCallback<Void>()
                                 {
                                     @Override
@@ -295,12 +295,12 @@
         final SettableFuture<Void> futureResult = SettableFuture.create();
 
         // Delete the node only if deletion of the virtualhost succeeds.
-        Futures.addCallback(deleteVirtualHostIfExists(), new FutureCallback<Void>()
+        addFutureCallback(deleteVirtualHostIfExists(), new FutureCallback<Void>()
         {
             @Override
             public void onSuccess(final Void result)
             {
-                Futures.addCallback(closeAsync(), new FutureCallback<Void>()
+                addFutureCallback(closeAsync(), new FutureCallback<Void>()
                 {
                     @Override
                     public void onSuccess(final Void result)
@@ -339,7 +339,7 @@
                             configurationStore.onDelete(AbstractVirtualHostNode.this);
                         }
                     }
-                });
+                }, getTaskExecutor());
             }
 
             @Override
@@ -347,7 +347,7 @@
             {
                 futureResult.setException(t);
             }
-        });
+        }, getTaskExecutor());
 
         return futureResult;
     }
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java
index 289287f..da815e2 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostImpl.java
@@ -52,7 +52,6 @@
 import org.apache.qpid.server.model.port.AmqpPort;
 import org.apache.qpid.server.model.preferences.UserPreferences;
 import org.apache.qpid.server.protocol.LinkRegistry;
-import org.apache.qpid.server.stats.StatisticsCounter;
 import org.apache.qpid.server.store.DurableConfigurationStore;
 import org.apache.qpid.server.store.MessageStore;
 import org.apache.qpid.server.transport.AMQPConnection;
@@ -69,7 +68,6 @@
 {
     public static final String VIRTUAL_HOST_TYPE = "REDIRECTOR";
 
-    private final StatisticsCounter _messagesDelivered, _dataDelivered, _messagesReceived, _dataReceived;
     private final Broker<?> _broker;
     private final VirtualHostPrincipal _principal;
 
@@ -117,10 +115,6 @@
         super(parentsMap(virtualHostNode), attributes);
 
         _broker = virtualHostNode.getParent(Broker.class);
-        _messagesDelivered = new StatisticsCounter("messages-delivered-" + getName());
-        _dataDelivered = new StatisticsCounter("bytes-delivered-" + getName());
-        _messagesReceived = new StatisticsCounter("messages-received-" + getName());
-        _dataReceived = new StatisticsCounter("bytes-received-" + getName());
         _principal = new VirtualHostPrincipal(this);
         setState(State.UNAVAILABLE);
     }
@@ -442,47 +436,6 @@
     }
 
     @Override
-    public void registerMessageReceived(final long messageSize, final long timestamp)
-    {
-        throwUnsupportedForRedirector();
-    }
-
-    @Override
-    public void registerMessageDelivered(final long messageSize)
-    {
-        throwUnsupportedForRedirector();
-    }
-
-    @Override
-    public StatisticsCounter getMessageDeliveryStatistics()
-    {
-        return _messagesDelivered;
-    }
-
-    @Override
-    public StatisticsCounter getMessageReceiptStatistics()
-    {
-        return _messagesReceived;
-    }
-
-    @Override
-    public StatisticsCounter getDataDeliveryStatistics()
-    {
-        return _dataDelivered;
-    }
-
-    @Override
-    public StatisticsCounter getDataReceiptStatistics()
-    {
-        return _dataReceived;
-    }
-
-    @Override
-    public void resetStatistics()
-    {
-    }
-
-    @Override
     public boolean authoriseCreateConnection(final AMQPConnection<?> connection)
     {
         return false;
diff --git a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java
index 050794f..44b96d7 100644
--- a/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java
+++ b/broker-core/src/main/java/org/apache/qpid/server/virtualhostnode/RedirectingVirtualHostNodeImpl.java
@@ -90,7 +90,7 @@
 
         final ListenableFuture<VirtualHost> virtualHostFuture = getObjectFactory().createAsync(VirtualHost.class, attributes, this);
 
-        Futures.addCallback(virtualHostFuture, new FutureCallback<VirtualHost>()
+        addFutureCallback(virtualHostFuture, new FutureCallback<VirtualHost>()
         {
             @Override
             public void onSuccess(final VirtualHost virtualHost)
@@ -115,7 +115,7 @@
                     resultFuture.setException(t);
                 }
             }
-        });
+        }, getTaskExecutor());
 
         return resultFuture;
     }
diff --git a/broker-core/src/test/java/org/apache/qpid/server/model/preferences/GenericPrincipalTest.java b/broker-core/src/test/java/org/apache/qpid/server/model/preferences/GenericPrincipalTest.java
index c130992..7282a9b 100644
--- a/broker-core/src/test/java/org/apache/qpid/server/model/preferences/GenericPrincipalTest.java
+++ b/broker-core/src/test/java/org/apache/qpid/server/model/preferences/GenericPrincipalTest.java
@@ -61,6 +61,17 @@
         }
     }
 
+    public void testParseWithDash() throws Exception
+    {
+        String username = "user-name";
+        String originType = "origin-type";
+        String originName = "origin-name";
+        GenericPrincipal p = new GenericPrincipal(String.format("%s@%s('%s')", username, originType, originName));
+        assertEquals("unexpected principal name", username, p.getName());
+        assertEquals("unexpected origin type", originType, p.getOriginType());
+        assertEquals("unexpected origin name", originName, p.getOriginName());
+    }
+
     public void testRejectQuotes() throws Exception
     {
         final String usernameWithQuote = "_username'withQuote";
@@ -96,6 +107,41 @@
 
     }
 
+    public void testRejectParenthesis() throws Exception
+    {
+        final String usernameWithParenthesis = "username(withParenthesis";
+        final String originTypeWithParenthesis = "authType(withParenthesis";
+        final String originNameWithParenthesis = "authName(withParenthesis";
+        try
+        {
+            new GenericPrincipal(String.format("%s@%s('%s')", usernameWithParenthesis, _originType, _originName));
+            fail("GenericPricinpal should reject _username with parenthesis");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // pass
+        }
+        try
+        {
+            new GenericPrincipal(String.format("%s@%s('%s')", _username, originTypeWithParenthesis, _originName));
+            fail("GenericPricinpal should reject origin type with parenthesis");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // pass
+        }
+        try
+        {
+            new GenericPrincipal(String.format("%s@%s('%s')", _username, _originType, originNameWithParenthesis));
+            fail("GenericPricinpal should reject origin name with parenthesis");
+        }
+        catch (IllegalArgumentException e)
+        {
+            // pass
+        }
+
+    }
+
     public void testRejectAtSign() throws Exception
     {
         final String _usernameWithAtSign = "_username@withAtSign";
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java
index 982b12c..c295ac8 100644
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/CreditCreditManager.java
@@ -47,30 +47,22 @@
 
     public synchronized void addCredit(final long messageCredit, final long bytesCredit)
     {
-        boolean notifyIncrease = true;
         if(_messageCredit >= 0L && messageCredit > 0L)
         {
-            notifyIncrease = _messageCredit != 0L;
             _messageCredit += messageCredit;
         }
 
-
+        boolean notifyIncrease = false;
 
         if(_bytesCredit >= 0L && bytesCredit > 0L)
         {
-            notifyIncrease = notifyIncrease && bytesCredit>0;
+            notifyIncrease = _messageCredit != 0L && bytesCredit > 0L;
             _bytesCredit += bytesCredit;
-
-        }
-        else
-        {
-            notifyIncrease = false;
         }
 
         if(!setSuspended(!hasCredit()) && notifyIncrease)
         {
             notifyIncreaseBytesCredit();
-
         }
 
     }
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java
index 45b0bba..20ed169 100644
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_Internal_to_v0_10.java
@@ -61,7 +61,8 @@
         final byte[] messageContent = MessageConverter_v0_10.convertToBody(serverMsg.getMessageBody());
         final MessageMetaData_0_10 messageMetaData_0_10 = convertMetaData(serverMsg,
                                                                           MessageConverter_v0_10.getBodyMimeType(
-                                                                                  serverMsg.getMessageBody()),
+                                                                                  serverMsg.getMessageBody(),
+                                                                                  serverMsg.getMessageHeader()),
                                                                           messageContent.length);
 
         return new StoredMessage<MessageMetaData_0_10>()
diff --git a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java
index 3e84ff9..ea4c02f 100644
--- a/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java
+++ b/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/MessageConverter_v0_10.java
@@ -31,6 +31,7 @@
 
 import org.apache.qpid.bytebuffer.QpidByteBuffer;
 import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.message.internal.InternalMessageHeader;
 import org.apache.qpid.server.model.NamedAddressSpace;
 import org.apache.qpid.server.plugin.MessageConverter;
 import org.apache.qpid.server.plugin.PluggableService;
@@ -182,15 +183,31 @@
         }
     }
 
-    public static String getBodyMimeType(Object object)
+    public static String getBodyMimeType(Object object, final InternalMessageHeader header)
     {
         if(object instanceof String)
         {
-            return "text/plain";
+            String mimeType;
+            if(header == null || (mimeType = header.getMimeType()) == null || !mimeType.trim().startsWith("text/"))
+            {
+                return "text/plain";
+            }
+            else
+            {
+                return mimeType;
+            }
         }
         else if(object instanceof byte[])
         {
-            return "application/octet-stream";
+            String mimeType;
+            if(header == null || (mimeType = header.getMimeType()) == null || "".equals(mimeType.trim()))
+            {
+                return "application/octet-stream";
+            }
+            else
+            {
+                return mimeType;
+            }
         }
         else if(object instanceof Map)
         {
diff --git a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java
index 399f36f..3234ad1 100644
--- a/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java
+++ b/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/MessageConverter_Internal_to_v0_8.java
@@ -38,6 +38,7 @@
 import org.apache.qpid.framing.FieldTable;
 import org.apache.qpid.framing.MessagePublishInfo;
 import org.apache.qpid.server.message.internal.InternalMessage;
+import org.apache.qpid.server.message.internal.InternalMessageHeader;
 import org.apache.qpid.server.model.NamedAddressSpace;
 import org.apache.qpid.server.plugin.MessageConverter;
 import org.apache.qpid.server.plugin.PluggableService;
@@ -73,7 +74,7 @@
     {
         final byte[] messageContent = convertToBody(serverMsg.getMessageBody());
         final MessageMetaData messageMetaData_0_8 = convertMetaData(serverMsg,
-                                                                    getBodyMimeType(serverMsg.getMessageBody()),
+                                                                    getBodyMimeType(serverMsg.getMessageBody(), serverMsg.getMessageHeader()),
                                                                     messageContent.length);
 
         return new StoredMessage<MessageMetaData>()
@@ -207,15 +208,31 @@
         }
     }
 
-    public static String getBodyMimeType(Object object)
+    public static String getBodyMimeType(Object object, final InternalMessageHeader header)
     {
         if(object instanceof String)
         {
-            return "text/plain";
+            String mimeType;
+            if(header == null || (mimeType = header.getMimeType()) == null || !mimeType.trim().startsWith("text/"))
+            {
+                return "text/plain";
+            }
+            else
+            {
+                return mimeType;
+            }
         }
         else if(object instanceof byte[])
         {
-            return "application/octet-stream";
+            String mimeType;
+            if(header == null || (mimeType = header.getMimeType()) == null || "".equals(mimeType.trim()))
+            {
+                return "application/octet-stream";
+            }
+            else
+            {
+                return mimeType;
+            }
         }
         else if(object instanceof Map)
         {
diff --git a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
index 876f91a..ebe63d3 100644
--- a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
+++ b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/ConsumerTarget_1_0.java
@@ -85,7 +85,7 @@
     private static boolean isPullOnly(SendingLink_1_0 link)
     {
         Source source = (Source) link.getEndpoint().getSource();
-        return Arrays.asList(source.getCapabilities()).contains(Symbol.getSymbol("QPID:PULL-ONLY"));
+        return source.getCapabilities() != null && Arrays.asList(source.getCapabilities()).contains(Symbol.getSymbol("QPID:PULL-ONLY"));
     }
 
     private SendingLinkEndpoint getEndpoint()
diff --git a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java
index b4bba8b..01c98c7 100644
--- a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java
+++ b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_Internal_to_v1_0.java
@@ -32,6 +32,7 @@
 import org.apache.qpid.server.protocol.v1_0.messaging.SectionEncoder;
 import org.apache.qpid.server.protocol.v1_0.type.Binary;
 import org.apache.qpid.server.protocol.v1_0.type.Section;
+import org.apache.qpid.server.protocol.v1_0.type.Symbol;
 import org.apache.qpid.server.protocol.v1_0.type.UnsignedByte;
 import org.apache.qpid.server.protocol.v1_0.type.UnsignedInteger;
 import org.apache.qpid.server.protocol.v1_0.type.messaging.AmqpValue;
@@ -75,6 +76,10 @@
         properties.setCorrelationId(serverMessage.getMessageHeader().getCorrelationId());
         properties.setCreationTime(new Date(serverMessage.getMessageHeader().getTimestamp()));
         properties.setMessageId(serverMessage.getMessageHeader().getMessageId());
+        if(bodySection instanceof Data)
+        {
+            properties.setContentType(Symbol.valueOf(serverMessage.getMessageHeader().getMimeType()));
+        }
         final String userId = serverMessage.getMessageHeader().getUserId();
         if(userId != null)
         {
@@ -97,7 +102,7 @@
 
     }
 
-    protected Section getBodySection(final InternalMessage serverMessage, final String mimeType)
+    protected Section getBodySection(final InternalMessage serverMessage)
     {
         return convertToBody(serverMessage.getMessageBody());
     }
diff --git a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java
index 8478d66..d996712 100644
--- a/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java
+++ b/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/MessageConverter_to_1_0.java
@@ -259,7 +259,7 @@
         };
     }
 
-    private Section getBodySection(final M serverMessage)
+    protected Section getBodySection(final M serverMessage)
     {
         final String mimeType = serverMessage.getMessageHeader().getMimeType();
         byte[] data = new byte[(int) serverMessage.getSize()];
diff --git a/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhost/derby/DerbyVirtualHost.java b/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhost/derby/DerbyVirtualHost.java
index bac2c8f..037477c 100644
--- a/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhost/derby/DerbyVirtualHost.java
+++ b/broker-plugins/derby-store/src/main/java/org/apache/qpid/server/virtualhost/derby/DerbyVirtualHost.java
@@ -20,6 +20,7 @@
 package org.apache.qpid.server.virtualhost.derby;
 
 import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedOperation;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.store.SizeMonitoringSettings;
 
@@ -35,4 +36,7 @@
 
     @ManagedAttribute(mandatory = true, defaultValue = "0")
     Long getStoreOverfullSize();
+
+    @ManagedOperation(description = "Resets statistics on this object and all child objects", changesConfiguredObjectState = false, nonModifying = true)
+    void resetStatistics();
 }
diff --git a/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhost/jdbc/JDBCVirtualHost.java b/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhost/jdbc/JDBCVirtualHost.java
index 4e31869..a4ddb56 100644
--- a/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhost/jdbc/JDBCVirtualHost.java
+++ b/broker-plugins/jdbc-store/src/main/java/org/apache/qpid/server/virtualhost/jdbc/JDBCVirtualHost.java
@@ -20,6 +20,7 @@
 package org.apache.qpid.server.virtualhost.jdbc;
 
 import org.apache.qpid.server.model.ManagedAttribute;
+import org.apache.qpid.server.model.ManagedOperation;
 import org.apache.qpid.server.model.VirtualHost;
 import org.apache.qpid.server.store.jdbc.DefaultConnectionProviderFactory;
 import org.apache.qpid.server.store.jdbc.JDBCSettings;
@@ -39,4 +40,7 @@
 
     @ManagedAttribute(secure=true)
     String getPassword();
+
+    @ManagedOperation(description = "Resets statistics on this object and all child objects", changesConfiguredObjectState = false, nonModifying = true)
+    void resetStatistics();
 }
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java
index 42eaeb7..dacf7db 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/auth/BasicAuthPreemptiveAuthenticator.java
@@ -24,7 +24,6 @@
 
 import javax.security.auth.Subject;
 import javax.servlet.http.HttpServletRequest;
-import javax.xml.bind.DatatypeConverter;
 
 import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
 import org.apache.qpid.server.management.plugin.HttpRequestPreemptiveAuthenticator;
@@ -34,6 +33,7 @@
 import org.apache.qpid.server.security.auth.AuthenticationResult;
 import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
 import org.apache.qpid.server.security.auth.manager.UsernamePasswordAuthenticationProvider;
+import org.apache.qpid.util.Strings;
 
 @PluggableService
 public class BasicAuthPreemptiveAuthenticator implements HttpRequestPreemptiveAuthenticator
@@ -67,7 +67,7 @@
                 if (isBasicAuthSupported)
                 {
                     String base64UsernameAndPassword = tokens[1];
-                    String[] credentials = (new String(DatatypeConverter.parseBase64Binary(base64UsernameAndPassword),
+                    String[] credentials = (new String(Strings.decodeBase64(base64UsernameAndPassword),
                                                        StandardCharsets.UTF_8)).split(":", 2);
                     if (credentials.length == 2)
                     {
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
index 46f487c..829387d 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
@@ -43,7 +43,7 @@
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.Part;
 
-import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.google.common.base.Joiner;
 import com.google.common.base.Predicate;
@@ -1021,7 +1021,15 @@
             {
                 if ("data".equals(part.getName()) && "application/json".equals(part.getContentType()))
                 {
-                    providedObject = (T) mapper.readValue(part.getInputStream(), LinkedHashMap.class);
+                    try
+                    {
+                        providedObject = (T) mapper.readValue(part.getInputStream(), LinkedHashMap.class);
+                    }
+                    catch (JsonProcessingException e)
+                    {
+                        throw new IllegalArgumentException("Cannot parse the operation body as json",e);
+                    }
+
                 }
                 else
                 {
@@ -1039,7 +1047,7 @@
             {
                 providedObject = mapper.readValue(request.getInputStream(), expectedClass);
             }
-            catch (JsonParseException e)
+            catch (JsonProcessingException e)
             {
                 throw new IllegalArgumentException("Cannot parse the operation body as json",e);
             }
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
index e531ec9..524593a 100644
--- a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/SaslServlet.java
@@ -47,6 +47,7 @@
 import org.apache.qpid.server.security.auth.AuthenticationResult;
 import org.apache.qpid.server.security.auth.SubjectAuthenticationResult;
 import org.apache.qpid.server.util.ConnectionScopedRuntimeException;
+import org.apache.qpid.util.Strings;
 
 public class SaslServlet extends AbstractServlet
 {
@@ -208,7 +209,7 @@
     {
         byte[] saslResponseBytes = saslResponse == null
                 ? new byte[0]
-                : DatatypeConverter.parseBase64Binary(saslResponse);
+                : Strings.decodeBase64(saslResponse);
         SubjectAuthenticationResult authenticationResult = subjectCreator.authenticate(saslServer, saslResponseBytes);
         byte[] challenge = authenticationResult.getChallenge();
         Map<String, Object> outputObject = new LinkedHashMap<>();
diff --git a/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html b/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html
index b4edf01..5b88a3c 100644
--- a/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html
+++ b/broker-plugins/management-http/src/main/java/resources/authenticationprovider/simpleldap/add.html
@@ -94,7 +94,7 @@
         </div>
     </div>
 
-    <div class="formBox">
+    <div class="clear formBox">
         <fieldset>
             <legend>User Search</legend>
             <div class="clear">
@@ -139,7 +139,7 @@
         </fieldset>
     </div>
 
-    <div class="formBox">
+    <div class="clear formBox">
         <fieldset>
             <legend>Additional Group Information <span id="addAuthenticationProvider.simpleldap.groupSearchLegend" class="infoPane"></span></legend>
             <div data-dojo-type="dijit/Tooltip"
diff --git a/broker-plugins/management-http/src/main/java/resources/css/common.css b/broker-plugins/management-http/src/main/java/resources/css/common.css
index e9af5a7..63cd14c 100644
--- a/broker-plugins/management-http/src/main/java/resources/css/common.css
+++ b/broker-plugins/management-http/src/main/java/resources/css/common.css
@@ -380,7 +380,8 @@
 .infoPane
 {
     margin-left: 5px;
-    padding: 5px 5px 5px 1.2em;
+    margin-bottom: 5px;
+    padding: 5px 5px 0px 1.2em;
     font-style: italic;
     background:url("../images/notification.svg") no-repeat left center;
     background-size: 1em;
@@ -428,12 +429,13 @@
   width:100%;
 }
 
-.criteriaControl.dijitTextBoxReadOnly,
-.claro .criteriaControl.dijitTextBoxReadOnly,
-.claro .criteriaControl.dijitTextBoxReadOnlyFocused .dijitInputContainer
+.readOnly.dijitTextBoxReadOnly,
+.claro .readOnly.dijitTextBoxReadOnly,
+.claro .readOnly.dijitTextBoxReadOnlyFocused .dijitInputContainer
 {
   background-color: #efefef !important;
   background-image: none !important;
+  border-color: #d3d3d3;
 }
 
 .advancedSearchItem
@@ -654,9 +656,9 @@
     background-size: 1em;
 }
 
-#message-content-preview{
+#message-content-preview
+{
     width: 100%;
-    height: 10.2em;
 }
 
 #message-content-preview .dgrid,
@@ -664,3 +666,58 @@
 {
     height: 10em;
 }
+
+.hexDumpBox
+{
+    border: solid;
+    border-width: 1px;
+    white-space: nowrap;
+}
+
+.hexBox
+{
+    display: inline-block;
+    padding-right: 25px;
+}
+
+.asciiBox
+{
+    display: inline-block;
+}
+
+.hexDumpHeadRow
+{
+    display: table-row;
+    font-family: monospace;
+    font-weight: bold;
+}
+
+.hexDumpRow
+{
+    display: table-row;
+}
+
+.hexCountCell
+{
+    padding-right: 25px;
+    font-weight: bold;
+    display: table-cell;
+    font-family: monospace;
+}
+
+.hexDumpCell
+{
+    padding-right: 5px;
+    display: table-cell;
+    font-family: monospace;
+}
+
+.hexDumpCell:last-child
+{
+    padding-right: 0;
+}
+
+.hexDumpCellHighlight
+{
+    background-color: darkgray;
+}
diff --git a/broker-plugins/management-http/src/main/java/resources/dashboard/AddWidgetDialogContent.html b/broker-plugins/management-http/src/main/java/resources/dashboard/AddWidgetDialogContent.html
index 5554172..3e4d157 100644
--- a/broker-plugins/management-http/src/main/java/resources/dashboard/AddWidgetDialogContent.html
+++ b/broker-plugins/management-http/src/main/java/resources/dashboard/AddWidgetDialogContent.html
@@ -19,6 +19,7 @@
 <div style="width:50vw">
     <form data-dojo-attach-point="addWidgetForm" data-dojo-type="dijit/form/Form" id="${id}_addWidgetForm">
         <div>
+            <div class="infoPane">Please, double-click on a row to add the corresponding widget into dashboard</div>
             <div data-dojo-attach-point="queryBrowserNode"></div>
         </div>
         <div class="dijitDialogPaneActionBar">
diff --git a/broker-plugins/management-http/src/main/java/resources/editBroker.html b/broker-plugins/management-http/src/main/java/resources/editBroker.html
index a7ddbfd..16cdd55 100644
--- a/broker-plugins/management-http/src/main/java/resources/editBroker.html
+++ b/broker-plugins/management-http/src/main/java/resources/editBroker.html
@@ -37,20 +37,20 @@
                   </div>
               </div>
               <div class="clear">
-                  <div class="formLabel-labelCell tableContainer-labelCell">Statistics reporting period (ms):</div>
+                  <div class="formLabel-labelCell tableContainer-labelCell">Statistics reporting period (s):</div>
                   <div class="formLabel-controlCell tableContainer-valueCell">
                       <input type="text" id="editBroker.statisticsReportingPeriod"
                              data-dojo-type="dijit/form/ValidationTextBox"
                              data-dojo-props="
                               name: 'statisticsReportingPeriod',
                               trim: true,
-                              placeholder: 'Time in ms',
-                              label: 'Statistics reporting period (ms):',
+                              placeholder: 'Time in seconds',
+                              label: 'Statistics reporting period (s):',
                               promptMessage: 'Frequency with which statistics are reported to broker log.'" />
                   </div>
               </div>
               <div class="clear">
-                  <div class="formLabel-labelCell tableContainer-labelCell">Statistics reporting period enabled:</div>
+                  <div class="formLabel-labelCell tableContainer-labelCell">Statistics reporting auto-reset enabled:</div>
                   <div class="formLabel-controlCell tableContainer-valueCell">
                       <input type="text" id="editBroker.statisticsReportingResetEnabled"
                              data-dojo-type="dijit/form/CheckBox"
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/HexDumpWidget.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/HexDumpWidget.js
new file mode 100644
index 0000000..a68c842
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/HexDumpWidget.js
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ *
+ */
+define(["dojo/_base/declare",
+        "dojo/_base/lang",
+        "dojo/dom-construct",
+        "dijit/_WidgetBase",
+        "dojo/domReady!"],
+    function (declare, lang, domConstruct)
+    {
+
+        return declare("qpid.common.HexDumpWidget", [dijit._WidgetBase], {
+            /**
+             * constructor fields
+             */
+            data: null,
+            numberOfColumns: 8,
+
+            postCreate: function ()
+            {
+                this.inherited(arguments);
+                var rows = Math.floor(this.data.length / this.numberOfColumns) + (this.data.length % this.numberOfColumns == 0 ? 0 : 1);
+
+                var hexDumpBox = domConstruct.create("div", {class: "hexDumpBox"}, this.domNode);
+                var hexBox = domConstruct.create("span", {class: "hexBox"}, hexDumpBox);
+                var asciiBox = domConstruct.create("span", {class: "asciiBox"}, hexDumpBox);
+
+                this._createHeadings(hexBox, asciiBox);
+                this._createRows(rows, hexBox, asciiBox);
+            },
+
+            _createHeadings: function (hexBox, asciiBox)
+            {
+                var hexHeadRowDom = domConstruct.create("div", {class: "hexDumpHeadRow"}, hexBox);
+                var asciiHeadRowDom = domConstruct.create("div", {class: "hexDumpHeadRow"}, asciiBox);
+                domConstruct.create("span", {class: "hexCountCell"}, hexHeadRowDom);
+
+                for (var column = 0; column < this.numberOfColumns; column++)
+                {
+                    var hexHeadCellDom = domConstruct.create("span", {class: "hexDumpCell"}, hexHeadRowDom);
+                    hexHeadCellDom.innerHTML = this._toHex(column, 2);
+
+                    var asciiHeadCellDom = domConstruct.create("span", {class: "hexDumpCell"}, asciiHeadRowDom);
+                    asciiHeadCellDom.innerHTML = this._toHex(column, 1);
+                }
+            },
+
+            _createRows: function (rows, hexBox, asciiBox)
+            {
+                for (var row = 0; row < rows; row++)
+                {
+                    var hexRowDom = domConstruct.create("div", {class: "hexDumpRow"}, hexBox);
+                    var asciiRowDom = domConstruct.create("div", {class: "hexDumpRow"}, asciiBox);
+
+                    var hexCountCellDom = domConstruct.create("span", {class: "hexCountCell"}, hexRowDom);
+                    hexCountCellDom.innerHTML = this._toHex(row * this.numberOfColumns, 4);
+
+                    for (var column = 0; column < this.numberOfColumns; column++)
+                    {
+                        var dataIndex = (row * this.numberOfColumns) + column;
+                        if (dataIndex >= this.data.length)
+                        {
+                            break;
+                        }
+                        var item = this.data[dataIndex];
+                        var hexCellDom = domConstruct.create("span", {class: "hexDumpCell"}, hexRowDom);
+                        hexCellDom.innerHTML = this._toHex(item, 2);
+
+                        var asciiCellDom = domConstruct.create("span", {class: "hexDumpCell"}, asciiRowDom);
+                        asciiCellDom.innerHTML = this._toAsciiPrintable(item);
+
+                        asciiCellDom.cousin = hexCellDom;
+                        hexCellDom.cousin = asciiCellDom;
+
+                        var mouseOverListener = function (event)
+                        {
+                            // highlight the mouseover target
+                            event.target.classList.add("hexDumpCellHighlight");
+                            event.target.cousin.classList.add("hexDumpCellHighlight");
+                        };
+                        var mouseLeaveListener = function (event)
+                        {
+                            event.target.classList.remove("hexDumpCellHighlight");
+                            event.target.cousin.classList.remove("hexDumpCellHighlight");
+                        };
+
+                        hexCellDom.addEventListener("mouseover", mouseOverListener);
+                        asciiCellDom.addEventListener("mouseover", mouseOverListener);
+                        hexCellDom.addEventListener("mouseleave", mouseLeaveListener);
+                        asciiCellDom.addEventListener("mouseleave", mouseLeaveListener);
+                    }
+                }
+            },
+
+            _toAsciiPrintable: function (c)
+            {
+                if (c <= 32 || c >= 127)
+                {
+                    return ".";
+                }
+                else
+                {
+                    return String.fromCharCode(c);
+                }
+            },
+
+            _toHex: function (d, pad)
+            {
+                var hex = Number(d & 0xFF).toString(16);
+
+                while (hex.length < pad)
+                {
+                    hex = "0" + hex;
+                }
+
+                return hex;
+            }
+        });
+    });
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
index ebb59a8..e1d0fe7 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js
@@ -75,6 +75,22 @@
               updater)
     {
         var util = {};
+
+        if (Number.isInteger)
+        {
+            util.isInteger = function(value)
+            {
+                return Number.isInteger(value);
+            };
+        }
+        else
+        {
+            util.isInteger = function(value)
+            {
+                return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
+            };
+        }
+
         if (Array.isArray)
         {
             util.isArray = function (object)
@@ -988,5 +1004,16 @@
             return serializedUserName;
         };
 
+        util.stopEventPropagation = function(domNode, eventName)
+        {
+            on(domNode, eventName, function(evt)
+            {
+                if (evt)
+                {
+                    evt.stopPropagation();
+                }
+            });
+        }
+
         return util;
     });
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/DashboardTab.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/DashboardTab.js
index 50181ad..8fbdd01 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/DashboardTab.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/DashboardTab.js
@@ -168,12 +168,12 @@
                 message: "<div>Dashbord contains unsaved changes.<br/>Would you like to close it anyway?</div>",
                 confirmationId: "dashboard.confirmation.close.changed"
             })
-                .then(lang.hitch(this, this.destroy));
+                .then(lang.hitch(this, function(){this.destroy(true);}));
 
             return false;
         };
 
-        DashboardTab.prototype.destroy = function ()
+        DashboardTab.prototype.destroy = function (destroyContentPane)
         {
             if (this.destroyed)
             {
@@ -188,6 +188,12 @@
                 this.dashboardWidget.destroyRecursive();
                 this.dashboardWidget = null;
             }
+
+            if (destroyContentPane)
+            {
+                this.contentPane.getParent().removeChild(this.contentPane);
+                this.contentPane.destroyRecursive();
+            }
         };
 
         DashboardTab.stopDisplayingConfirmation = false;
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/QueryTab.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/QueryTab.js
index a2de59e..8fcf704 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/QueryTab.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/QueryTab.js
@@ -164,12 +164,12 @@
                 message: "<div>Query contains unsaved changes.<br/>Would you like to close it anyway?</div>",
                 confirmationId: "query.confirmation.close.changed"
             })
-                .then(lang.hitch(this, this.destroy));
+                .then(lang.hitch(this, function(){this.destroy(true);}));
 
             return false;
         };
 
-        QueryTab.prototype.destroy = function ()
+        QueryTab.prototype.destroy = function (destroyContentPane)
         {
             if (this.destroyed)
             {
@@ -184,6 +184,12 @@
                 this.queryWidget.destroyRecursive();
                 this.queryWidget = null;
             }
+
+            if (destroyContentPane)
+            {
+                this.contentPane.getParent().removeChild(this.contentPane);
+                this.contentPane.destroyRecursive();
+            }
         };
 
         return QueryTab;
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
index bd15d0f..80d2774 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/TrustStore.js
@@ -178,7 +178,7 @@
 
         TrustStore.prototype.deleteKeyStore = function ()
         {
-            if (confirm("Are you sure you want to delete trust store '" + this.keyStoreName + "'?"))
+            if (confirm("Are you sure you want to delete trust store '" + this.name + "'?"))
             {
                 var that = this;
                 this.management.remove(this.modelObj)
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/base64md5passwordfile/add.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/base64md5passwordfile/add.js
index 8627966..56a7fc9 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/base64md5passwordfile/add.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/base64md5passwordfile/add.js
@@ -25,11 +25,9 @@
         {
             util.parseHtmlIntoDiv(data.containerNode, "authenticationprovider/filebased/add.html", function ()
             {
-                if (data.data)
-                {
-                    var path = registry.byNode(query(".path", data.containerNode)[0]);
-                    path.set("value", data.data.path);
-                }
+                var pathWidget = registry.byNode(query(".path", data.containerNode)[0]);
+                pathWidget.set("disabled", data.data && data.data.id ? true : false);
+                pathWidget.set("value", data.data ? data.data.path : "");
             });
         }
     };
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/plainpasswordfile/add.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/plainpasswordfile/add.js
index 8627966..56a7fc9 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/plainpasswordfile/add.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/authenticationprovider/plainpasswordfile/add.js
@@ -25,11 +25,9 @@
         {
             util.parseHtmlIntoDiv(data.containerNode, "authenticationprovider/filebased/add.html", function ()
             {
-                if (data.data)
-                {
-                    var path = registry.byNode(query(".path", data.containerNode)[0]);
-                    path.set("value", data.data.path);
-                }
+                var pathWidget = registry.byNode(query(".path", data.containerNode)[0]);
+                pathWidget.set("disabled", data.data && data.data.id ? true : false);
+                pathWidget.set("value", data.data ? data.data.path : "");
             });
         }
     };
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/DashboardWidget.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/DashboardWidget.js
index a954409..282634d 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/DashboardWidget.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/DashboardWidget.js
@@ -92,7 +92,15 @@
                     }, this.queryBrowserNode);
                     this._queryBrowser.on("open", lang.hitch(this, this._onOpenQuery));
                 },
-
+                startup: function ()
+                {
+                    this.inherited(arguments);
+                    this._queryBrowser.startup();
+                },
+                resizeQueryBrowser: function ()
+                {
+                    this._queryBrowser.resize();
+                },
                 update: function ()
                 {
                     return this._queryBrowser.update();
@@ -171,7 +179,7 @@
                     this._addWidgetDialogContent.on("cancel",
                         lang.hitch(this._addWidgetDialog, this._addWidgetDialog.hide));
                     this._addWidgetDialogContent.on("add", lang.hitch(this, this._onWidgetChosen));
-
+                    this._addWidgetDialog.on("show", lang.hitch(this._addWidgetDialogContent, this._addWidgetDialogContent.resizeQueryBrowser));
                     this._saveDashboardDialogContent = new PreferenceSaveDialogContent({management: this.management});
                     this._saveDashboardDialog =
                         new dijit.Dialog({title: "Save Dashboard", content: this._saveDashboardDialogContent});
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/query.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/query.js
index d30ee20..11678cc 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/query.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/query.js
@@ -201,6 +201,7 @@
                             if (settingsIconNodes && settingsIconNodes.length == 1)
                             {
                                 settingsIconNodes[0].title = "Configure the settings of this widget.";
+                                util.stopEventPropagation(settingsIconNodes[0], "mousedown");
                             }
                         }
                     });
@@ -208,11 +209,13 @@
                     if (portlet.closeIcon)
                     {
                         portlet.closeIcon.title = "Remove this query from the dashboard.";
+                        util.stopEventPropagation(portlet.closeIcon, "mousedown");
                     }
 
                     if (portlet.arrowNode)
                     {
                         portlet.arrowNode.title = "Maximise/minimise this widget.";
+                        util.stopEventPropagation(portlet.arrowNode, "mousedown");
                     }
 
                     portlet._preferenceAccessIcon = portlet._createIcon("preferenceAccessIcon",
@@ -228,6 +231,7 @@
                             this.controller.showTab(tabData);
                         }));
                     portlet._preferenceAccessIcon.title = "Open this query in a separate tab.";
+                    util.stopEventPropagation(portlet._preferenceAccessIcon, "mousedown");
 
                     var settings = new QueryWidgetSettings();
                     settings.set("limit", this.limit);
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/unavailable.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/unavailable.js
index 87588e3..e1fdaea 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/unavailable.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/dashboard/widget/unavailable.js
@@ -24,14 +24,16 @@
         "dojo/Deferred",
         "dojo/Evented",
         "dojox/widget/Portlet",
-        "qpid/common/MessageDialog"],
+        "qpid/common/MessageDialog",
+        "qpid/common/util"],
     function (declare,
               lang,
               json,
               Deferred,
               Evented,
               Portlet,
-              MessageDialog)
+              MessageDialog,
+              util)
     {
 
         return declare(Evented, {
@@ -66,11 +68,13 @@
                 if (portlet.closeIcon)
                 {
                     portlet.closeIcon.title = "Remove this query from the dashboard.";
+                    util.stopEventPropagation(portlet.closeIcon, "mousedown");
                 }
 
                 if (portlet.arrowNode)
                 {
                     portlet.arrowNode.title = "Maximise/minimise this widget.";
+                    util.stopEventPropagation(portlet.arrowNode, "mousedown");
                 }
 
                 portlet.on("hide", lang.hitch(this, function(){
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/groupfile/add.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/groupfile/add.js
index 06df33b..3a13daa 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/groupfile/add.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/groupprovider/groupfile/add.js
@@ -32,11 +32,9 @@
             var that = this;
             util.parse(data.containerNode, template, function ()
             {
-                if (data.data)
-                {
-                    var pathWidget = registry.byNode(query(".addGroupProviderPath", data.containerNode)[0]);
-                    pathWidget.set("value", data.data.path);
-                }
+                var pathWidget = registry.byNode(query(".addGroupProviderPath", data.containerNode)[0]);
+                pathWidget.set("disabled", data.data && data.data.id ? true : false);
+                pathWidget.set("value",  data.data ? data.data.path : "");
             });
         }
     };
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js
index e6aa451..2ac96ef 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/DropDownSelect.js
@@ -87,7 +87,7 @@
                 this._selectedItems = this._optionsPanel.get("selectedItems");
                 popup.close(this._optionsDialog);
                 this._optionsPanel.resetItems();
-                this.emit("change", this._selectedItems);
+                this.emit("change", lang.clone(this._selectedItems));
             },
             _hideAndResetSearch: function ()
             {
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js
index 9dabff3..91d6c9a 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/query/WhereExpression.js
@@ -31,12 +31,13 @@
     return declare("qpid.management.query.WhereExpression", [ContentPane, Evented], {
         whereExpression: "",
         whereFieldsSelector: null,
-        _whereItems: {},
+        _whereItems: null,
         userPreferences: null,
 
         postCreate: function ()
         {
             this.inherited(arguments);
+            this._whereItems = {};
             if (this.whereFieldsSelector)
             {
                 this.whereFieldsSelector.on("change", lang.hitch(this, this._whereExpressionChanged));
diff --git a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js
index 97b34ea..072eef9 100644
--- a/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js
+++ b/broker-plugins/management-http/src/main/java/resources/js/qpid/management/showMessage.js
@@ -30,6 +30,7 @@
         "qpid/common/properties",
         "dojox/html/entities",
         "qpid/common/util",
+        "qpid/common/HexDumpWidget",
         "dojo/text!showMessage.html",
         'dojo/_base/declare',
         'dstore/Memory',
@@ -53,6 +54,7 @@
               properties,
               entities,
               util,
+              HexDumpWidget,
               template,
               declare,
               Memory,
@@ -95,6 +97,90 @@
 
         };
 
+        showMessage.createPreviewWidget = function(contentData, widgetDiv)
+        {
+            if (typeof contentData !== 'object')
+            {
+                return new dijit.form.SimpleTextarea({
+                    value: contentData,
+                    rows: 4,
+                    readOnly: true
+                }, widgetDiv);
+            }
+            else
+            {
+                if (Array.isArray(contentData))
+                {
+                    var isByteArray = true;
+
+                    for (var i = 0; i < contentData.length; i++)
+                    {
+                        var element = contentData[i];
+                        if (!util.isInteger(element) || element < -128 || element > 127)
+                        {
+                            isByteArray = false;
+                            break;
+                        }
+                    }
+
+                    if (isByteArray)
+                    {
+                        return new HexDumpWidget({data: contentData}, widgetDiv);
+                    }
+                    else
+                    {
+                        var columns = {
+                            value: {
+                                label: 'Item'
+                            }
+                        };
+                        var items = [];
+                        for (var i = 0; i < contentData.length; i++)
+                        {
+                            items.push({
+                                id: i,
+                                value: json.stringify(contentData[i])
+                            });
+                        }
+                        var store = new (declare([Memory, Trackable]))({
+                            data: items
+                        });
+                        return new (declare([OnDemandGrid, DijitRegistry]))({
+                            collection: store,
+                            columns: columns
+                        }, widgetDiv);
+                    }
+
+                }
+                else
+                {
+                    var columns = {
+                        id: {
+                            label: 'Key'
+                        },
+                        value: {
+                            label: 'Value'
+                        }
+                    };
+                    var items = [];
+                    for (var i in contentData)
+                    {
+                        items.push({
+                            id: i,
+                            value: json.stringify(contentData[i])
+                        });
+                    }
+                    var store = new (declare([Memory, Trackable]))({
+                        data: items
+                    });
+                    return new (declare([OnDemandGrid, DijitRegistry]))({
+                        collection: store,
+                        columns: columns
+                    }, widgetDiv);
+                }
+            }
+        }
+
         showMessage.populateShowMessage = function (management, modelObj, data, includesConfidential)
         {
 
@@ -151,7 +237,7 @@
                 }
             }
 
-            var preview = query('#preview', this.dialogNode)[0];
+            var contentAndPreview = query('#contentAndPreview', this.dialogNode)[0];
             var confidentialInformationWarning = query('#confidentialInformationWarning', this.dialogNode)[0];
             confidentialInformationWarning.style.display = includesConfidential ? "none" : "block";
             var confidentialCells = query('.confidential', this.dialogNode);
@@ -173,101 +259,47 @@
                     type: modelObj.type
                 };
                 var parameters = {messageId: data.id};
-                var url = management.buildObjectURL(contentModelObj, parameters);
-
-                var href = query('a#message-download', this.dialogNode)[0];
-                href.title = url;
-                connect.connect(href, 'onclick', function ()
+                var download = registry.byId('message-download', this.dialogNode);
+                download.on("click", function ()
                 {
                     management.download(contentModelObj, parameters);
                 });
 
-                if (data.mimeType && (data.mimeType.match(/text\/.*/)
-                                      || data.mimeType === "amqp/list"
-                                      || data.mimeType === "amqp/map"
-                                      || data.mimeType === "jms/map-message"))
-                {
-                    var limit = 1024;
-                    preview.style.display = "block";
-                    var previewDetail = query('#preview-detail', preview)[0];
-                    previewDetail.innerHTML = (limit < data.size
-                        ? 'showing the first ' + limit + ' of ' + data.size + ' bytes'
-                        : 'showing all ' + data.size + ' bytes');
-                    var previewContent = query("#message-content-preview", preview)[0];
-                    var previewParameters = lang.mixin({limit: limit, returnJson: true}, parameters);
-                    management.load(contentModelObj, previewParameters, {
-                            handleAs: "text",
-                            headers: {"Content-Type": data.mimeType}
-                        })
-                        .then(function (content)
+                var limit = 1024;
+                var previewParameters = lang.mixin({
+                    limit: limit,
+                    returnJson: true
+                }, parameters);
+                management.load(contentModelObj, previewParameters, {
+                        handleAs: "json"
+                    })
+                    .then(function (content)
+                    {
+                        if (showMessage.previewWidget)
                         {
-                            if (showMessage.previewWidget)
-                            {
-                                showMessage.previewWidget.destroyRecursive();
-                            }
+                            showMessage.previewWidget.destroyRecursive();
+                        }
+
+                        if (content == null || (Array.isArray(content) && content.length == 0))
+                        {
+                            contentAndPreview.style.display = "none";
+                        }
+                        else
+                        {
+                            contentAndPreview.style.display = "block";
+                            var previewDetail = query('#preview-detail', contentAndPreview)[0];
+                            previewDetail.innerHTML = (limit < data.size
+                                ? 'showing the first ' + limit + ' of ' + data.size + ' bytes'
+                                : 'showing all ' + data.size + ' bytes');
+                            var previewContent = query("#message-content-preview", contentAndPreview)[0];
+
                             var widgetDiv = construct.create("div", null, previewContent, "last");
-                            var contentWidget = null;
-                            if (data.mimeType === "amqp/list"
-                                || data.mimeType === "amqp/map"
-                                || data.mimeType === "jms/map-message")
-                            {
-                                var contentData = json.parse(content);
-                                var columns, items = [];
-                                if (data.mimeType === "amqp/list")
-                                {
-                                    columns = {
-                                        value: {
-                                            label: 'Item'
-                                        }
-                                    };
-                                    for (var i = 0; i < contentData.length; i++)
-                                    {
-                                        items.push({id: i, value: json.stringify(contentData[i])});
-                                    }
-                                }
-                                else
-                                {
-                                    columns = {
-                                        id: {
-                                            label: 'Key'
-                                        },
-                                        value: {
-                                            label: 'Value'
-                                        }
-                                    };
-
-                                    for (var i in contentData)
-                                    {
-                                        items.push({id: i, value: json.stringify(contentData[i])});
-                                    }
-                                }
-                                var store = new (declare([Memory, Trackable]))({
-                                    data: items
-                                });
-                                 contentWidget = new (declare([OnDemandGrid,DijitRegistry]))({
-                                    collection: store,
-                                    columns: columns
-                                }, widgetDiv);
-
-                            }
-                            else
-                            {
-                                contentWidget = new dijit.form.SimpleTextarea({
-                                    value: content,
-                                    rows: 4,
-                                    readOnly: true
-                                }, widgetDiv);
-                            }
+                            var contentWidget = showMessage.createPreviewWidget(content, widgetDiv);
                             showMessage.previewWidget = contentWidget;
                             contentWidget.startup();
-                            registry.byId("showMessage") .show();
-                        });
-                }
-                else
-                {
-                    preview.style.display = "none";
-                    registry.byId("showMessage").show();
-                }
+                        }
+                        registry.byId("showMessage") .show();
+                    });
             }
             else
             {
diff --git a/broker-plugins/management-http/src/main/java/resources/query/WhereCriteria.html b/broker-plugins/management-http/src/main/java/resources/query/WhereCriteria.html
index fc9856f..cd43f8d 100644
--- a/broker-plugins/management-http/src/main/java/resources/query/WhereCriteria.html
+++ b/broker-plugins/management-http/src/main/java/resources/query/WhereCriteria.html
@@ -30,7 +30,7 @@
                 return false;
                 </script>
 
-                <input class="criteriaControl"
+                <input class="criteriaControl readOnly"
                           data-dojo-type="dijit/form/TextBox"
                           data-dojo-attach-point="newColumnCondition"
                           data-dojo-props="readOnly:true, title: 'Current where expression'"/>
diff --git a/broker-plugins/management-http/src/main/java/resources/showBroker.html b/broker-plugins/management-http/src/main/java/resources/showBroker.html
index b0f0ae2..00973f0 100644
--- a/broker-plugins/management-http/src/main/java/resources/showBroker.html
+++ b/broker-plugins/management-http/src/main/java/resources/showBroker.html
@@ -46,11 +46,11 @@
                 <div id="brokerAttribute.confidentialConfigurationEncryptionProvider"></div>
             </div>
             <div id="brokerAttribute.statisticsReportingPeriod.container" class="hidden clear">
-                <div class="formLabel-labelCell">Statistics reporting period (ms):</div>
+                <div class="formLabel-labelCell">Statistics reporting period (s):</div>
                 <div id="brokerAttribute.statisticsReportingPeriod"></div>
             </div>
             <div id="brokerAttribute.statisticsReportingResetEnabled.container" class="hidden clear">
-                <div class="formLabel-labelCell">Statistics reporting period enabled:</div>
+                <div class="formLabel-labelCell">Statistics reporting auto-reset enabled:</div>
                 <div id="brokerAttribute.statisticsReportingResetEnabled"></div>
             </div>
             <div class="clear"></div>
@@ -61,7 +61,7 @@
                     <div id="brokerAttribute.connection.sessionCountLimit"></div>
                 </div>
                 <div id="brokerAttribute.connection.heartBeatDelay.container" class="clear">
-                    <div class="formLabel-labelCell">Heart beat delay (ms):</div>
+                    <div class="formLabel-labelCell">Heart beat delay (s):</div>
                     <div id="brokerAttribute.connection.heartBeatDelay"></div>
                 </div>
                 <div class="clear"></div>
diff --git a/broker-plugins/management-http/src/main/java/resources/showMessage.html b/broker-plugins/management-http/src/main/java/resources/showMessage.html
index fadb9d3..0df1b65 100644
--- a/broker-plugins/management-http/src/main/java/resources/showMessage.html
+++ b/broker-plugins/management-http/src/main/java/resources/showMessage.html
@@ -16,7 +16,10 @@
   -->
 
 <div class="dijitHidden">
-    <div data-dojo-type="dijit.Dialog" style="width:600px;" data-dojo-props="title:'View Message'" id="showMessage">
+    <div data-dojo-type="dijit.Dialog" style="width:600px;"
+         data-dojo-props="title:'View Message',
+                          autofocus: false"
+         id="showMessage">
 
         <div id="confidentialInformationWarning" class="infoMessage">Confidential message information (headers
             and content) is not available on an insecure transport. Switch to a secure management transport (i.e. one
@@ -87,11 +90,11 @@
             <td style="width: 10em; vertical-align: top"><span style="font-weight: bold;">Content:</span></td>
             <td>
                 <div class="confidential">
-                    <a href="#" id="message-download">Download</a>
-                    <br/>
-                    <div id="preview">
+                    <div id="contentAndPreview">
                         Preview (<span id="preview-detail"></span>):<br/>
                         <div id="message-content-preview"></div>
+                        <br/>
+                        <input type="button" id="message-download" label="Download Content" dojoType="dijit.form.Button"/>
                     </div>
                 </div>
                 <div class="confidentialPlaceholder highlightedText">Not available</div>
diff --git a/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java b/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java
index 735fb4f..d9f6f53 100644
--- a/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java
+++ b/client/src/main/java/org/apache/qpid/client/security/scram/AbstractScramSaslClient.java
@@ -40,6 +40,8 @@
 import javax.security.sasl.SaslException;
 import javax.xml.bind.DatatypeConverter;
 
+import org.apache.qpid.util.Strings;
+
 public abstract class AbstractScramSaslClient implements SaslClient
 {
 
@@ -129,7 +131,7 @@
         {
             throw new SaslException("Server final message did not contain verifier");
         }
-        byte[] serverSignature = DatatypeConverter.parseBase64Binary(parts[0].substring(2));
+        byte[] serverSignature = Strings.decodeBase64(parts[0].substring(2));
         if(!Arrays.equals(_serverSignature, serverSignature))
         {
             throw new SaslException("Server signature did not match");
@@ -165,7 +167,7 @@
                 throw new SaslException("Server challenge '" + serverFirstMessage + "' cannot be parsed, cannot find salt");
             }
             String base64Salt = parts[1].substring(2);
-            _salt = DatatypeConverter.parseBase64Binary(base64Salt);
+            _salt = Strings.decodeBase64(base64Salt);
             if(!parts[2].startsWith("i="))
             {
                 throw new SaslException("Server challenge '" + serverFirstMessage + "' cannot be parsed, cannot find iteration count");
diff --git a/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java b/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
index 1d181ca..24207f3 100644
--- a/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
+++ b/common/src/main/java/org/apache/qpid/transport/network/security/ssl/SSLUtil.java
@@ -63,12 +63,12 @@
 import javax.net.ssl.SSLParameters;
 import javax.net.ssl.SSLPeerUnverifiedException;
 import javax.net.ssl.SSLSocket;
-import javax.xml.bind.DatatypeConverter;
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import org.apache.qpid.transport.TransportException;
+import org.apache.qpid.util.Strings;
 
 public class SSLUtil
 {
@@ -388,7 +388,7 @@
                     keyBuilder.append(line);
                 }
 
-                content = DatatypeConverter.parseBase64Binary(keyBuilder.toString());
+                content = Strings.decodeBase64(keyBuilder.toString());
             }
         }
         return readPrivateKey(content, "RSA");
diff --git a/common/src/main/java/org/apache/qpid/util/Strings.java b/common/src/main/java/org/apache/qpid/util/Strings.java
index d995d62..b94ac11 100644
--- a/common/src/main/java/org/apache/qpid/util/Strings.java
+++ b/common/src/main/java/org/apache/qpid/util/Strings.java
@@ -33,6 +33,8 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.xml.bind.DatatypeConverter;
+
 
 /**
  * Strings
@@ -125,6 +127,17 @@
         return resolver;
     }
 
+    public static byte[] decodeBase64(String base64String)
+    {
+        base64String = base64String.replaceAll("\\s","");
+        if(!base64String.matches("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$"))
+        {
+            throw new IllegalArgumentException("Cannot convert string '"+ base64String+ "'to a byte[] - it does not appear to be base64 data");
+        }
+
+        return DatatypeConverter.parseBase64Binary(base64String);
+    }
+
     public static interface Resolver
     {
         String resolve(String variable, final Resolver resolver);
diff --git a/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Channel-REST-API.xml b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Channel-REST-API.xml
index 5d2790d..350c486 100644
--- a/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Channel-REST-API.xml
+++ b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Channel-REST-API.xml
@@ -342,6 +342,8 @@
     </para>
   </section>
 
+  <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="Java-Broker-Management-Channel-REST-Query-API.xml"/>
+
   <section xml:id="Java-Broker-Management-Channel-REST-API-CORS">
     <title>Cross Origin Resource Sharing (CORS)</title>
     <para> The Broker supports Cross Origin Resource Sharing (CORS)
diff --git a/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Channel-REST-Query-API.xml b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Channel-REST-Query-API.xml
new file mode 100644
index 0000000..e56ea0d
--- /dev/null
+++ b/doc/java-broker/src/docbkx/management/channels/Java-Broker-Management-Channel-REST-Query-API.xml
@@ -0,0 +1,285 @@
+<?xml version="1.0"?>
+<!--
+  ~ 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.
+  ~
+  -->
+
+<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="Java-Broker-Management-Channel-REST-Query-API">
+    <title>Query API</title>
+    <section xml:id="Java-Broker-Management-Channel-REST-Query-API-Introduction">
+        <title>Introduction</title>
+        <para>The <emphasis>Qpid Broker for Java</emphasis> provides a powerful feature called
+            the <emphasis>Query API</emphasis>. This allows the retrieval of the existing configured objects attributes
+            satisfying user-provided queries.</para>
+        <para>Developers and operators can use this feature to monitor the Broker.
+            For example, using <emphasis>Query API</emphasis> one can find all queues with queue depth
+            exceeding some limit or existing connections made from a particular location(s).</para>
+    </section>
+    <section xml:id="Java-Broker-Management-Channel-REST-Query-API-Overview">
+        <title>Query API Overview</title>
+        <para>
+            When using the <emphasis>Query API</emphasis> one specifies the category of the object
+            to query, a list of attributes to return in the result set, an optional where clause,
+            expressed as a predicate, that determines the filtering criteria, ordering, and
+            limit/offset. The features should be readily recognisable to anyone who has has familiarity
+            with SQL.
+        </para>
+        <para>Queries associate with either the <emphasis>broker</emphasis> as a whole, or an
+            individual  <emphasis>virtualhost</emphasis>.  Queries associated with the Broker
+            can query any object within the Broker. Queries associated with a virtualhost are limited
+            to the objects of the virtualhost itself.   For instance a queue query associated
+            with a virtualhost queries only the queues belonging to that virtualhost.  On the other
+            hand, a queue query associated with the Broker sees all the queues belonging on the entire
+            Broker.
+        </para>
+        <para>
+            <table>
+                <title>Query API URLs</title>
+                <tgroup cols="2">
+                    <thead>
+                        <row>
+                            <entry>Query API URL</entry>
+                            <entry>Description</entry>
+                        </row>
+                    </thead>
+                    <tbody>
+                        <row>
+                            <entry>
+                                <para>/api/latest/querybroker/&lt;configured object category name&gt;</para>
+                                <para>/api/&lt;version&gt;/querybroker/&lt;configured object category name&gt;</para>
+                            </entry>
+                            <entry>
+                                <para>Query API URL fragment to query the specified object type across the entire broker</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para>/api/latest/queryvhost/&lt;virtual host node name&gt;/&lt;virtual host name&gt;/&lt;configured object category name&gt;</para>
+                                <para>/api/&lt;version&gt;/queryvhost/&lt;virtual host node name&gt;/&lt;virtual host name&gt;/&lt;configured object category name&gt;</para>
+                            </entry>
+                            <entry>
+                                <para>Query API URL fragment to query the specified object type for a specific virtualhost</para>
+                            </entry>
+                        </row>
+                    </tbody>
+                </tgroup>
+            </table>
+        </para>
+        <para>
+            The QueryAPI accepts <literal>select</literal>, <literal>where</literal>, <literal>orderBy</literal>,
+            <literal>limit</literal> and <literal>offset</literal> request parameters.
+            <table>
+                <title>Query API request parameters</title>
+                <tgroup cols="2">
+                    <thead>
+                        <row>
+                            <entry>Parameter Name</entry>
+                            <entry>Parameter Description</entry>
+                        </row>
+                    </thead>
+                    <tbody>
+                        <row>
+                            <entry>
+                                <para><literal>select</literal></para>
+                            </entry>
+                            <entry>
+                                <para>The <literal>select</literal> defines the columns of the result set.  It is a
+                                    comma-separated list of expressions.  At its most simple, an expression can be
+                                    the name of the attribute (e.g. <literal>queueDepthBytes</literal>), but more complex
+                                    <link linkend="Java-Broker-Management-Channel-REST-Query-API-Expressions">expressions</link> are also supported.</para>
+                                <para>Columns within the result set are named.  For expressions that are simple attribute
+                                    names, the column names will follow the attributes themselves.  By default, other
+                                    expressions will have a no name.</para>
+                                <para>Column names can be overridden with an <literal>AS</literal>
+                                    clause e.g. <literal>now() AS currentDate</literal>
+                                </para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>where</literal></para>
+                            </entry>
+                            <entry>
+                                <para>The <literal>where</literal> provides a boolean expression defining the result set filtering.</para>
+                                <para>The syntax of the <link linkend="Java-Broker-Management-Channel-REST-Query-API-Expressions">expression</link>
+                                    is based on a subset of the SQL92 conditional expression syntax and is similar to selector expressions in JMS e.g.
+                                    <literal>queueDepthBytes > 16384 AND name like '%flow_queue'</literal>.
+                                </para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>orderBy</literal></para>
+                            </entry>
+                            <entry>
+                                <para>Ordering conditions; the syntax of the
+                                    <link linkend="Java-Broker-Management-Channel-REST-Query-API-Expressions">
+                                        expression
+                                    </link>
+                                    is based on a subset of
+                                    the SQL92 ordering expression syntax. Similar to ordering expressions in SQL,
+                                    one can specify in ordering expression attributes names, sub-expressions
+                                    or indexes (starting from 1) of attributes or expressions specified in select.
+                                </para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>limit</literal></para>
+                            </entry>
+                            <entry>
+                                <para>The maximum number of results to provide starting from given offset.</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>offset</literal></para>
+                            </entry>
+                            <entry>
+                                <para>An offset in results (default is 0) to provide results from.</para>
+                            </entry>
+                        </row>
+                    </tbody>
+                </tgroup>
+            </table>
+        </para>
+        <example>
+            <title>Example of a Query API request to retrieve queue names and depths.</title>
+            <screen>GET api/latest/querybroker/queue?select=name,queueDepthBytes,queueDepthMessages&amp;where=queueDepthBytes&gt;0&amp;orderBy=1 desc,2 desc&amp;offset=0&amp;limit=100 HTTP/1.1</screen>
+        </example>
+    </section>
+    <section xml:id="Java-Broker-Management-Channel-REST-Query-API-Results">
+        <title>Query API Results</title>
+        <para>The <emphasis>Query API</emphasis> returns a JSON response.  The response contains the following:
+            <variablelist>
+                <varlistentry>
+                    <term><literal>headers</literal></term>
+                    <listitem>
+                        <para>ordered list of result set column names derived from the <literal>select</literal>
+                            clause. Note that anonymous expressions (that is, those expressed without an
+                            <literal>AS</literal>) will have empty column name.</para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term><literal>results</literal></term>
+                    <listitem>
+                        <para>two dimensional array containing the result-set</para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term><literal>total</literal></term>
+                    <listitem>
+                        <para>The <emphasis>total</emphasis> number of results matching the where criteria.</para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+        </para>
+        <example>
+            <title>Example of Query API call for queue names and depths.</title>
+            <screen>GET api/latest/querybroker/queue?select=name,queueDepthBytes,queueDepthMessages&amp;where=queueDepthBytes&gt;0&amp;orderBy=1 desc,2 desc&amp;offset=0&amp;limit=100 HTTP/1.1</screen>
+            <programlisting language="javascript">
+{
+    "headers" : [ "name", "queueDepthBytes", "queueDepthMessages" ],
+    "results" : [ [ "foo", 312, 26], [ "bar", 300, 24 ] ],
+    "total" : 2
+}
+            </programlisting>
+        </example>
+        <section xml:id="Java-Broker-Management-Channel-REST-Query-API-Expressions">
+            <title>Query API expressions</title>
+
+            <para>Expressions within the <literal>select</literal>, <literal>where</literal> and <literal>orderBy</literal>
+                clauses can be comprised in the following manner. Expressions can be nested to arbitary depth. Parentheses
+                allow for precedence to be explicitly denoted.
+            <itemizedlist>
+                <listitem><para>variable name which can be an attribute name e.g <literal>queueDepthBytes</literal> or
+                a reference to a parent attribute <literal>$parent.name</literal></para></listitem>
+                <listitem><para>literal e.g. <literal>3</literal> or <literal>'foo'</literal></para></listitem>
+                <listitem><para>functions - see below e.g. <literal>now()</literal> or <literal>to_string(createdDate, '%tm/%td/%ty', 'EST')</literal></para></listitem>
+                <listitem><para>arithmetic operations e.g. <literal>3 * 4</literal> or <literal>to_string(now()) + name</literal></para></listitem>
+            </itemizedlist></para>
+            <para>The following functions are supported:
+                <table>
+                    <title>Query API functions</title>
+                    <tgroup cols="2">
+                    <thead>
+                        <row>
+                            <entry>Function Name</entry>
+                            <entry>Function Description</entry>
+                        </row>
+                    </thead>
+                    <tbody>
+                        <row>
+                            <entry>
+                                <para><literal>concat(obj[,obj..])</literal></para>
+                            </entry>
+                            <entry>
+                                <para>concatenates the given objects into a string</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>now()</literal></para>
+                            </entry>
+                            <entry>
+                                <para>returns current date and time</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>to_date(object)</literal></para>
+                            </entry>
+                            <entry>
+                                <para>converts the first parameter, which must be a string. into a date.  The
+                                string must be in ISO-8601 format e.g. <literal>1970-01-01T10:00:00Z</literal>.</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>date_add(object, duration)</literal></para>
+                            </entry>
+                            <entry>
+                                <para>adds the given ISO-8601 duration <literal>duration</literal> e.g.
+                                    <literal>P1D</literal> or <literal>-PT10H</literal> to the date provided by the
+                                    first parameter.</para>
+                            </entry>
+                        </row>
+                        <row>
+                            <entry>
+                                <para><literal>to_string(object[, format[, timezone]])</literal></para>
+                            </entry>
+                            <entry>
+                                <para>Converts given object into a string.</para>
+                                <para>If the format argument is present, it must be a Java
+                                    <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleJdkDocUrl}java/util/Formatter.html">Formatter</link>
+                                    compliant string e.g. <literal>%f</literal> or <literal>%tY-%tm-%td</literal>.
+                                </para>
+                                <para>The timezone argument is significant if the object is a Date. If the timezone
+                                    argument is specified it must be a valid Java timezone name. The date is converted
+                                    to the specified timezone before being formatted by the<literal>format</literal>.
+                                    If the timezone is omitted <literal>UTC</literal> is assumed.
+                                </para>
+                            </entry>
+                        </row>
+                    </tbody>
+                    </tgroup>
+                </table>
+            </para>
+        </section>
+    </section>
+</section>
diff --git a/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Truststores.xml b/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Truststores.xml
index d3dab62..37f02cd 100644
--- a/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Truststores.xml
+++ b/doc/java-broker/src/docbkx/management/managing/Java-Broker-Management-Managing-Truststores.xml
@@ -22,10 +22,31 @@
 
 <section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="Java-Broker-Management-Managing-Truststores">
     <title>Truststores</title>
-    <para> A <link linkend="Java-Broker-Concepts-Truststores">Truststore</link> is required by a
-        Port in order to SSL client authentication. Some authentication provides also use a
-        truststore when connecting to authentication systems that are protected by a private issuer
-        SSL certificate.</para>
+    <para>
+        <link linkend="Java-Broker-Concepts-Truststores">Truststores</link>
+        have a number of roles within
+        the Broker.
+        <itemizedlist>
+            <listitem>
+                <para>A truststore is required by a Port in order to support SSL client authentication.</para>
+            </listitem>
+            <listitem>
+                <para>Truststores have a optional role in end to end message encryption. The Broker acts as a
+                    <link xmlns:xlink="http://www.w3.org/1999/xlink"
+                          xlink:href="https://en.wikipedia.org/wiki/Key_server_(cryptographic)">
+                        Key Server
+                    </link>
+                    so that publishing applications have convenient access to recipient's public keys.
+                </para>
+            </listitem>
+            <listitem>
+                <para>Some authentication providers also use a truststore when connecting to authentication systems that
+                    are protected by a private issuer
+                    SSL certificate.
+                </para>
+            </listitem>
+        </itemizedlist>
+    </para>
     <section xml:id="Java-Broker-Management-Managing-Truststores-Types">
         <title>Types</title>
         <para>The following truststore types are supported. <itemizedlist>
@@ -55,6 +76,11 @@
                     <para><emphasis>Name the truststore</emphasis>. Used to identify the
                         truststore.</para>
                 </listitem>
+                <listitem>
+                    <para><emphasis>Exposed as Message Source</emphasis>. If enabled, the Broker
+                        will distribute certificates contained within the trustore to clients.
+                        Used by the end to end message encryption feature.</para>
+                </listitem>
             </itemizedlist>
         </para>
         <para>The following attributes apply to <emphasis>File Trust Stores</emphasis> only.</para>
diff --git a/doc/java-broker/src/docbkx/runtime/Java-Broker-Runtime-Memory.xml b/doc/java-broker/src/docbkx/runtime/Java-Broker-Runtime-Memory.xml
index c7bd120..8babeb8 100644
--- a/doc/java-broker/src/docbkx/runtime/Java-Broker-Runtime-Memory.xml
+++ b/doc/java-broker/src/docbkx/runtime/Java-Broker-Runtime-Memory.xml
@@ -57,7 +57,7 @@
     <section>
       <title>Direct</title>
       <para>
-        The world ouside of the JVM, in particular the operating system (OS), does not know about Java heap memory and uses other structures like C arrays.
+        The world outside of the JVM, in particular the operating system (OS), does not know about Java heap memory and uses other structures like C arrays.
         In order to interact with these systems Java needs to copy data between its own heap memory and these native structures.
         This can become a bottle neck when there is a lot of exchange between Java and the OS like in I/O (both disk and network) heavy applications.
         Java's solution to this is to allow programmers to request <literal>ByteBuffer</literal>s from so called direct memory.
@@ -158,7 +158,7 @@
   <section xml:id="Java-Broker-Runtime-Memory-Defaults">
     <title>Defaults</title>
     <para>
-      By default Qpid uses these settiongs:
+      By default Qpid uses these settings:
       <itemizedlist>
         <listitem>
           0.5 GB heap memory
@@ -173,7 +173,7 @@
           Start flow-to-disk at 40% direct memory utilisation.
         </listitem>
       </itemizedlist>
-      As an example, this would accomodate a broker with 50 connections, each serving 5 sessions, and each session having 1000 messages of 1 kB on queues in the broker.
+      As an example, this would accommodate a broker with 50 connections, each serving 5 sessions, and each session having 1000 messages of 1 kB on queues in the broker.
       This means a total of 250 concurrent sessions and a total of 250000 messages without flowing messages to disk.
     </para>
   </section>
@@ -214,16 +214,25 @@
       <para>
         <informalequation>
           <mathphrase>
-            memory<subscript>heap</subscript> = 15 MB + 15 kB * N<subscript>sessions</subscript> + 1 kB * N<subscript>messages</subscript> + 17 kB * N<subscript>connections</subscript>
+            memory<subscript>heap</subscript> = 15 MB + 15 kB * N<subscript>sessions</subscript> + 1.5 kB * N<subscript>messages</subscript> + 17 kB * N<subscript>connections</subscript>
           </mathphrase>
         </informalequation>
+      </para>
+      <para>
         <informalequation>
           <mathphrase>
-            memory<subscript>direct</subscript> = 2 MB + (200 B + averageSize<subscript>msg</subscript> *2)*  N<subscript>messages</subscript> + 512 kB * N<subscript>connections</subscript>
+            memory<subscript>direct</subscript> = 2 MB + (200 B + averageSize<subscript>msg</subscript> *2)*  N<subscript>messages</subscript> + 1MB * N<subscript>connections</subscript>
           </mathphrase>
         </informalequation>
+      </para>
+      <para>
         Where <mathphrase>N</mathphrase> denotes the total number of connections/sessions/messages on the broker. Furthermore, for direct memory only the messages that have not been flown to disk are relevant.
       </para>
+      <note>
+        <para>The formulae assume the worst case in terms of memory usage: persistent messages and TLS connections. Transient messages consume less heap memory than peristent and plain connections consume less direct memory than TLS
+          connections.
+        </para>
+      </note>
     </section>
     <section>
       <title>Things to Consider</title>
@@ -234,7 +243,7 @@
           This can have impact on performance in the transient case where otherwise no disk I/O would be involved.
         </para>
         <para>
-          Having to little heap memory will result in poor performance due to frequent garbage collection events. See <xref linkend="Java-Broker-Runtime-Memory-Low-Memory"/> for more details.
+          Having too little heap memory will result in poor performance due to frequent garbage collection events. See <xref linkend="Java-Broker-Runtime-Memory-Low-Memory"/> for more details.
         </para>
       </section>
       <section>
diff --git a/doc/jms-client-0-8/src/docbkx/JMS-Client-Appendix-Exceptions.xml b/doc/jms-client-0-8/src/docbkx/JMS-Client-Appendix-Exceptions.xml
index b001187..5435378 100644
--- a/doc/jms-client-0-8/src/docbkx/JMS-Client-Appendix-Exceptions.xml
+++ b/doc/jms-client-0-8/src/docbkx/JMS-Client-Appendix-Exceptions.xml
@@ -103,6 +103,15 @@
               group) has not been permissioned within the Broker's <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${qpidJavaBrokerBook}Java-Broker-Security-ACLs.html">Access Control List
                 (ACL)</link>.</para></entry>
         </row>
+        <row xml:id="JMS-Client-0-8-Appendix-Exceptions-CertificateException">
+          <entry>CertificateException</entry>
+          <entry>Unable to find certificate for recipient '&lt;recipient&gt;'</entry>
+          <entry>
+            <para>When using end to end message encryption, this exception indicates the the message recipent's
+              principal cannot be found in the truststore. See <xref linkend="JMS-Client-Message-Encryption"/>
+            </para>
+          </entry>
+        </row>
       </tbody>
     </tgroup>
   </table>
diff --git a/doc/jms-client-0-8/src/docbkx/JMS-Client-Message-Encryption.xml b/doc/jms-client-0-8/src/docbkx/JMS-Client-Message-Encryption.xml
index b19e0f4..3287b6c 100644
--- a/doc/jms-client-0-8/src/docbkx/JMS-Client-Message-Encryption.xml
+++ b/doc/jms-client-0-8/src/docbkx/JMS-Client-Message-Encryption.xml
@@ -88,8 +88,16 @@
                 <link linkend="JMS-Client-0-8-Connection-URL-BrokerOptions-EncryptionRemoteTrustStore">encryption_remote_trust_store</link>
                 option. Such a connection URL might look somthing like:
             </para>
-            <programlisting>amqp://username:password@clientid/test?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%5c/certstore''</programlisting>
-
+            <programlisting>amqp://username:password@clientid/test?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/certstore''</programlisting>
+            <para>
+                The <literal>$certificates/</literal> prefix is mandatory.
+                However, in order to prevent the client from interpreting this the wrong way several layers of escaping and encoding need to take place.
+                The slash character ('/') needs to be escaped by a backslash ('\') which needs to be doubly URL encoded resulting in <literal>$certificates%255c/</literal>.
+            </para>
+            <para>
+                Note that to use the broker-distributed certificates the broker must be configured to expose the trust store as a message source.
+                See the broker documentation on TrustStores for more details.
+            </para>
         </section>
         <section xml:id="JMS-Client-Message-Encryption-Sending-Enabling-Encryption">
             <title>Enabling Encryption</title>
@@ -107,7 +115,7 @@
             <para>
                 In order to encrypt all messages sent to a given Destination, the option
                 <link linkend="JMS-Client-0-8-Binding-URL-Options-SendEncrypted">sendencrypted</link> can be used.  Note
-                that enabling encryption on the address can be overridden by explicitly seting the property
+                that enabling encryption on the address can be overridden by explicitly setting the property
                 <literal>x-qpid-encrypt</literal> to false on an individual message. An example address would look like:
             </para>
             <programlisting>direct:///queue/queue?sendencrypted='true'</programlisting>
@@ -170,4 +178,216 @@
 
         </section>
     </section>
+    <section  xml:id="JMS-Client-Message-Encryption-Example">
+        <title>Message Encryption Example</title>
+        <section xml:id="JMS-Client-Message-Encryption-Example-Introduction">
+            <title>Introduction</title>
+            <para>
+                In this example we will setup the Qpid Broker for Java and two clients who will send each other encrypted messages.
+                The clients will use self signed certificates and the certificates will be distributed by the Broker.
+            </para>
+        </section>
+        <section xml:id="JMS-Client-Message-Encryption-Example-Prerequisites">
+            <title>Prerequisites</title>
+            <para>
+                For this example it is assumed the Broker is already running and that Management is enabled on port
+                8443.
+            </para>
+            <para>
+                The example requires two (one for each client) self-signed X.509 certificates and the corresponding
+                keys. We refer to these as
+                <literal>client_1/2.cert</literal>
+                and
+                <literal>client_1/2.key</literal>
+                throughout the text below.
+            </para>
+            <para>
+                The following
+                <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://www.openssl.org">openssl</link>
+                commands can be used to generate self signed certicates suitable for this test.
+                <programlisting>
+<![CDATA[openssl req -x509 -newkey rsa:4096 -keyout client_1.key -out client_1.cert -days 365 -nodes -subj "/C=US/O=Apache/OU=Qpid/CN=client1"
+openssl req -x509 -newkey rsa:4096 -keyout client_2.key -out client_2.cert -days 365 -nodes -subj "/C=US/O=Apache/OU=Qpid/CN=client2"]]>
+                </programlisting>
+            </para>
+        </section>
+        <section xml:id="JMS-Client-Message-Encryption-Example-Broker-Config">
+            <title>Broker Configuration</title>
+            <para>
+                In this example we want the broker to distribute the client certificates.
+                Essentially, we want the broker to act as a<link xmlns:xlink="http://www.w3.org/1999/xlink"
+                                                                 xlink:href="https://en.wikipedia.org/wiki/Key_server_(cryptographic)">
+                Key Server</link>.
+                Use
+                <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleKeytool}">java's keytool</link>
+                to create a trust store containing the two client certificates.
+                <programlisting>
+<![CDATA[keytool -importcert -file client_1.cert -alias client1 -keystore mytruststore.jks
+keytool -importcert -file client_2.cert -alias client2 -keystore mytruststore.jks]]>
+                </programlisting>
+                Now a FileTrustStore can be created on the broker pointing to the java trust store that was just
+                created.
+                This can be done via the Web Management Console or the REST API:
+                <programlisting>curl -v -u admin https://localhost:8443/api/v6.1/truststore/clientcerts -X PUT -d
+                    '{"type": "FileTrustStore", "stroeUrl": "&lt;path_to_truststore&gt;", "password": "&lt;your_truststore_password&gt;"}'
+                </programlisting>
+                The TrustStore must be configured to expose the certificates as a message source to the clients:
+                <programlisting>curl -v -u admin https://localhost:8443/api/v6.1/truststore/clientcerts -X POST -d
+                    '{"exposedAsMessageSource": true}'
+                </programlisting>
+            </para>
+        </section>
+        <section xml:id="JMS-Client-Message-Encryption-Example-Client-Config">
+            <title>Client Configuration</title>
+            <para>
+                The configuration for the clients happens in the connection URL. In this example this is provided via a
+                JNDI properties file.
+            </para>
+            <para>
+                On the producing side, in order to encrypt a message for a recipient, the Qpid client needs the
+                recipient's public certificate which is distributed by the Broker following our above broker setup. The
+                <literal>encryption_remote_trust_store</literal>
+                element within the connection URL provides the name of the truststore.
+            </para>
+            <para>
+                On the receiving side, in order to decrypt a message it needs a JKS keystore with the private key
+                matching the public certificate.
+                For this example, the keystores can again be created with a two-step process involving
+                <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://www.openssl.org">openssl</link>
+                and <link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="${oracleKeytool}">java's keytool</link>.
+                <programlisting>
+<![CDATA[openssl pkcs12 -export -in client_1.cert -inkey client_1.key -out client_1.pkcs12 -name "client1"
+openssl pkcs12 -export -in client_2.cert -inkey client_2.key -out client_2.pkcs12 -name "client2"
+
+keytool -importkeystore -destkeystore client_1.jks -srckeystore client_1.pkcs12 -srcstoretype PKCS12
+keytool -importkeystore -destkeystore client_2.jks -srckeystore client_2.pkcs12 -srcstoretype PKCS12]]>
+                </programlisting>
+
+            </para>
+            <para>
+                The final JNDI properties file should look similar to this:
+                <programlisting>
+java.naming.factory.initial = org.apache.qpid.jndi.PropertiesFileInitialContextFactory
+
+# connection factories. This is where end-to-end encryption is configured on the client.
+# connectionfactory.[jndiname] = [ConnectionURL]
+connectionfactory.producerConnectionFactory = amqp://&lt;username&gt;:&lt;password&gt;@?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/clientcerts''
+connectionfactory.consumer1ConnectionFactory = amqp://&lt;username&gt;:&lt;password&gt;@?brokerlist='tcp://localhost:5672?encryption_key_store='path/to/client_1.jks'&amp;encryption_key_store_password='&lt;keystore_password&gt;''
+connectionfactory.consumer2ConnectionFactory = amqp://&lt;username&gt;:&lt;password&gt;@?brokerlist='tcp://localhost:5672?encryption_key_store='path/to/client_2.jks'&amp;encryption_key_store_password='&lt;keystore_password&gt;''
+
+# Rest of JNDI configuration. For example
+# destination.[jniName] = [Address Format]
+queue.myTestQueue = testQueue
+                </programlisting>
+            </para>
+        </section>
+        <section xml:id="JMS-Client-Message-Encryption-Example-Application">
+            <title>Application Code</title>
+            <para>
+                On the producing side, the application needs to enable encryption and indicate the intended recipient(s)
+                of each message. This is done via the
+                <literal>x-qpid-encrypt</literal>
+                and
+                <literal>x-qpid-encrypt-recipients</literal>
+                message properties. Note that the order of the relative distinguished name (RDN) entries within the
+                recipent's distinguished name (DNs) is significant. If the order does not match that recorded in
+                truststore, a
+                <link linkend="JMS-Client-0-8-Appendix-Exceptions-CertificateException">CertificateException</link>
+                will be encountered.
+            </para>
+            <para>
+                On the receiving side, there is nothing to do.  The application code does not have to add decryption code as this is handled transparently by the Qpid client library.
+                However, the receiving application should gracefully handle failures in decryption in which case the encrypted message will be delivered as a BytesMessage.
+                <programlisting language="java">
+// imports omitted for brevity
+
+public class EncryptionExample {
+    public EncryptionExample() {
+    }
+
+    public static void main(String[] args) throws Exception {
+        EncryptionExample encryptionExampleApp = new EncryptionExample();
+        encryptionExampleApp.runProducerExample();
+        encryptionExampleApp.runReceiverExample();
+    }
+
+    private void runProducerExample() throws Exception
+    {
+        Connection connection = createConnection("producerConnectionFactory");
+        try {
+            Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+            Destination destination = createDesination("myTestQueue");
+
+            MessageProducer messageProducer = session.createProducer(destination);
+            TextMessage message = session.createTextMessage("Hello world!");
+
+            // ============== Enable encryption for this message ==============
+            message.setBooleanProperty("x-qpid-encrypt", true);
+            // ============== Configure recipients for encryption ==============
+            message.setStringProperty("x-qpid-encrypt-recipients", "CN=client1, OU=Qpid, O=Apache, C=US");
+
+            messageProducer.send(message);
+            session.commit();
+        }
+        finally {
+            connection.close();
+        }
+    }
+
+    private void runReceiverExample() throws Exception
+    {
+        Connection connection = createConnection("consumer1ConnectionFactory");
+        try {
+            connection.start();
+            Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
+            Destination destination = createDesination("myTestQueue");
+            MessageConsumer messageConsumer = session.createConsumer(destination);
+            Message message = messageConsumer.receive();
+            if (message instanceof TextMessage) {
+                // application logic
+                System.out.println(((TextMessage) message).getText());
+            } else if (message instanceof BytesMessage) {
+                // handle potential decryption failure
+                System.out.println("Potential decryption problem. Application not in list of intended recipients?");
+            }
+            session.commit();
+        }
+        finally {
+            connection.close();
+        }
+    }
+
+    ///////////////////////////////////////
+    // The following is boilerplate code //
+    ///////////////////////////////////////
+
+    private Connection createConnection(final String connectionFactoryName) throws JMSException, IOException, NamingException
+    {
+        try (InputStream resourceAsStream = this.getClass().getResourceAsStream("example.properties")) {
+            Properties properties = new Properties();
+            properties.load(resourceAsStream);
+            Context context = new InitialContext(properties);
+            ConnectionFactory connectionFactory = (ConnectionFactory) context.lookup(connectionFactoryName);
+            final Connection connection = connectionFactory.createConnection();
+            context.close();
+            return connection;
+        }
+    }
+
+    private Destination createDesination(String desinationJndiName) throws IOException, NamingException
+    {
+        try (InputStream resourceAsStream = this.getClass().getResourceAsStream("example.properties")) {
+            Properties properties = new Properties();
+            properties.load(resourceAsStream);
+            Context context = new InitialContext(properties);
+            Destination destination = (Destination) context.lookup(desinationJndiName);
+            context.close();
+            return destination;
+        }
+    }
+}
+                </programlisting>
+            </para>
+        </section>
+    </section>
 </chapter>
diff --git a/systests/src/test/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java b/systests/src/test/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java
index 57a48f2..7ee6fb1 100644
--- a/systests/src/test/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java
+++ b/systests/src/test/java/org/apache/qpid/systest/rest/AuthenticationProviderRestTest.java
@@ -262,11 +262,12 @@
         try
         {
             principalDatabase = getDefaultBrokerConfiguration().createTemporaryPasswordFile(new String[]{"admin2", "guest2", "test2"});
-            attributes = new HashMap<String, Object>();
+            attributes = new HashMap<>();
             attributes.put(AuthenticationProvider.NAME, providerName);
             attributes.put(AuthenticationProvider.ID, id);
             attributes.put(AuthenticationProvider.TYPE, PlainPasswordDatabaseAuthenticationManager.PROVIDER_TYPE);
-            attributes.put(ExternalFileBasedAuthenticationManager.PATH, principalDatabase.getAbsolutePath());
+
+            file.createNewFile();
 
             int status = getRestTestHelper().submitRequest("authenticationprovider/" + providerName, "PUT", attributes);
             assertEquals("ACL was not deleted", 200, status);
@@ -274,7 +275,7 @@
             provider = getRestTestHelper().getJsonAsSingletonList("authenticationprovider/" + providerName);
             assertEquals("Unexpected id", id.toString(), provider.get(AuthenticationProvider.ID));
             assertEquals("Unexpected name", providerName, provider.get(AuthenticationProvider.NAME));
-            assertEquals("Unexpected path", principalDatabase.getAbsolutePath() , provider.get(
+            assertEquals("Unexpected path", file.getAbsolutePath() , provider.get(
                     ExternalFileBasedAuthenticationManager.PATH));
             assertEquals("Unexpected state", State.ACTIVE.name() , provider.get(AuthenticationProvider.STATE));
         }
diff --git a/systests/src/test/java/org/apache/qpid/systest/rest/MessagesRestTest.java b/systests/src/test/java/org/apache/qpid/systest/rest/MessagesRestTest.java
index 037bd15..4f3ec17 100644
--- a/systests/src/test/java/org/apache/qpid/systest/rest/MessagesRestTest.java
+++ b/systests/src/test/java/org/apache/qpid/systest/rest/MessagesRestTest.java
@@ -30,6 +30,7 @@
 import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
+import javax.jms.BytesMessage;
 import javax.jms.Connection;
 import javax.jms.DeliveryMode;
 import javax.jms.Destination;
@@ -37,6 +38,7 @@
 import javax.jms.Message;
 import javax.jms.MessageProducer;
 import javax.jms.Session;
+import javax.jms.StreamMessage;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.qpid.jms.ListMessage;
@@ -51,9 +53,13 @@
      * Message number to publish into queue
      */
     private static final int MESSAGE_NUMBER = 12;
-    public static final String STRING_PROP = "shortstring";
+    private static final String STRING_PROP = "shortstring";
     // Dollar Pound Euro: 1 byte, 2 byte, and 3 byte UTF-8 encodings respectively
-    public static final String STRING_VALUE = "\u0024 \u00A3 \u20AC";
+    private static final String STRING_VALUE = "\u0024 \u00A3 \u20AC";
+    private static final String GET_MESSAGE_CONTENT_BY_ID =
+            "queue/test/test/%s/getMessageContent?returnJson=%s&messageId=%d";
+    private static final String GET_MESSAGE_INFO_BY_ID = "queue/test/test/%s/getMessageInfoById?messageId=%d";
+    private static final String GET_MESSAGE_INFO = "queue/test/test/%s/getMessageInfo";
 
     private Connection _connection;
     private Session _session;
@@ -61,6 +67,7 @@
     private long _startTime;
     private long _ttl;
 
+    @Override
     public void setUp() throws Exception
     {
         super.setUp();
@@ -97,13 +104,13 @@
         getDefaultBrokerConfiguration().setObjectAttribute(Port.class, TestBrokerConfiguration.ENTRY_NAME_HTTP_PORT,
                                                            HttpPort.ALLOW_CONFIDENTIAL_OPERATIONS_ON_INSECURE_CHANNELS,
                                                            true);
-
     }
 
     public void testGet() throws Exception
     {
         String queueName = getTestQueueName();
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
         int position = 0;
@@ -127,16 +134,21 @@
         // get message IDs
         Long lastMessageId = getLastMessageIdAndVerifyMimeType(queueName, "text/plain");
 
-        Map<String, Object> message = getRestTestHelper().getJsonAsMap("queue/test/test/" + queueName + "/getMessageInfoById?messageId=" + lastMessageId);
+        Map<String, Object> message = getRestTestHelper().getJsonAsMap(String.format(GET_MESSAGE_INFO_BY_ID,
+                                                                                     queueName,
+                                                                                     lastMessageId));
         @SuppressWarnings("unchecked")
         Map<String, Object> messageHeader = (Map<String, Object>) message.get("headers");
         assertNotNull("Message headers are not found", messageHeader);
         assertEquals("Unexpected message header value", STRING_VALUE, messageHeader.get(STRING_PROP));
 
         // get content
-        byte[] data = getRestTestHelper().getBytes("queue/test/test/" + queueName + "/getMessageContent?messageId=" + lastMessageId);
-        assertTrue("Unexpected message for id " + lastMessageId + ":" + data.length, Arrays.equals(STRING_VALUE.getBytes(StandardCharsets.UTF_8), data));
-
+        byte[] data = getRestTestHelper().getBytes(String.format(GET_MESSAGE_CONTENT_BY_ID,
+                                                                 queueName,
+                                                                 false,
+                                                                 lastMessageId));
+        assertTrue("Unexpected message for id " + lastMessageId + ":" + data.length,
+                   Arrays.equals(STRING_VALUE.getBytes(StandardCharsets.UTF_8), data));
     }
 
     public void testGetMapMessageContentAsJson() throws Exception
@@ -150,15 +162,62 @@
 
         Long lastMessageId = getLastMessageIdAndVerifyMimeType(queueName, "amqp/map");
 
-        Map<String, Object> jsonMessageData = getRestTestHelper().getJsonAsMap("queue/test/test/"
-                                                                               + queueName
-                                                                               + "/getMessageContent?returnJson=true&messageId="
-                                                                               + lastMessageId);
+        Map<String, Object> jsonMessageData = getRestTestHelper().getJsonAsMap(String.format(
+                GET_MESSAGE_CONTENT_BY_ID,
+                queueName,
+                true,
+                lastMessageId));
         assertEquals("Unexpected map content size", 2, jsonMessageData.size());
         assertEquals("Unexpected testStringProperty", "My String", jsonMessageData.get("testStringProperty"));
         assertEquals("Unexpected testIntProperty", 999999, jsonMessageData.get("testIntProperty"));
     }
 
+    public void testGetStreamMessageContentAsJson() throws Exception
+    {
+        String queueName = getTestQueueName();
+        StreamMessage streamMessage = _session.createStreamMessage();
+        streamMessage.writeLong(Long.MAX_VALUE);
+        streamMessage.writeBoolean(true);
+        streamMessage.writeString("Hello world");
+        _producer.send(streamMessage);
+        _session.commit();
+
+        Long lastMessageId = getLastMessageIdAndVerifyMimeType(queueName, "jms/stream-message");
+
+        List<Object> jsonMessageData = getRestTestHelper().getJsonAsSimpleList(String.format(
+                GET_MESSAGE_CONTENT_BY_ID,
+                queueName,
+                true,
+                lastMessageId));
+        assertEquals("Unexpected list content size", 3, jsonMessageData.size());
+        assertEquals("Unexpected value at index 0", Long.MAX_VALUE, jsonMessageData.get(0));
+        assertEquals("Unexpected value at index 1", true, jsonMessageData.get(1));
+        assertEquals("Unexpected value at index 2", "Hello world", jsonMessageData.get(2));
+    }
+
+    public void testGetBytesMessageContentAsJson() throws Exception
+    {
+        String queueName = getTestQueueName();
+        BytesMessage bytesMessage = _session.createBytesMessage();
+        final byte[] payloadBytes = {1, 2, 3, 4};
+        bytesMessage.writeBytes(payloadBytes);
+        _producer.send(bytesMessage);
+        _session.commit();
+
+        Long lastMessageId = getLastMessageIdAndVerifyMimeType(queueName, "application/octet-stream");
+
+        List<Object> jsonMessageData = getRestTestHelper().getJsonAsSimpleList(String.format(
+                GET_MESSAGE_CONTENT_BY_ID,
+                queueName,
+                true,
+                lastMessageId));
+        assertEquals("Unexpected list content size", payloadBytes.length, jsonMessageData.size());
+        for(int i = 0; i < payloadBytes.length; i++)
+        {
+            assertEquals("Unexpected value at index " + i, ((Number)payloadBytes[i]).intValue(), jsonMessageData.get(i));
+        }
+    }
+
     public void testGetListMessageContentAsJson() throws Exception
     {
         String queueName = getTestQueueName();
@@ -170,13 +229,14 @@
 
         Long lastMessageId = getLastMessageIdAndVerifyMimeType(queueName, "amqp/list");
 
-        List<Object> jsonMessageData = getRestTestHelper().getJsonAsSimpleList("queue/test/test/"
-                                                                               + queueName
-                                                                               + "/getMessageContent?returnJson=true&messageId="
-                                                                               + lastMessageId);
-        assertEquals("Unexpected map content size", 2, jsonMessageData.size());
-        assertEquals("Unexpected value at index 1", "My String", jsonMessageData.get(1));
+        List<Object> jsonMessageData = getRestTestHelper().getJsonAsSimpleList(String.format(
+                GET_MESSAGE_CONTENT_BY_ID,
+                queueName,
+                true,
+                lastMessageId));
+        assertEquals("Unexpected list size", 2, jsonMessageData.size());
         assertEquals("Unexpected value at index 0", 999999, jsonMessageData.get(0));
+        assertEquals("Unexpected value at index 1", "My String", jsonMessageData.get(1));
     }
 
     public void testPostMoveMessages() throws Exception
@@ -203,11 +263,14 @@
         messagesData.put("messageIds", movedMessageIds);
         messagesData.put("destination", queueName2);
 
-
-        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/moveMessages", "POST", messagesData, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/moveMessages",
+                                          "POST",
+                                          messagesData,
+                                          HttpServletResponse.SC_OK);
 
         // check messages on target queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName2 + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName2));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", movedMessageIds.size(), messages.size());
         for (Long id : movedMessageIds)
@@ -217,7 +280,7 @@
         }
 
         // check messages on original queue
-        messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        messages = getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", ids.size(), messages.size());
         for (Long id : ids)
@@ -239,18 +302,20 @@
         Destination queue2 = _session.createQueue(queueName2);
         _session.createConsumer(queue2);
 
-
         // move messages
 
         Map<String, Object> messagesData = new HashMap<>();
         messagesData.put("selector", "index % 2 = 0");
         messagesData.put("destination", queueName2);
 
-
-        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/moveMessages", "POST", messagesData, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/moveMessages",
+                                          "POST",
+                                          messagesData,
+                                          HttpServletResponse.SC_OK);
 
         // check messages on target queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName2 + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName2));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", MESSAGE_NUMBER / 2, messages.size());
         final List<Long> movedMessageIds = getMesssageIds(queueName2);
@@ -262,7 +327,7 @@
         }
 
         // check messages on original queue
-        messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        messages = getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", MESSAGE_NUMBER / 2, messages.size());
 
@@ -271,7 +336,6 @@
             Map<String, Object> message = getRestTestHelper().find("id", id.intValue(), messages);
             assertMessageAttributes(message);
             assertMessageAttributeValues(message, false);
-
         }
         for (Long id : movedMessageIds)
         {
@@ -288,21 +352,22 @@
         Destination queue2 = _session.createQueue(queueName2);
         _session.createConsumer(queue2);
 
-
         // get message IDs
         List<Long> ids = getMesssageIds(queueName);
 
-
         // move messages
 
         Map<String, Object> messagesData = new HashMap<>();
         messagesData.put("destination", queueName2);
 
-
-        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/moveMessages", "POST", messagesData, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/moveMessages",
+                                          "POST",
+                                          messagesData,
+                                          HttpServletResponse.SC_OK);
 
         // check messages on target queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName2 + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName2));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
         final List<Long> movedMessageIds = getMesssageIds(queueName2);
@@ -313,10 +378,9 @@
         }
 
         // check messages on original queue
-        messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        messages = getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", 0, messages.size());
-
     }
 
 
@@ -343,10 +407,14 @@
         messagesData.put("messageIds", copyMessageIds);
         messagesData.put("destination", queueName2);
 
-        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/copyMessages", "POST", messagesData, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/copyMessages",
+                                          "POST",
+                                          messagesData,
+                                          HttpServletResponse.SC_OK);
 
         // check messages on target queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName2 + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName2));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", copyMessageIds.size(), messages.size());
         for (Long id : copyMessageIds)
@@ -356,7 +424,7 @@
         }
 
         // check messages on original queue
-        messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        messages = getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
         for (Long id : ids)
@@ -384,10 +452,14 @@
         messagesData.put("limit", 1);
         messagesData.put("destination", queueName2);
 
-        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/copyMessages", "POST", messagesData, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/copyMessages",
+                                          "POST",
+                                          messagesData,
+                                          HttpServletResponse.SC_OK);
 
         // check messages on target queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName2 + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName2));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", 1, messages.size());
         for (Long id : getMesssageIds(queueName2))
@@ -398,10 +470,9 @@
         }
 
         // check messages on original queue
-        messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        messages = getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", MESSAGE_NUMBER, messages.size());
-
     }
 
 
@@ -424,10 +495,14 @@
         // delete messages
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("messageIds", deleteMessageIds);
-        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/deleteMessages", "POST", parameters, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/deleteMessages",
+                                          "POST",
+                                          parameters,
+                                          HttpServletResponse.SC_OK);
 
         // check messages on queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", ids.size(), messages.size());
         for (Long id : ids)
@@ -450,32 +525,35 @@
         List<Long> ids = getMesssageIds(queueName);
 
         // delete half of the messages
-        int deleteNumber = MESSAGE_NUMBER/2;
+        int deleteNumber = MESSAGE_NUMBER / 2;
 
         // delete messages
         Map<String, Object> parameters = new HashMap<>();
         parameters.put("limit", deleteNumber);
-        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/deleteMessages", "POST", parameters, HttpServletResponse.SC_OK);
+        getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/deleteMessages",
+                                          "POST",
+                                          parameters,
+                                          HttpServletResponse.SC_OK);
 
         // check messages on queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
-        assertEquals("Unexpected number of messages", MESSAGE_NUMBER/2, messages.size());
-
+        assertEquals("Unexpected number of messages", MESSAGE_NUMBER / 2, messages.size());
     }
 
 
-
     public void testClearQueue() throws Exception
     {
         String queueName = getTestQueueName();
 
         // clear queue
         getRestTestHelper().submitRequest("queue/test/test/" + queueName + "/clearQueue", "POST",
-                Collections.<String, Object>emptyMap(), HttpServletResponse.SC_OK);
+                                          Collections.<String, Object>emptyMap(), HttpServletResponse.SC_OK);
 
         // check messages on queue
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         assertNotNull("Messages are not found", messages);
         assertEquals("Unexpected number of messages", 0, messages.size());
     }
@@ -483,7 +561,8 @@
 
     private List<Long> getMesssageIds(String queueName) throws IOException
     {
-        List<Map<String, Object>> messages = getRestTestHelper().getJsonAsList("queue/test/test/" + queueName + "/getMessageInfo");
+        List<Map<String, Object>> messages =
+                getRestTestHelper().getJsonAsList(String.format(GET_MESSAGE_INFO, queueName));
         List<Long> ids = new ArrayList<>();
         for (Map<String, Object> message : messages)
         {
@@ -512,7 +591,7 @@
         else
         {
             assertEquals("Unexpected message attribute expirationTime", ((Number) message.get("timestamp")).longValue()
-                    + _ttl, message.get("expirationTime"));
+                                                                        + _ttl, message.get("expirationTime"));
             assertEquals("Unexpected message attribute priority", 5, message.get("priority"));
             assertEquals("Unexpected message attribute persistent", Boolean.FALSE, message.get("persistent"));
         }
@@ -530,7 +609,8 @@
         assertNotNull("Unexpected message attribute id", message.get("id"));
         assertNotNull("Message arrivalTime cannot be null", message.get("arrivalTime"));
         assertNotNull("Message timestamp cannot be null", message.get("timestamp"));
-        assertTrue("Message arrivalTime cannot be null", ((Number) message.get("arrivalTime")).longValue() > _startTime);
+        assertTrue("Message arrivalTime cannot be null",
+                   ((Number) message.get("arrivalTime")).longValue() > _startTime);
         assertNotNull("Message messageId cannot be null", message.get("messageId"));
         assertNotNull("Unexpected message attribute mimeType", message.get("mimeType"));
         assertNotNull("Unexpected message attribute userId", message.get("userId"));
diff --git a/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java b/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
index 9a58115..9a0362e 100644
--- a/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
+++ b/systests/src/test/java/org/apache/qpid/systest/rest/acl/BrokerACLTest.java
@@ -43,6 +43,7 @@
 import org.apache.qpid.server.model.KeyStore;
 import org.apache.qpid.server.model.Port;
 import org.apache.qpid.server.model.Protocol;
+import org.apache.qpid.server.model.State;
 import org.apache.qpid.server.model.TrustStore;
 import org.apache.qpid.server.model.adapter.FileBasedGroupProvider;
 import org.apache.qpid.server.model.adapter.FileBasedGroupProviderImpl;
@@ -154,13 +155,10 @@
 
         assertAuthenticationProviderExists(providerName);
 
-        File file = TestFileUtils.createTempFile(this, ".users", "guest:guest\n" + ALLOWED_USER + ":" + ALLOWED_USER + "\n"
-                + DENIED_USER + ":" + DENIED_USER);
-
-        Map<String, Object> attributes = new HashMap<String, Object>();
+        Map<String, Object> attributes = new HashMap<>();
         attributes.put(AuthenticationProvider.NAME, providerName);
         attributes.put(AuthenticationProvider.TYPE, PlainPasswordDatabaseAuthenticationManager.PROVIDER_TYPE);
-        attributes.put(ExternalFileBasedAuthenticationManager.PATH, file.getAbsolutePath());
+        attributes.put(AuthenticationProvider.STATE, State.DELETED.name());
 
         int responseCode = getRestTestHelper().submitRequest("authenticationprovider/" + providerName, "PUT", attributes);
         assertEquals("Setting of provider attribites should be allowed", 200, responseCode);
diff --git a/tools/src/main/java/org/apache/qpid/tools/RestStressTestClient.java b/tools/src/main/java/org/apache/qpid/tools/RestStressTestClient.java
index cfc7457..510b328 100644
--- a/tools/src/main/java/org/apache/qpid/tools/RestStressTestClient.java
+++ b/tools/src/main/java/org/apache/qpid/tools/RestStressTestClient.java
@@ -20,10 +20,6 @@
  */
 package org.apache.qpid.tools;
 
-import javax.crypto.Mac;
-import javax.crypto.spec.SecretKeySpec;
-import javax.xml.bind.DatatypeConverter;
-
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
@@ -41,10 +37,15 @@
 import java.util.Map;
 import java.util.Set;
 
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
+
 import com.fasterxml.jackson.core.type.TypeReference;
 import com.fasterxml.jackson.databind.ObjectMapper;
 
 import org.apache.qpid.tools.util.ArgumentsParser;
+import org.apache.qpid.util.Strings;
 
 public class RestStressTestClient
 {
@@ -463,7 +464,7 @@
         {
             try
             {
-                byte[] challengeBytes = DatatypeConverter.parseBase64Binary(challenge);
+                byte[] challengeBytes = Strings.decodeBase64(challenge);
 
                 String macAlgorithm = "HmacMD5";
                 Mac mac = Mac.getInstance(macAlgorithm);