summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Godfrey <rgodfrey@apache.org>2015-02-13 22:18:48 +0000
committerRobert Godfrey <rgodfrey@apache.org>2015-02-13 22:18:48 +0000
commit6b17c57341c1b822d7f888e76aae1104f1599795 (patch)
tree3a2c935c1c6085e4ff6eb47c2782e0bad8f24ff9
parent928fed665a842440179db42ef090be91217284ce (diff)
downloadqpid-python-6b17c57341c1b822d7f888e76aae1104f1599795.tar.gz
QPID-6338 : [Java AMQP 1.0 Client] validate sections in created Message
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1659700 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java179
1 files changed, 173 insertions, 6 deletions
diff --git a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java
index e8ac1de6c1..212342cd96 100644
--- a/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java
+++ b/qpid/java/amqp-1-0-client/src/main/java/org/apache/qpid/amqp_1_0/client/Message.java
@@ -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;