[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/<configured object category name></para>
+ <para>/api/<version>/querybroker/<configured object category name></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/<virtual host node name>/<virtual host name>/<configured object category name></para>
+ <para>/api/<version>/queryvhost/<virtual host node name>/<virtual host name>/<configured object category name></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&where=queueDepthBytes>0&orderBy=1 desc,2 desc&offset=0&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&where=queueDepthBytes>0&orderBy=1 desc,2 desc&offset=0&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 '<recipient>'</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": "<path_to_truststore>", "password": "<your_truststore_password>"}'
+ </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://<username>:<password>@?brokerlist='tcp://localhost:5672?encryption_remote_trust_store='$certificates%255c/clientcerts''
+connectionfactory.consumer1ConnectionFactory = amqp://<username>:<password>@?brokerlist='tcp://localhost:5672?encryption_key_store='path/to/client_1.jks'&encryption_key_store_password='<keystore_password>''
+connectionfactory.consumer2ConnectionFactory = amqp://<username>:<password>@?brokerlist='tcp://localhost:5672?encryption_key_store='path/to/client_2.jks'&encryption_key_store_password='<keystore_password>''
+
+# 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);