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/02/13 23:18:48 UTC

svn commit: r1659700 - /qpid/trunk/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java

Author: rgodfrey
Date: Fri Feb 13 22:18:48 2015
New Revision: 1659700

URL: http://svn.apache.org/r1659700
Log:
QPID-6338 : [Java AMQP 1.0 Client] validate sections in created Message

Modified:
    qpid/trunk/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java

Modified: qpid/trunk/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java
URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java?rev=1659700&r1=1659699&r2=1659700&view=diff
==============================================================================
--- qpid/trunk/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java (original)
+++ qpid/trunk/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java Fri Feb 13 22:18:48 2015
@@ -20,21 +20,89 @@
  */
 package org.apache.qpid.amqp_1_0.client;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
 import org.apache.qpid.amqp_1_0.type.Binary;
 import org.apache.qpid.amqp_1_0.type.DeliveryState;
 import org.apache.qpid.amqp_1_0.type.Section;
+import org.apache.qpid.amqp_1_0.type.messaging.AmqpSequence;
 import org.apache.qpid.amqp_1_0.type.messaging.AmqpValue;
 import org.apache.qpid.amqp_1_0.type.messaging.ApplicationProperties;
+import org.apache.qpid.amqp_1_0.type.messaging.Data;
+import org.apache.qpid.amqp_1_0.type.messaging.DeliveryAnnotations;
+import org.apache.qpid.amqp_1_0.type.messaging.Footer;
 import org.apache.qpid.amqp_1_0.type.messaging.Header;
+import org.apache.qpid.amqp_1_0.type.messaging.MessageAnnotations;
 import org.apache.qpid.amqp_1_0.type.messaging.Properties;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
 public class Message
 {
+
+    private static final Map<Class<? extends Section>, Collection<Class<? extends Section>>> VALID_NEXT_SECTIONS = new HashMap<>();
+
+    static
+    {
+        VALID_NEXT_SECTIONS.put(null, Arrays.asList(Header.class,
+                                                    DeliveryAnnotations.class,
+                                                    MessageAnnotations.class,
+                                                    Properties.class,
+                                                    ApplicationProperties.class,
+                                                    AmqpValue.class,
+                                                    AmqpSequence.class,
+                                                    Data.class));
+
+        VALID_NEXT_SECTIONS.put(Header.class, Arrays.asList(DeliveryAnnotations.class,
+                                                            MessageAnnotations.class,
+                                                            Properties.class,
+                                                            ApplicationProperties.class,
+                                                            AmqpValue.class,
+                                                            AmqpSequence.class,
+                                                            Data.class));
+
+        VALID_NEXT_SECTIONS.put(DeliveryAnnotations.class, Arrays.asList(MessageAnnotations.class,
+                                                                         Properties.class,
+                                                                         ApplicationProperties.class,
+                                                                         AmqpValue.class,
+                                                                         AmqpSequence.class,
+                                                                         Data.class));
+
+        VALID_NEXT_SECTIONS.put(MessageAnnotations.class, Arrays.asList(Properties.class,
+                                                                        ApplicationProperties.class,
+                                                                        AmqpValue.class,
+                                                                        AmqpSequence.class,
+                                                                        Data.class));
+
+        VALID_NEXT_SECTIONS.put(Properties.class, Arrays.asList(ApplicationProperties.class,
+                                                                AmqpValue.class,
+                                                                AmqpSequence.class,
+                                                                Data.class));
+
+
+        VALID_NEXT_SECTIONS.put(ApplicationProperties.class, Arrays.asList(AmqpValue.class,
+                                                                           AmqpSequence.class,
+                                                                           Data.class));
+
+        VALID_NEXT_SECTIONS.put(AmqpValue.class, Arrays.<Class<? extends Section>>asList(Footer.class, null));
+
+        VALID_NEXT_SECTIONS.put(AmqpSequence.class, Arrays.asList(AmqpSequence.class,
+                                                                  Footer.class, null));
+
+        VALID_NEXT_SECTIONS.put(Data.class, Arrays.asList(Data.class, Footer.class, null));
+
+        VALID_NEXT_SECTIONS.put(Footer.class, Collections.<Class<? extends Section>>singletonList(null));
+
+
+    }
+
+
     private Binary _deliveryTag;
     private List<Section> _payload = new ArrayList<Section>();
     private Boolean _resume;
@@ -49,7 +117,7 @@ public class Message
 
     public Message(Collection<Section> sections)
     {
-        _payload.addAll(sections);
+        _payload.addAll(validateOrReorder(sections));
     }
 
     public Message(Section section)
@@ -63,6 +131,105 @@ public class Message
     }
 
 
+    private static Collection<Section>  validateOrReorder(final Collection<Section> providedSections)
+    {
+        Collection<Section> validatedSections;
+        if(providedSections == null)
+        {
+            validatedSections = Collections.emptyList();
+        }
+        else if(isValidOrder(providedSections))
+        {
+            validatedSections = providedSections;
+        }
+        else
+        {
+            validatedSections = reorderSections(providedSections);
+        }
+        return validatedSections;
+    }
+
+    private static Collection<Section> reorderSections(final Collection<Section> providedSections)
+    {
+        Collection<Section> validSections = new ArrayList<>();
+        List<Section> originalSection = new ArrayList<>(providedSections);
+        validSections.addAll(getAndRemoveSections(Header.class, originalSection, false));
+        validSections.addAll(getAndRemoveSections(DeliveryAnnotations.class, originalSection, false));
+        validSections.addAll(getAndRemoveSections(MessageAnnotations.class, originalSection, false));
+        validSections.addAll(getAndRemoveSections(Properties.class, originalSection, false));
+        validSections.addAll(getAndRemoveSections(ApplicationProperties.class, originalSection, false));
+
+        final List<AmqpValue> valueSections = getAndRemoveSections(AmqpValue.class, originalSection, false);
+        final List<AmqpSequence> sequenceSections = getAndRemoveSections(AmqpSequence.class, originalSection, true);
+        final List<Data> dataSections = getAndRemoveSections(Data.class, originalSection, true);
+
+        if(valueSections.isEmpty() && sequenceSections.isEmpty() && dataSections.isEmpty())
+        {
+            throw new IllegalArgumentException("Message must contain one of Data, AmqpValue or AmqpSequence");
+        }
+        if((!valueSections.isEmpty() && (!sequenceSections.isEmpty() || !dataSections.isEmpty()))
+                || (!sequenceSections.isEmpty() && !dataSections.isEmpty()))
+        {
+            throw new IllegalArgumentException("Only one type of content Data, AmqpValue or AmqpSequence can be used");
+        }
+        validSections.addAll(valueSections);
+        validSections.addAll(sequenceSections);
+        validSections.addAll(dataSections);
+
+        validSections.addAll(getAndRemoveSections(Footer.class, originalSection, false));
+
+        if(!originalSection.isEmpty())
+        {
+            throw new IllegalArgumentException("Invalid section type: " + originalSection.get(0).getClass().getName());
+        }
+        return validSections;
+    }
+
+    private static <T extends Section> List<T> getAndRemoveSections(Class<T> clazz,
+                                                                    List<Section> sections,
+                                                                    boolean allowMultiple)
+    {
+        List<T> desiredSections = new ArrayList<>();
+        ListIterator<Section> iterator = sections.listIterator();
+        while(iterator.hasNext())
+        {
+            Section s = iterator.next();
+            if(s.getClass() == clazz)
+            {
+                desiredSections.add((T)s);
+                iterator.remove();
+            }
+        }
+        if(desiredSections.size() > 1 && !allowMultiple)
+        {
+            throw new IllegalArgumentException("Multiple " + clazz.getSimpleName() + " sections are not allowed");
+        }
+        return desiredSections;
+    }
+
+    private static boolean isValidOrder(final Collection<Section> providedSections)
+    {
+        Class<? extends Section> previousSection = null;
+        final Iterator<? extends Section> it = providedSections.iterator();
+        while(it.hasNext())
+        {
+            Collection<Class<? extends Section>> validSections = VALID_NEXT_SECTIONS.get(previousSection);
+            Class<? extends Section> sectionClass = it.next().getClass();
+            if(validSections == null || !validSections.contains(sectionClass))
+            {
+                return false;
+            }
+            else
+            {
+                previousSection = sectionClass;
+            }
+        }
+        Collection<Class<? extends Section>> validSections = VALID_NEXT_SECTIONS.get(previousSection);
+        return validSections != null && validSections.contains(null);
+    }
+
+
+
     public Binary getDeliveryTag()
     {
         return _deliveryTag;



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org