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