You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by rg...@apache.org on 2015/06/12 03:41:42 UTC
svn commit: r1685015 - in /qpid/java/trunk:
broker-codegen/src/main/java/org/apache/qpid/server/model/validation/
broker-codegen/src/main/resources/META-INF/services/
broker-core/src/main/java/org/apache/qpid/server/model/
broker-core/src/main/java/org...
Author: rgodfrey
Date: Fri Jun 12 01:41:41 2015
New Revision: 1685015
URL: http://svn.apache.org/r1685015
Log:
QPID-6586 : [Java Broker] Allow configured objects to define "ManagedOperations" and expose these through the REST api
Added:
qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/OperationAnnotationValidator.java
- copied, changed from r1684834, qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/AttributeAnnotationValidator.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectOperation.java (with props)
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedOperation.java
- copied, changed from r1684834, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedAttribute.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Param.java (with props)
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/ClearQueueTransaction.java (with props)
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/CopyMessagesTransaction.java (with props)
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/DeleteMessagesTransaction.java (with props)
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/MoveMessagesTransaction.java (with props)
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryTransaction.java (with props)
Modified:
qpid/java/trunk/broker-codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
Copied: qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/OperationAnnotationValidator.java (from r1684834, qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/AttributeAnnotationValidator.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/OperationAnnotationValidator.java?p2=qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/OperationAnnotationValidator.java&p1=qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/AttributeAnnotationValidator.java&r1=1684834&r2=1685015&rev=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/AttributeAnnotationValidator.java (original)
+++ qpid/java/trunk/broker-codegen/src/main/java/org/apache/qpid/server/model/validation/OperationAnnotationValidator.java Fri Jun 12 01:41:41 2015
@@ -23,6 +23,7 @@ package org.apache.qpid.server.model.val
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
@@ -31,10 +32,12 @@ import javax.annotation.processing.Round
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
@@ -43,19 +46,13 @@ import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
-@SupportedAnnotationTypes({AttributeAnnotationValidator.MANAGED_ATTRIBUTE_CLASS_NAME,
- AttributeAnnotationValidator.DERIVED_ATTRIBUTE_CLASS_NAME,
- AttributeAnnotationValidator.MANAGED_STATISTIC_CLASS_NAME})
-public class AttributeAnnotationValidator extends AbstractProcessor
+@SupportedAnnotationTypes({OperationAnnotationValidator.MANAGED_OPERATION_CLASS_NAME,
+ OperationAnnotationValidator.OPERATION_PARAM_CLASS_NAME})
+public class OperationAnnotationValidator extends AbstractProcessor
{
- public static final String MANAGED_ATTRIBUTE_CLASS_NAME = "org.apache.qpid.server.model.ManagedAttribute";
- public static final String DERIVED_ATTRIBUTE_CLASS_NAME = "org.apache.qpid.server.model.DerivedAttribute";
-
- public static final String MANAGED_STATISTIC_CLASS_NAME = "org.apache.qpid.server.model.ManagedStatistic";
-
-
-
+ public static final String MANAGED_OPERATION_CLASS_NAME = "org.apache.qpid.server.model.ManagedOperation";
+ public static final String OPERATION_PARAM_CLASS_NAME = "org.apache.qpid.server.model.Param";
private static final Set<TypeKind> VALID_PRIMITIVE_TYPES = new HashSet<>(Arrays.asList(TypeKind.BOOLEAN,
@@ -77,20 +74,8 @@ public class AttributeAnnotationValidato
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv)
{
- processAttributes(roundEnv, MANAGED_ATTRIBUTE_CLASS_NAME);
- processAttributes(roundEnv, DERIVED_ATTRIBUTE_CLASS_NAME);
-
- processStatistics(roundEnv, MANAGED_STATISTIC_CLASS_NAME);
-
- return false;
- }
-
- public void processAttributes(final RoundEnvironment roundEnv,
- String elementName)
- {
-
Elements elementUtils = processingEnv.getElementUtils();
- TypeElement annotationElement = elementUtils.getTypeElement(elementName);
+ TypeElement annotationElement = elementUtils.getTypeElement(MANAGED_OPERATION_CLASS_NAME);
for (Element e : roundEnv.getElementsAnnotatedWith(annotationElement))
{
@@ -99,121 +84,89 @@ public class AttributeAnnotationValidato
ExecutableElement methodElement = (ExecutableElement) e;
checkInterfaceExtendsConfiguredObject(annotationElement, methodElement);
- checkMethodTakesNoArgs(annotationElement, methodElement);
- checkMethodName(annotationElement, methodElement);
+ checkMethodArgsAreValid(annotationElement, methodElement);
checkMethodReturnType(annotationElement, methodElement);
- checkTypeAgreesWithName(annotationElement, methodElement);
- }
- }
-
- public void processStatistics(final RoundEnvironment roundEnv,
- String elementName)
- {
-
- Elements elementUtils = processingEnv.getElementUtils();
- TypeElement annotationElement = elementUtils.getTypeElement(elementName);
-
- for (Element e : roundEnv.getElementsAnnotatedWith(annotationElement))
- {
- checkAnnotationIsOnMethodInInterface(annotationElement, e);
-
- ExecutableElement methodElement = (ExecutableElement) e;
-
- checkInterfaceExtendsConfiguredObject(annotationElement, methodElement);
- checkMethodTakesNoArgs(annotationElement, methodElement);
- checkMethodName(annotationElement, methodElement);
- checkTypeAgreesWithName(annotationElement, methodElement);
- checkMethodReturnTypeIsNumber(annotationElement, methodElement);
-
- }
- }
-
- private void checkMethodReturnTypeIsNumber(final TypeElement annotationElement,
- final ExecutableElement methodElement)
- {
- Types typeUtils = processingEnv.getTypeUtils();
- Elements elementUtils = processingEnv.getElementUtils();
-
- TypeMirror numberType = elementUtils.getTypeElement("java.lang.Number").asType();
- if(!typeUtils.isAssignable(methodElement.getReturnType(),numberType))
- {
- processingEnv.getMessager()
- .printMessage(Diagnostic.Kind.ERROR,
- "@"
- + annotationElement.getSimpleName()
- + " return type does not extend Number: "
- + methodElement.getReturnType().toString(),
- methodElement
- );
- }
- }
-
- public void checkTypeAgreesWithName(final TypeElement annotationElement, final ExecutableElement methodElement)
- {
- Types typeUtils = processingEnv.getTypeUtils();
-
- String methodName = methodElement.getSimpleName().toString();
-
- if((methodName.startsWith("is") || methodName.startsWith("has"))
- && !(methodElement.getReturnType().getKind() == TypeKind.BOOLEAN
- || typeUtils.isSameType(typeUtils.boxedClass(typeUtils.getPrimitiveType(TypeKind.BOOLEAN)).asType(), methodElement.getReturnType())))
- {
- processingEnv.getMessager()
- .printMessage(Diagnostic.Kind.ERROR,
- "@"
- + annotationElement.getSimpleName()
- + " return type is not boolean or Boolean: "
- + methodElement.getReturnType().toString(),
- methodElement
- );
}
+ return false;
}
public void checkMethodReturnType(final TypeElement annotationElement, final ExecutableElement methodElement)
{
- if (!isValidType(methodElement.getReturnType()))
+ final TypeMirror returnType = methodElement.getReturnType();
+ if (!(returnType.getKind() == TypeKind.VOID || isValidType(returnType)))
{
processingEnv.getMessager()
.printMessage(Diagnostic.Kind.ERROR,
"@"
+ annotationElement.getSimpleName()
+ " cannot be applied to methods with return type "
- + methodElement.getReturnType().toString(),
+ + returnType.toString(),
methodElement
);
}
}
- public void checkMethodName(final TypeElement annotationElement, final ExecutableElement methodElement)
+ public void checkMethodArgsAreValid(final TypeElement annotationElement, final ExecutableElement methodElement)
{
- String methodName = methodElement.getSimpleName().toString();
+ Elements elementUtils = processingEnv.getElementUtils();
+ TypeElement paramElement = elementUtils.getTypeElement(OPERATION_PARAM_CLASS_NAME);
- if (methodName.length() < 3
- || (methodName.length() < 4 && !methodName.startsWith("is"))
- || !(methodName.startsWith("is") || methodName.startsWith("get") || methodName.startsWith("has")))
+ for (VariableElement varElem : methodElement.getParameters())
{
- processingEnv.getMessager()
- .printMessage(Diagnostic.Kind.ERROR,
- "@"
- + annotationElement.getSimpleName()
- + " can only be applied to methods which of the form getXXX(), isXXX() or hasXXX()",
- methodElement
- );
- }
- }
+ String name = varElem.getSimpleName().toString();
+ final List<? extends AnnotationMirror> annotationMirrors = varElem.getAnnotationMirrors();
+ AnnotationMirror paramAnnotation = null;
+ for(AnnotationMirror annotationMirror : annotationMirrors)
+ {
+ if(annotationMirror.getAnnotationType().asElement().equals(paramElement))
+ {
+ paramAnnotation = annotationMirror;
+ break;
+ }
+ }
+ if(paramAnnotation == null)
+ {
+ processingEnv.getMessager()
+ .printMessage(Diagnostic.Kind.ERROR,
+ "Argument " + name + " of " + methodElement.getSimpleName()
+ + " must be annotated with @"
+ + paramElement.getSimpleName()
+ + " or the method should not be annotated with @"
+ + annotationElement.getSimpleName()
+ );
+ }
+ else
+ {
+ String paramName = null;
- public void checkMethodTakesNoArgs(final TypeElement annotationElement, final ExecutableElement methodElement)
- {
- if (!methodElement.getParameters().isEmpty())
- {
- processingEnv.getMessager()
- .printMessage(Diagnostic.Kind.ERROR,
- "@"
- + annotationElement.getSimpleName()
- + " can only be applied to methods which take no parameters",
- methodElement
- );
+ for(Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : paramAnnotation.getElementValues().entrySet())
+ {
+ if(entry.getKey().getSimpleName().toString().equals("name"))
+ {
+ paramName = String.valueOf(entry.getValue().getValue());
+ }
+ }
+
+ if(!name.equals(paramName))
+ {
+ processingEnv.getMessager()
+ .printMessage(Diagnostic.Kind.ERROR,
+ "Argument " + name + " of " + methodElement.getSimpleName()
+ + " is annotated with @"
+ + paramElement.getSimpleName()
+ + "( name = \""
+ + paramName
+ + "\") the name must match the actual parameter name, i.e. it should read @"
+
+ + paramElement.getSimpleName()
+ + "( name = \""
+ + name
+ + "\")"
+ );
+ }
+
+ }
}
}
@@ -254,104 +207,7 @@ public class AttributeAnnotationValidato
boolean isValidType(final TypeMirror type)
{
- return isValidType(processingEnv, type);
- }
-
- static boolean isValidType(ProcessingEnvironment processingEnv,
- final TypeMirror type)
- {
- Types typeUtils = processingEnv.getTypeUtils();
- Elements elementUtils = processingEnv.getElementUtils();
- Element typeElement = typeUtils.asElement(type);
-
- if (VALID_PRIMITIVE_TYPES.contains(type.getKind()))
- {
- return true;
- }
- for(TypeKind primitive : VALID_PRIMITIVE_TYPES)
- {
- if(typeUtils.isSameType(type, typeUtils.boxedClass(typeUtils.getPrimitiveType(primitive)).asType()))
- {
- return true;
- }
- }
- if(typeElement.getKind()==ElementKind.ENUM)
- {
- return true;
- }
-
- String className = "org.apache.qpid.server.model.ConfiguredObject";
- TypeMirror configuredObjectType = getErasure(processingEnv, className);
-
- if(typeUtils.isAssignable(typeUtils.erasure(type), configuredObjectType))
- {
- return true;
- }
-
- final TypeElement managedAttributeTypeValueElement =
- elementUtils.getTypeElement(ManagedAttributeValueTypeValidator.MANAGED_ATTRIBUTE_VALUE_TYPE_CLASS_NAME);
- for(AnnotationMirror annotation : typeElement.getAnnotationMirrors())
- {
- if(annotation.getAnnotationType().asElement().equals(managedAttributeTypeValueElement))
- {
- return true;
- }
- }
- if(typeUtils.isSameType(type,elementUtils.getTypeElement("java.lang.Object").asType()))
- {
- return true;
- }
-
-
- if(typeUtils.isSameType(type, elementUtils.getTypeElement("java.lang.String").asType()))
- {
- return true;
- }
-
-
- if(typeUtils.isSameType(type,elementUtils.getTypeElement("java.util.UUID").asType()))
- {
- return true;
- }
-
-
- if(typeUtils.isSameType(type,elementUtils.getTypeElement("java.security.cert.Certificate").asType()))
- {
- return true;
- }
-
- TypeMirror erasedType = typeUtils.erasure(type);
- if(typeUtils.isSameType(erasedType, getErasure(processingEnv, "java.util.List"))
- || typeUtils.isSameType(erasedType, getErasure(processingEnv, "java.util.Set"))
- || typeUtils.isSameType(erasedType, getErasure(processingEnv, "java.util.Collection")))
- {
-
-
- for(TypeMirror paramType : ((DeclaredType)type).getTypeArguments())
- {
-
- if(!isValidType(processingEnv, paramType))
- {
- return false;
- }
- }
- return true;
- }
-
- if(typeUtils.isSameType(erasedType, getErasure(processingEnv, "java.util.Map")))
- {
- List<? extends TypeMirror> args = ((DeclaredType) type).getTypeArguments();
- if (args.size() != 2)
- {
- throw new IllegalArgumentException("Map types " + type + " must have exactly two type arguments");
- }
- return isValidType(processingEnv, args.get(0))
- && (isValidType(processingEnv, args.get(1))
- || typeUtils.isSameType(args.get(1), getErasure(processingEnv, "java.lang.Object")));
- }
-
-
- return false;
+ return AttributeAnnotationValidator.isValidType(processingEnv, type);
}
private TypeMirror getErasure(final String className)
Modified: qpid/java/trunk/broker-codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor?rev=1685015&r1=1685014&r2=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor (original)
+++ qpid/java/trunk/broker-codegen/src/main/resources/META-INF/services/javax.annotation.processing.Processor Fri Jun 12 01:41:41 2015
@@ -23,3 +23,4 @@ org.apache.qpid.server.model.ConfiguredO
org.apache.qpid.server.model.validation.AttributeAnnotationValidator
org.apache.qpid.server.model.validation.AttributeFieldValidation
org.apache.qpid.server.model.validation.ManagedAnnotationValidator
+org.apache.qpid.server.model.validation.OperationAnnotationValidator
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectOperation.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectOperation.java?rev=1685015&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectOperation.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectOperation.java Fri Jun 12 01:41:41 2015
@@ -0,0 +1,153 @@
+/*
+ *
+ * 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.model;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.util.ServerScopedRuntimeException;
+
+public class ConfiguredObjectOperation<C extends ConfiguredObject>
+{
+ private final Method _operation;
+ private final Param[] _params;
+ private final Set<String> _validNames;
+
+ public ConfiguredObjectOperation(Class<C> clazz,
+ final Method operation)
+ {
+ _operation = operation;
+ final Annotation[][] allParameterAnnotations = _operation.getParameterAnnotations();
+ _params = new Param[allParameterAnnotations.length];
+ Set<String> validNames = new LinkedHashSet<>();
+ for(int i = 0; i < allParameterAnnotations.length; i++)
+ {
+ final Annotation[] parameterAnnotations = allParameterAnnotations[i];
+ for(Annotation annotation : parameterAnnotations)
+ {
+ if(annotation instanceof Param)
+ {
+ _params[i] = (Param) annotation;
+ validNames.add(_params[i].name());
+ }
+ }
+ if(_params[i] == null)
+ {
+ throw new IllegalArgumentException("Parameter doesn't have a @Param annotation");
+ }
+ }
+ _validNames = Collections.unmodifiableSet(validNames);
+ }
+
+ public String getName()
+ {
+ return _operation.getName();
+ }
+
+ public Object perform(C subject, Map<String, Object> parameters)
+ {
+ Set<String> providedNames = new HashSet<>(parameters.keySet());
+ providedNames.removeAll(_validNames);
+ if(!providedNames.isEmpty())
+ {
+ throw new IllegalArgumentException("Parameters " + providedNames + " are not accepted by " + getName());
+ }
+ Object[] paramValues = new Object[_params.length];
+ for(int i = 0; i <_params.length; i++)
+ {
+ Param param = _params[i];
+ Object providedVal;
+ if(parameters.containsKey(param.name()))
+ {
+ providedVal = parameters.get(param.name());
+ }
+ else if(!"".equals(param.defaultValue()))
+ {
+ providedVal = param.defaultValue();
+ }
+ else
+ {
+ providedVal = null;
+ }
+ final AttributeValueConverter<?> converter =
+ AttributeValueConverter.getConverter(_operation.getParameterTypes()[i],
+ _operation.getGenericParameterTypes()[i]);
+ final Object convertedVal = converter.convert(providedVal, subject);
+ paramValues[i] = convertedVal;
+ }
+ try
+ {
+ return _operation.invoke(subject, paramValues);
+ }
+ catch (IllegalAccessException e)
+ {
+ throw new ServerScopedRuntimeException(e);
+ }
+ catch (InvocationTargetException e)
+ {
+ if(e.getCause() instanceof RuntimeException)
+ {
+ throw (RuntimeException) e.getCause();
+ }
+ else if(e.getCause() instanceof Error)
+ {
+ throw (Error) e.getCause();
+ }
+ else
+ {
+ throw new ServerScopedRuntimeException(e);
+ }
+ }
+ }
+
+ public boolean hasSameParameters(final ConfiguredObjectOperation<?> other)
+ {
+ if(_params.length == other._params.length)
+ {
+ for(int i = 0; i < _params.length; i++)
+ {
+ if(!_params[i].name().equals(other._params[i].name()))
+ {
+ return false;
+ }
+ if(!_operation.getParameterTypes()[i].equals(other._operation.getParameterTypes()[i]))
+ {
+ return false;
+ }
+ if(!_operation.getGenericParameterTypes()[i].equals(other._operation.getGenericParameterTypes()[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectOperation.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java?rev=1685015&r1=1685014&r2=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ConfiguredObjectTypeRegistry.java Fri Jun 12 01:41:41 2015
@@ -181,6 +181,10 @@ public class ConfiguredObjectTypeRegistr
private final Map<Class<? extends ConfiguredObject>,Set<Class<? extends ManagedInterface>>> _allManagedInterfaces =
Collections.synchronizedMap(new HashMap<Class<? extends ConfiguredObject>, Set<Class<? extends ManagedInterface>>>());
+ private final Map<Class<? extends ConfiguredObject>,Set<ConfiguredObjectOperation<?>>> _allOperations =
+ Collections.synchronizedMap(new HashMap<Class<? extends ConfiguredObject>, Set<ConfiguredObjectOperation<?>>>());
+
+
private final Map<Class<? extends ConfiguredObject>, Map<String, Collection<String>>> _validChildTypes =
Collections.synchronizedMap(new HashMap<Class<? extends ConfiguredObject>, Map<String, Collection<String>>>());
@@ -566,10 +570,12 @@ public class ConfiguredObjectTypeRegistr
final SortedSet<ConfiguredObjectAttribute<?, ?>> attributeSet = new TreeSet<>(OBJECT_NAME_COMPARATOR);
final SortedSet<ConfiguredObjectStatistic<?, ?>> statisticSet = new TreeSet<>(OBJECT_NAME_COMPARATOR);
final Set<Class<? extends ManagedInterface>> managedInterfaces = new HashSet<>();
+ final Set<ConfiguredObjectOperation<?>> operationsSet = new HashSet<>();
_allAttributes.put(clazz, attributeSet);
_allStatistics.put(clazz, statisticSet);
_allManagedInterfaces.put(clazz, managedInterfaces);
+ _allOperations.put(clazz, operationsSet);
doWithAllParents(clazz, new Action<Class<? extends ConfiguredObject>>()
{
@@ -579,12 +585,13 @@ public class ConfiguredObjectTypeRegistr
initialiseWithParentAttributes(attributeSet,
statisticSet,
managedInterfaces,
+ operationsSet,
parent);
}
});
- processMethods(clazz, attributeSet, statisticSet);
+ processMethods(clazz, attributeSet, statisticSet, operationsSet);
processAttributesTypesAndFields(clazz);
@@ -614,17 +621,19 @@ public class ConfiguredObjectTypeRegistr
private <X extends ConfiguredObject> void processMethods(final Class<X> clazz,
final SortedSet<ConfiguredObjectAttribute<?, ?>> attributeSet,
- final SortedSet<ConfiguredObjectStatistic<?, ?>> statisticSet)
+ final SortedSet<ConfiguredObjectStatistic<?, ?>> statisticSet,
+ final Set<ConfiguredObjectOperation<?>> operationsSet)
{
for(Method method : clazz.getDeclaredMethods())
{
- processMethod(clazz, attributeSet, statisticSet, method);
+ processMethod(clazz, attributeSet, statisticSet, operationsSet, method);
}
}
private <X extends ConfiguredObject> void processMethod(final Class<X> clazz,
final SortedSet<ConfiguredObjectAttribute<?, ?>> attributeSet,
final SortedSet<ConfiguredObjectStatistic<?, ?>> statisticSet,
+ final Set<ConfiguredObjectOperation<?>> operationsSet,
final Method m)
{
if(m.isAnnotationPresent(ManagedAttribute.class))
@@ -640,6 +649,10 @@ public class ConfiguredObjectTypeRegistr
{
processManagedStatistic(clazz, statisticSet, m);
}
+ else if(m.isAnnotationPresent(ManagedOperation.class))
+ {
+ processManagedOperation(clazz, operationsSet, m);
+ }
}
private <X extends ConfiguredObject> void processManagedStatistic(final Class<X> clazz,
@@ -697,14 +710,47 @@ public class ConfiguredObjectTypeRegistr
attributeSet.add(attribute);
}
+ private <X extends ConfiguredObject> void processManagedOperation(final Class<X> clazz,
+ final Set<ConfiguredObjectOperation<?>> operationSet,
+ final Method m)
+ {
+ ManagedOperation annotation = m.getAnnotation(ManagedOperation.class);
+
+ if(!clazz.isInterface() || !ConfiguredObject.class.isAssignableFrom(clazz))
+ {
+ throw new ServerScopedRuntimeException("Can only define ManagedOperations on interfaces which extend " + ConfiguredObject.class.getSimpleName() + ". " + clazz.getSimpleName() + " does not meet these criteria.");
+ }
+
+ ConfiguredObjectOperation<?> operation = new ConfiguredObjectOperation<>(clazz, m);
+ Iterator<ConfiguredObjectOperation<?>> iter = operationSet.iterator();
+ while(iter.hasNext())
+ {
+ final ConfiguredObjectOperation<?> existingOperation = iter.next();
+ if(operation.getName().equals(existingOperation.getName()))
+ {
+ if(!operation.hasSameParameters(existingOperation))
+ {
+ throw new IllegalArgumentException("Cannot redefine the operation " + operation.getName() + " with different parameters in " + clazz.getSimpleName());
+ }
+ iter.remove();
+ break;
+ }
+ }
+ operationSet.add(operation);
+ }
+
+
+
private void initialiseWithParentAttributes(final SortedSet<ConfiguredObjectAttribute<?, ?>> attributeSet,
final SortedSet<ConfiguredObjectStatistic<?, ?>> statisticSet,
final Set<Class<? extends ManagedInterface>> managedInterfaces,
+ final Set<ConfiguredObjectOperation<?>> operationsSet,
final Class<? extends ConfiguredObject> parent)
{
attributeSet.addAll(_allAttributes.get(parent));
statisticSet.addAll(_allStatistics.get(parent));
managedInterfaces.addAll(_allManagedInterfaces.get(parent));
+ operationsSet.addAll(_allOperations.get(parent));
}
private <X extends ConfiguredObject> void processAttributesTypesAndFields(final Class<X> clazz)
@@ -975,6 +1021,24 @@ public class ConfiguredObjectTypeRegistr
return statistics;
}
+ public Map<String, ConfiguredObjectOperation<?>> getOperations(final Class<? extends ConfiguredObject> clazz)
+ {
+ processClassIfNecessary(clazz);
+ final Set<ConfiguredObjectOperation<?>> operations = _allOperations.get(clazz);
+ if(operations == null)
+ {
+ return Collections.emptyMap();
+ }
+ else
+ {
+ Map<String, ConfiguredObjectOperation<?>> returnVal = new HashMap<>();
+ for(ConfiguredObjectOperation<?> operation : operations)
+ {
+ returnVal.put(operation.getName(), operation);
+ }
+ return returnVal;
+ }
+ }
public Map<String, ConfiguredObjectAttribute<?, ?>> getAttributeTypes(final Class<? extends ConfiguredObject> clazz)
{
Copied: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedOperation.java (from r1684834, qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedAttribute.java)
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedOperation.java?p2=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedOperation.java&p1=qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedAttribute.java&r1=1684834&r2=1685015&rev=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedAttribute.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/ManagedOperation.java Fri Jun 12 01:41:41 2015
@@ -27,15 +27,7 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
-public @interface ManagedAttribute
+public @interface ManagedOperation
{
- boolean secure() default false;
- boolean mandatory() default false;
- boolean persist() default true;
- String defaultValue() default "";
String description() default "";
- String[] validValues() default {};
- boolean oversize() default false;
- String oversizedAltText() default "";
- String secureValueFilter() default "";
}
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Param.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Param.java?rev=1685015&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Param.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Param.java Fri Jun 12 01:41:41 2015
@@ -0,0 +1,35 @@
+package org.apache.qpid.server.model;/*
+ *
+ * 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.
+ *
+ */
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.PARAMETER)
+public @interface Param
+{
+ String name();
+ String defaultValue() default "";
+ String description() default "";
+ String[] validValues() default {};
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Param.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java?rev=1685015&r1=1685014&r2=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/model/Queue.java Fri Jun 12 01:41:41 2015
@@ -232,5 +232,8 @@ public interface Queue<X extends Queue<X
@ManagedStatistic
long getOldestMessageAge();
+ @ManagedOperation
+ List<Long> moveMessages(@Param(name = "destination") Queue<?> destination, @Param(name = "messageIds") List<Long> messageIds);
+
}
Modified: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java?rev=1685015&r1=1685014&r2=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java (original)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/AbstractQueue.java Fri Jun 12 01:41:41 2015
@@ -3202,4 +3202,15 @@ public abstract class AbstractQueue<X ex
return _enqueueRecord;
}
}
+
+ @Override
+ public List<Long> moveMessages(Queue<?> destination, List<Long> messageIds)
+ {
+ List<Long> copy = new ArrayList<>(messageIds);
+ _virtualHost.executeTransaction(new MoveMessagesTransaction(this, copy, destination));
+ List<Long> returnVal = new ArrayList<>(messageIds);
+ returnVal.removeAll(copy);
+ return returnVal;
+
+ }
}
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/ClearQueueTransaction.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/ClearQueueTransaction.java?rev=1685015&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/ClearQueueTransaction.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/ClearQueueTransaction.java Fri Jun 12 01:41:41 2015
@@ -0,0 +1,54 @@
+/*
+ *
+ * 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.queue;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class ClearQueueTransaction implements VirtualHost.TransactionalOperation
+{
+ private final Queue _queue;
+
+ public ClearQueueTransaction(Queue queue)
+ {
+ _queue = queue;
+ }
+
+ @Override
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+ _queue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ txn.dequeue(entry);
+ }
+ return false;
+ }
+ });
+
+ }
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/ClearQueueTransaction.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/CopyMessagesTransaction.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/CopyMessagesTransaction.java?rev=1685015&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/CopyMessagesTransaction.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/CopyMessagesTransaction.java Fri Jun 12 01:41:41 2015
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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.queue;
+
+import java.util.List;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.store.TransactionLogResource;
+
+public class CopyMessagesTransaction extends QueueEntryTransaction
+{
+ private final Queue _destinationQueue;
+
+ public CopyMessagesTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
+ {
+ super(sourceQueue, messageIds);
+ _destinationQueue = destinationQueue;
+ }
+
+ @Override
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ ServerMessage msg = entry.getMessage();
+ if(msg != null && !msg.isReferenced((TransactionLogResource)_destinationQueue))
+ {
+ txn.copy(entry, _destinationQueue);
+ }
+ }
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/CopyMessagesTransaction.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/DeleteMessagesTransaction.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/DeleteMessagesTransaction.java?rev=1685015&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/DeleteMessagesTransaction.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/DeleteMessagesTransaction.java Fri Jun 12 01:41:41 2015
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.queue;
+
+import java.util.List;
+
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+
+public class DeleteMessagesTransaction extends QueueEntryTransaction
+{
+ public DeleteMessagesTransaction(Queue sourceQueue, List<Long> messageIds)
+ {
+ super(sourceQueue, messageIds);
+ }
+
+ @Override
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ txn.dequeue(entry);
+ }
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/DeleteMessagesTransaction.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/MoveMessagesTransaction.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/MoveMessagesTransaction.java?rev=1685015&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/MoveMessagesTransaction.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/MoveMessagesTransaction.java Fri Jun 12 01:41:41 2015
@@ -0,0 +1,49 @@
+/*
+ *
+ * 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.queue;
+
+import java.util.List;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.store.TransactionLogResource;
+
+public class MoveMessagesTransaction extends QueueEntryTransaction
+{
+ private final Queue _destinationQueue;
+
+ public MoveMessagesTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
+ {
+ super(sourceQueue, messageIds);
+ _destinationQueue = destinationQueue;
+ }
+
+ @Override
+ protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
+ {
+ ServerMessage msg = entry.getMessage();
+ if(msg != null && !msg.isReferenced((TransactionLogResource)_destinationQueue))
+ {
+ txn.move(entry, _destinationQueue);
+ }
+ }
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/MoveMessagesTransaction.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryTransaction.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryTransaction.java?rev=1685015&view=auto
==============================================================================
--- qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryTransaction.java (added)
+++ qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryTransaction.java Fri Jun 12 01:41:41 2015
@@ -0,0 +1,66 @@
+/*
+ *
+ * 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.queue;
+
+import java.util.List;
+
+import org.apache.qpid.server.message.ServerMessage;
+import org.apache.qpid.server.model.Queue;
+import org.apache.qpid.server.model.VirtualHost;
+
+abstract class QueueEntryTransaction implements VirtualHost.TransactionalOperation
+{
+ private final Queue _sourceQueue;
+ private final List _messageIds;
+
+ protected QueueEntryTransaction(Queue sourceQueue, List messageIds)
+ {
+ _sourceQueue = sourceQueue;
+ _messageIds = messageIds;
+ }
+
+ @Override
+ public void withinTransaction(final VirtualHost.Transaction txn)
+ {
+
+ _sourceQueue.visit(new QueueEntryVisitor()
+ {
+
+ public boolean visit(final QueueEntry entry)
+ {
+ final ServerMessage message = entry.getMessage();
+ if(message != null)
+ {
+ final long messageId = message.getMessageNumber();
+ if (_messageIds.remove(messageId) || (messageId <= (long) Integer.MAX_VALUE
+ && _messageIds.remove(Integer.valueOf((int)messageId))))
+ {
+ updateEntry(entry, txn);
+ }
+ }
+ return _messageIds.isEmpty();
+ }
+ });
+ }
+
+
+ protected abstract void updateEntry(QueueEntry entry, VirtualHost.Transaction txn);
+}
Propchange: qpid/java/trunk/broker-core/src/main/java/org/apache/qpid/server/queue/QueueEntryTransaction.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java?rev=1685015&r1=1685014&r2=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/MessageServlet.java Fri Jun 12 01:41:41 2015
@@ -42,11 +42,14 @@ import org.apache.qpid.server.message.Me
import org.apache.qpid.server.message.ServerMessage;
import org.apache.qpid.server.model.Queue;
import org.apache.qpid.server.model.VirtualHost;
+import org.apache.qpid.server.queue.ClearQueueTransaction;
+import org.apache.qpid.server.queue.CopyMessagesTransaction;
+import org.apache.qpid.server.queue.DeleteMessagesTransaction;
+import org.apache.qpid.server.queue.MoveMessagesTransaction;
import org.apache.qpid.server.queue.QueueEntry;
import org.apache.qpid.server.queue.QueueEntryVisitor;
import org.apache.qpid.server.security.SecurityManager;
import org.apache.qpid.server.security.access.Operation;
-import org.apache.qpid.server.store.TransactionLogResource;
public class MessageServlet extends AbstractServlet
{
@@ -168,130 +171,6 @@ public class MessageServlet extends Abst
return queue;
}
- private abstract static class QueueEntryTransaction implements VirtualHost.TransactionalOperation
- {
- private final Queue _sourceQueue;
- private final List _messageIds;
-
- protected QueueEntryTransaction(Queue sourceQueue, List messageIds)
- {
- _sourceQueue = sourceQueue;
- _messageIds = messageIds;
- }
-
- @Override
- public void withinTransaction(final VirtualHost.Transaction txn)
- {
-
- _sourceQueue.visit(new QueueEntryVisitor()
- {
-
- public boolean visit(final QueueEntry entry)
- {
- final ServerMessage message = entry.getMessage();
- if(message != null)
- {
- final long messageId = message.getMessageNumber();
- if (_messageIds.remove(messageId) || (messageId <= (long) Integer.MAX_VALUE
- && _messageIds.remove(Integer.valueOf((int)messageId))))
- {
- updateEntry(entry, txn);
- }
- }
- return _messageIds.isEmpty();
- }
- });
- }
-
-
- protected abstract void updateEntry(QueueEntry entry, VirtualHost.Transaction txn);
- }
-
- private static class MoveTransaction extends QueueEntryTransaction
- {
- private final Queue _destinationQueue;
-
- public MoveTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
- {
- super(sourceQueue, messageIds);
- _destinationQueue = destinationQueue;
- }
-
- @Override
- protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
- {
- ServerMessage msg = entry.getMessage();
- if(msg != null && !msg.isReferenced((TransactionLogResource)_destinationQueue))
- {
- txn.move(entry, _destinationQueue);
- }
- }
- }
-
- private static class CopyTransaction extends QueueEntryTransaction
- {
- private final Queue _destinationQueue;
-
- public CopyTransaction(Queue sourceQueue, List<Long> messageIds, Queue destinationQueue)
- {
- super(sourceQueue, messageIds);
- _destinationQueue = destinationQueue;
- }
-
- @Override
- protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
- {
- ServerMessage msg = entry.getMessage();
- if(msg != null && !msg.isReferenced((TransactionLogResource)_destinationQueue))
- {
- txn.copy(entry, _destinationQueue);
- }
- }
- }
-
- private static class DeleteTransaction extends QueueEntryTransaction
- {
- public DeleteTransaction(Queue sourceQueue, List<Long> messageIds)
- {
- super(sourceQueue, messageIds);
- }
-
- @Override
- protected void updateEntry(QueueEntry entry, VirtualHost.Transaction txn)
- {
- txn.dequeue(entry);
- }
- }
-
-
- private static class ClearQueueTransaction implements VirtualHost.TransactionalOperation
- {
- private final Queue _queue;
-
- protected ClearQueueTransaction(Queue queue)
- {
- _queue = queue;
- }
-
- @Override
- public void withinTransaction(final VirtualHost.Transaction txn)
- {
- _queue.visit(new QueueEntryVisitor()
- {
-
- public boolean visit(final QueueEntry entry)
- {
- final ServerMessage message = entry.getMessage();
- if(message != null)
- {
- txn.dequeue(entry);
- }
- return false;
- }
- });
-
- }
- }
private class MessageCollector implements QueueEntryVisitor
{
@@ -488,10 +367,10 @@ public class MessageServlet extends Abst
final Queue destinationQueue = getQueueFromVirtualHost(destQueueName, vhost);
final List<Long> messageIds = new ArrayList<Long>((List<Long>) providedObject.get("messages"));
- QueueEntryTransaction txn =
+ VirtualHost.TransactionalOperation txn =
isMoveTransaction
- ? new MoveTransaction(sourceQueue, messageIds, destinationQueue)
- : new CopyTransaction(sourceQueue, messageIds, destinationQueue);
+ ? new MoveMessagesTransaction(sourceQueue, messageIds, destinationQueue)
+ : new CopyMessagesTransaction(sourceQueue, messageIds, destinationQueue);
vhost.executeTransaction(txn);
response.setStatus(HttpServletResponse.SC_OK);
@@ -548,7 +427,7 @@ public class MessageServlet extends Abst
// FIXME: added temporary authorization check until we introduce management layer
// and review current ACL rules to have common rules for all management interfaces
authorizeMethod("deleteMessages", vhost);
- vhost.executeTransaction(new DeleteTransaction(queue, messageIds));
+ vhost.executeTransaction(new DeleteMessagesTransaction(queue, messageIds));
}
private void clearQueue(final Queue<?> queue, final VirtualHost<?, ?, ?> vhost)
Modified: qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java
URL: http://svn.apache.org/viewvc/qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java?rev=1685015&r1=1685014&r2=1685015&view=diff
==============================================================================
--- qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java (original)
+++ qpid/java/trunk/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/RestServlet.java Fri Jun 12 01:41:41 2015
@@ -38,9 +38,12 @@ import javax.servlet.http.HttpServletRes
import javax.servlet.http.Part;
import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.BrokerModel;
import org.apache.qpid.server.model.ConfiguredObjectJacksonModule;
+import org.apache.qpid.server.model.ConfiguredObjectOperation;
import org.apache.qpid.server.model.IllegalStateTransitionException;
import org.apache.qpid.server.model.IntegrityViolationException;
+import org.apache.qpid.server.model.Model;
import org.apache.qpid.server.virtualhost.ExchangeExistsException;
import org.apache.qpid.server.virtualhost.QueueExistsException;
import org.codehaus.jackson.map.ObjectMapper;
@@ -441,54 +444,108 @@ public class RestServlet extends Abstrac
List<String> names = getParentNamesFromServletPath(request);
Map<String, Object> providedObject = getRequestProvidedObject(request);
boolean isFullObjectURL = names.size() == _hierarchy.length;
- boolean updateOnlyAllowed = isFullObjectURL && "POST".equalsIgnoreCase(request.getMethod());
+ boolean isPostToFullURL = isFullObjectURL && "POST".equalsIgnoreCase(request.getMethod());
+ final String[] pathInfoElements = getPathInfoElements(request);
+ boolean isOperation = pathInfoElements != null && pathInfoElements.length == _hierarchy.length + 1;
try
{
- if (names.isEmpty() && _hierarchy.length == 0)
+ if(!isOperation)
{
- getBroker().setAttributes(providedObject);
- response.setStatus(HttpServletResponse.SC_OK);
- return;
- }
+ if (names.isEmpty() && _hierarchy.length == 0)
+ {
+ getBroker().setAttributes(providedObject);
+ response.setStatus(HttpServletResponse.SC_OK);
+ return;
+ }
- ConfiguredObject theParent = getBroker();
- ConfiguredObject[] otherParents = null;
- Class<? extends ConfiguredObject> objClass = getConfiguredClass();
- if (_hierarchy.length > 1)
- {
- List<ConfiguredObject> parents = findAllObjectParents(names);
- theParent = parents.remove(0);
- otherParents = parents.toArray(new ConfiguredObject[parents.size()]);
- }
- if (isFullObjectURL)
- {
- providedObject.put("name", names.get(names.size() - 1));
- ConfiguredObject<?> configuredObject = findObjectToUpdateInParent(objClass, providedObject, theParent, otherParents);
+ ConfiguredObject theParent = getBroker();
+ ConfiguredObject[] otherParents = null;
+ Class<? extends ConfiguredObject> objClass = getConfiguredClass();
+ if (_hierarchy.length > 1)
+ {
+ List<ConfiguredObject> parents = findAllObjectParents(names);
+ theParent = parents.remove(0);
+ otherParents = parents.toArray(new ConfiguredObject[parents.size()]);
+ }
- if (configuredObject != null)
+ if (isFullObjectURL)
{
- configuredObject.setAttributes(providedObject);
- response.setStatus(HttpServletResponse.SC_OK);
- return;
+ providedObject.put("name", names.get(names.size() - 1));
+ ConfiguredObject<?> configuredObject =
+ findObjectToUpdateInParent(objClass, providedObject, theParent, otherParents);
+
+ if (configuredObject != null)
+ {
+ configuredObject.setAttributes(providedObject);
+ response.setStatus(HttpServletResponse.SC_OK);
+ return;
+ }
+ else if (isPostToFullURL)
+ {
+ sendErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Object with "
+ + (providedObject.containsKey(
+ "id") ? " id '" + providedObject.get("id") : " name '" + providedObject.get("name"))
+ + "' does not exist!");
+ return;
+ }
}
- else if (updateOnlyAllowed)
+
+ ConfiguredObject<?> configuredObject = theParent.createChild(objClass, providedObject, otherParents);
+ StringBuffer requestURL = request.getRequestURL();
+ if (!isFullObjectURL)
{
- sendErrorResponse(request, response, HttpServletResponse.SC_NOT_FOUND, "Object with "
- + (providedObject.containsKey("id") ? " id '" + providedObject.get("id") : " name '" + providedObject.get("name"))
- + "' does not exist!");
- return;
+ requestURL.append("/").append(configuredObject.getName());
}
+ response.setHeader("Location", requestURL.toString());
+ response.setStatus(HttpServletResponse.SC_CREATED);
}
-
- ConfiguredObject<?> configuredObject = theParent.createChild(objClass, providedObject, otherParents);
- StringBuffer requestURL = request.getRequestURL();
- if (!isFullObjectURL)
+ else
{
- requestURL.append("/").append(configuredObject.getName());
+ if(isPostToFullURL)
+ {
+ ConfiguredObject<?> subject;
+ if (names.isEmpty() && _hierarchy.length == 0)
+ {
+ subject = getBroker();
+ }
+ else
+ {
+ ConfiguredObject theParent = getBroker();
+ ConfiguredObject[] otherParents = null;
+ Class<? extends ConfiguredObject> objClass = getConfiguredClass();
+ if (_hierarchy.length > 1)
+ {
+ List<ConfiguredObject> parents = findAllObjectParents(names);
+ theParent = parents.remove(0);
+ otherParents = parents.toArray(new ConfiguredObject[parents.size()]);
+ }
+
+ Map<String,Object> objectName = Collections.<String,Object>singletonMap("name", names.get(names.size() - 1));
+ subject = findObjectToUpdateInParent(objClass, objectName, theParent, otherParents);
+ String operationName = pathInfoElements[pathInfoElements.length-1];
+ final Map<String, ConfiguredObjectOperation<?>> availableOperations =
+ getBroker().getModel().getTypeRegistry().getOperations(subject.getClass());
+ ConfiguredObjectOperation operation = availableOperations.get(operationName);
+ if(operation == null)
+ {
+ throw new IllegalArgumentException("No such operation: " + operationName);
+ }
+ Object returnVal = operation.perform(subject, providedObject);
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("application/json");
+ Writer writer = getOutputWriter(request, response);
+ ObjectMapper mapper = ConfiguredObjectJacksonModule.newObjectMapper();
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.writeValue(writer, returnVal);
+
+ }
+ }
+ else
+ {
+ throw new IllegalArgumentException("Request path is not valid for this operation");
+ }
}
- response.setHeader("Location", requestURL.toString());
- response.setStatus(HttpServletResponse.SC_CREATED);
}
catch (RuntimeException e)
{
@@ -568,16 +625,27 @@ public class RestServlet extends Abstrac
if (!(pathInfoElements.length == _hierarchy.length ||
(_hierarchy.length > 0 && pathInfoElements.length == _hierarchy.length - 1)))
{
- throw new IllegalArgumentException("Either parent path or full object path must be specified on object creation."
- + " Full object path must be specified on object update. "
- + "Found "
- + names
- + " of size "
- + names.size()
- + " expecting "
- + _hierarchy.length);
+ if(pathInfoElements.length == _hierarchy.length + 1)
+ {
+ names.addAll(Arrays.asList(pathInfoElements).subList(0,pathInfoElements.length-1));
+ }
+ else
+ {
+ throw new IllegalArgumentException(
+ "Either parent path or full object path must be specified on object creation."
+ + " Full object path must be specified on object update. "
+ + "Found "
+ + names
+ + " of size "
+ + names.size()
+ + " expecting "
+ + _hierarchy.length);
+ }
+ }
+ else
+ {
+ names.addAll(Arrays.asList(pathInfoElements));
}
- names.addAll(Arrays.asList(pathInfoElements));
}
return names;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org