Repository: qpid-jms
Updated Branches:
  refs/heads/master b05d577c1 -> 669cfff83


http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/669cfff8/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ClassLoadingAwareObjectInputStreamTest.java
----------------------------------------------------------------------
diff --git 
a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ClassLoadingAwareObjectInputStreamTest.java
 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ClassLoadingAwareObjectInputStreamTest.java
new file mode 100644
index 0000000..82de42c
--- /dev/null
+++ 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/ClassLoadingAwareObjectInputStreamTest.java
@@ -0,0 +1,569 @@
+/*
+ * 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.jms.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.util.Arrays;
+import java.util.UUID;
+import java.util.Vector;
+
+import 
org.apache.qpid.jms.util.ClassLoadingAwareObjectInputStream.TrustedClassFilter;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+public class ClassLoadingAwareObjectInputStreamTest {
+
+    private final TrustedClassFilter ACCEPTS_ALL_FILTER = new 
TrustedClassFilter() {
+
+        @Override
+        public boolean isTrusted(Class<?> clazz) {
+            return true;
+        }
+    };
+
+    private final TrustedClassFilter ACCEPTS_NONE_FILTER = new 
TrustedClassFilter() {
+
+        @Override
+        public boolean isTrusted(Class<?> clazz) {
+            return false;
+        }
+    };
+
+    @Rule
+    public TestName name = new TestName();
+
+    //----- Test for serialized objects 
--------------------------------------//
+
+    @Test
+    public void testReadObject() throws Exception {
+        // Expect to succeed
+        doTestReadObject(new SimplePojo(name.getMethodName()), 
ACCEPTS_ALL_FILTER);
+
+        // Expect to fail
+        try {
+            doTestReadObject(new SimplePojo(name.getMethodName()), 
ACCEPTS_NONE_FILTER);
+            fail("Should have failed to read");
+        } catch (ClassNotFoundException cnfe) {
+            // Expected
+        }
+    }
+
+    @Test
+    public void testReadObjectWithAnonymousClass() throws Exception {
+        AnonymousSimplePojoParent pojoParent = new 
AnonymousSimplePojoParent(name.getMethodName());
+
+        byte[] serialized = serializeObject(pojoParent);
+
+        TrustedClassFilter myFilter = new TrustedClassFilter() {
+            @Override
+            public boolean isTrusted(Class<?> clazz) {
+                return clazz.equals(AnonymousSimplePojoParent.class);
+            }
+        };
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+                ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+
+            Object obj = reader.readObject();
+
+            assertTrue(obj instanceof AnonymousSimplePojoParent);
+            assertEquals("Unexpected payload", pojoParent.getPayload(), 
((AnonymousSimplePojoParent)obj).getPayload());
+        }
+    }
+
+    @Test
+    public void testReadObjectWitLocalClass() throws Exception {
+        LocalSimplePojoParent pojoParent = new 
LocalSimplePojoParent(name.getMethodName());
+
+        byte[] serialized = serializeObject(pojoParent);
+
+        TrustedClassFilter myFilter = new TrustedClassFilter() {
+            @Override
+            public boolean isTrusted(Class<?> clazz) {
+                return clazz.equals(LocalSimplePojoParent.class);
+            }
+        };
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+
+            Object obj = reader.readObject();
+
+            assertTrue(obj instanceof LocalSimplePojoParent);
+            assertEquals("Unexpected payload", pojoParent.getPayload(), 
((LocalSimplePojoParent)obj).getPayload());
+        }
+    }
+
+    @Test
+    public void testReadObjectByte() throws Exception {
+        doTestReadObject(Byte.valueOf((byte) 255), ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectShort() throws Exception {
+        doTestReadObject(Short.valueOf((short) 255), ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectInteger() throws Exception {
+        doTestReadObject(Integer.valueOf(255), ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectLong() throws Exception {
+        doTestReadObject(Long.valueOf(255l), ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectFloat() throws Exception {
+        doTestReadObject(Float.valueOf(255.0f), ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectDouble() throws Exception {
+        doTestReadObject(Double.valueOf(255.0), ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectBoolean() throws Exception {
+        doTestReadObject(Boolean.FALSE, ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectString() throws Exception {
+        doTestReadObject(new String(name.getMethodName()), ACCEPTS_ALL_FILTER);
+    }
+
+    //----- Test that arrays of objects can be read 
--------------------------//
+
+    @Test
+    public void testReadObjectStringArray() throws Exception {
+        String[] value = new String[2];
+
+        value[0] = name.getMethodName() + "-1";
+        value[1] = name.getMethodName() + "-2";
+
+        doTestReadObject(value, ACCEPTS_ALL_FILTER);
+    }
+
+    @Test
+    public void testReadObjectMultiDimensionalArray() throws Exception {
+        String[][][] value = new String[2][2][1];
+
+        value[0][0][0] = "0-0-0";
+        value[0][1][0] = "0-1-0";
+        value[1][0][0] = "1-0-0";
+        value[1][1][0] = "1-1-0";
+
+        doTestReadObject(value, ACCEPTS_ALL_FILTER);
+    }
+
+    //----- Test that primitive types are not filtered 
-----------------------//
+
+    @Test
+    public void testPrimitiveByteNotFiltered() throws Exception {
+        doTestReadPrimitive((byte) 255, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveShortNotFiltered() throws Exception {
+        doTestReadPrimitive((short) 255, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveIntegerNotFiltered() throws Exception {
+        doTestReadPrimitive(255, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveLongNotFiltered() throws Exception {
+        doTestReadPrimitive((long) 255, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveFloatNotFiltered() throws Exception {
+        doTestReadPrimitive((float) 255.0, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveDoubleNotFiltered() throws Exception {
+        doTestReadPrimitive(255.0, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveBooleanNotFiltered() throws Exception {
+        doTestReadPrimitive(false, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitveCharNotFiltered() throws Exception {
+        doTestReadPrimitive('c', ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testReadObjectStringNotFiltered() throws Exception {
+        doTestReadObject(new String(name.getMethodName()), 
ACCEPTS_NONE_FILTER);
+    }
+
+    //----- Test that primitive arrays get past filters 
----------------------//
+
+    @Test
+    public void testPrimitiveByteArrayNotFiltered() throws Exception {
+        byte[] value = new byte[2];
+
+        value[0] = 1;
+        value[1] = 2;
+
+        doTestReadPrimitiveArray(value, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveShortArrayNotFiltered() throws Exception {
+        short[] value = new short[2];
+
+        value[0] = 1;
+        value[1] = 2;
+
+        doTestReadPrimitiveArray(value, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveIntegerArrayNotFiltered() throws Exception {
+        int[] value = new int[2];
+
+        value[0] = 1;
+        value[1] = 2;
+
+        doTestReadPrimitiveArray(value, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveLongArrayNotFiltered() throws Exception {
+        long[] value = new long[2];
+
+        value[0] = 1;
+        value[1] = 2;
+
+        doTestReadPrimitiveArray(value, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveFloatArrayNotFiltered() throws Exception {
+        float[] value = new float[2];
+
+        value[0] = 1.1f;
+        value[1] = 2.1f;
+
+        doTestReadPrimitiveArray(value, ACCEPTS_NONE_FILTER);
+    }
+
+    @Test
+    public void testPrimitiveDoubleArrayNotFiltered() throws Exception {
+        double[] value = new double[2];
+
+        value[0] = 1.1;
+        value[1] = 2.1;
+
+        doTestReadPrimitiveArray(value, ACCEPTS_NONE_FILTER);
+    }
+
+    //----- Tests for types that should be filtered 
--------------------------//
+
+    @Test
+    public void testReadObjectStringArrayFiltered() throws Exception {
+        String[] value = new String[2];
+
+        value[0] = name.getMethodName() + "-1";
+        value[1] = name.getMethodName() + "-2";
+
+        byte[] serialized = serializeObject(value);
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, ACCEPTS_NONE_FILTER)) {
+
+            try {
+                reader.readObject();
+                fail("Should not be able to read the payload.");
+            } catch (ClassNotFoundException ex) {}
+        }
+    }
+
+    @Test
+    public void testReadObjectMixedTypeArrayGetsFiltered() throws Exception {
+        Object[] value = new Object[4];
+
+        value[0] = name.getMethodName();
+        value[1] = UUID.randomUUID();
+        value[2] = new Vector<Object>();
+        value[3] = new SimplePojo(name.getMethodName());
+
+        byte[] serialized = serializeObject(value);
+
+        TrustedClassFilter myFilter = new TrustedClassFilter() {
+
+            @Override
+            public boolean isTrusted(Class<?> clazz) {
+                return !clazz.equals(SimplePojo.class);
+            }
+        };
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+
+            try {
+                reader.readObject();
+                fail("Should not be able to read the payload.");
+            } catch (ClassNotFoundException ex) {}
+        }
+
+        // Replace the filtered type and try again
+        value[3] = new Integer(20);
+
+        serialized = serializeObject(value);
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+            ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+
+           try {
+               Object result = reader.readObject();
+
+               assertNotNull(result);
+               assertTrue(result.getClass().isArray());
+           } catch (ClassNotFoundException ex) {
+               fail("Should be able to read the payload.");
+           }
+       }
+    }
+
+    @Test
+    public void testReadObjectMultiDimensionalStringArrayFiltered() throws 
Exception {
+        String[][] value = new String[2][2];
+
+        value[0][0] = name.getMethodName() + "-0-0";
+        value[0][1] = name.getMethodName() + "-0-1";
+        value[1][0] = name.getMethodName() + "-1-0";
+        value[1][1] = name.getMethodName() + "-1-1";
+
+        byte[] serialized = serializeObject(value);
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, ACCEPTS_NONE_FILTER)) {
+
+            try {
+                reader.readObject();
+                fail("Should not be able to read the payload.");
+            } catch (ClassNotFoundException ex) {}
+        }
+    }
+
+    @Test
+    public void testReadObjectFailsWithUntrustedType() throws Exception {
+        byte[] serialized = serializeObject(new 
SimplePojo(name.getMethodName()));
+
+        TrustedClassFilter myFilter = new TrustedClassFilter() {
+
+            @Override
+            public boolean isTrusted(Class<?> clazz) {
+                return !clazz.equals(SimplePojo.class);
+            }
+        };
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+
+            try {
+                reader.readObject();
+                fail("Should not be able to read the payload.");
+            } catch (ClassNotFoundException ex) {}
+        }
+
+        serialized = serializeObject(UUID.randomUUID());
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+
+            try {
+                reader.readObject();
+            } catch (ClassNotFoundException ex) {
+                fail("Should be able to read the payload.");
+            }
+        }
+    }
+
+    @Test
+    public void testReadObjectFailsWithUnstrustedContentInTrustedType() throws 
Exception {
+        byte[] serialized = serializeObject(new SimplePojo(UUID.randomUUID()));
+
+        TrustedClassFilter myFilter = new TrustedClassFilter() {
+
+            @Override
+            public boolean isTrusted(Class<?> clazz) {
+                return clazz.equals(SimplePojo.class);
+            }
+        };
+
+        ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+        try (ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+            try {
+                reader.readObject();
+                fail("Should not be able to read the payload.");
+            } catch (ClassNotFoundException ex) {}
+        }
+
+        serialized = serializeObject(UUID.randomUUID());
+        input = new ByteArrayInputStream(serialized);
+        try (ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, myFilter)) {
+            try {
+                reader.readObject();
+                fail("Should not be able to read the payload.");
+            } catch (ClassNotFoundException ex) {
+            }
+        }
+    }
+
+    //----- Internal methods 
-------------------------------------------------//
+
+    private void doTestReadObject(Object value, TrustedClassFilter filter) 
throws Exception {
+        byte[] serialized = serializeObject(value);
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, filter)) {
+
+            Object result = reader.readObject();
+            assertNotNull(result);
+            assertEquals(value.getClass(), result.getClass());
+            if (result.getClass().isArray()) {
+                assertTrue(Arrays.deepEquals((Object[]) value, (Object[]) 
result));
+            } else {
+                assertEquals(value, result);
+            }
+        }
+    }
+
+    private byte[] serializeObject(Object value) throws IOException {
+        byte[] result = new byte[0];
+
+        if (value != null) {
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                 ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+
+                oos.writeObject(value);
+                oos.flush();
+                oos.close();
+
+                result = baos.toByteArray();
+            }
+        }
+
+        return result;
+    }
+
+    private void doTestReadPrimitive(Object value, TrustedClassFilter filter) 
throws Exception {
+        byte[] serialized = serializePrimitive(value);
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, filter)) {
+
+            Object result = null;
+
+            if (value instanceof Byte) {
+                result = reader.readByte();
+            } else if (value instanceof Short) {
+                result = reader.readShort();
+            } else if (value instanceof Integer) {
+                result = reader.readInt();
+            } else if (value instanceof Long) {
+                result = reader.readLong();
+            } else if (value instanceof Float) {
+                result = reader.readFloat();
+            } else if (value instanceof Double) {
+                result = reader.readDouble();
+            } else if (value instanceof Boolean) {
+                result = reader.readBoolean();
+            } else if (value instanceof Character) {
+                result = reader.readChar();
+            } else {
+                throw new IllegalArgumentException("unsuitable type for 
primitive deserialization");
+            }
+
+            assertNotNull(result);
+            assertEquals(value.getClass(), result.getClass());
+            assertEquals(value, result);
+        }
+    }
+
+    private void doTestReadPrimitiveArray(Object value, TrustedClassFilter 
filter) throws Exception {
+        byte[] serialized = serializeObject(value);
+
+        try (ByteArrayInputStream input = new ByteArrayInputStream(serialized);
+             ClassLoadingAwareObjectInputStream reader = new 
ClassLoadingAwareObjectInputStream(input, filter)) {
+
+            Object result = reader.readObject();
+
+            assertNotNull(result);
+            assertEquals(value.getClass(), result.getClass());
+            assertTrue(result.getClass().isArray());
+            assertEquals(value.getClass().getComponentType(), 
result.getClass().getComponentType());
+            assertTrue(result.getClass().getComponentType().isPrimitive());
+        }
+    }
+
+    private byte[] serializePrimitive(Object value) throws IOException {
+        byte[] result = new byte[0];
+
+        if (value != null) {
+            try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                 ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+
+                if (value instanceof Byte) {
+                    oos.writeByte((byte) value);
+                } else if (value instanceof Short) {
+                    oos.writeShort((short) value);
+                } else if (value instanceof Integer) {
+                    oos.writeInt((int) value);
+                } else if (value instanceof Long) {
+                    oos.writeLong((long) value);
+                } else if (value instanceof Float) {
+                    oos.writeFloat((float) value);
+                } else if (value instanceof Double) {
+                    oos.writeDouble((double) value);
+                } else if (value instanceof Boolean) {
+                    oos.writeBoolean((boolean) value);
+                } else if (value instanceof Character) {
+                    oos.writeChar((char) value);
+                } else {
+                    throw new IllegalArgumentException("unsuitable type for 
primitive serialization");
+                }
+
+                oos.flush();
+                oos.close();
+
+                result = baos.toByteArray();
+            }
+        }
+
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/669cfff8/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LocalSimplePojoParent.java
----------------------------------------------------------------------
diff --git 
a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LocalSimplePojoParent.java
 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LocalSimplePojoParent.java
new file mode 100644
index 0000000..45c1bd0
--- /dev/null
+++ 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LocalSimplePojoParent.java
@@ -0,0 +1,46 @@
+/*
+ * 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.jms.util;
+
+import java.io.Serializable;
+
+public class LocalSimplePojoParent implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private SimplePojo payload;
+
+    public LocalSimplePojoParent(Object simplePojoPayload) {
+        // Create an LOCAL simple payload, itself serializable, like we
+        // have to be since the object references us and is used
+        // during the serialization.
+
+        class LocalSimplPojo extends SimplePojo {
+            private static final long serialVersionUID = 1L;
+
+            LocalSimplPojo(Object simplePojoPayload) {
+                super(simplePojoPayload);
+            }
+        }
+
+        payload = new LocalSimplPojo(simplePojoPayload);
+    }
+
+    public SimplePojo getPayload() {
+        return payload;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/669cfff8/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/PropertyUtilTest.java
----------------------------------------------------------------------
diff --git 
a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/PropertyUtilTest.java 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/PropertyUtilTest.java
index 797f5ee..261b843 100644
--- 
a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/PropertyUtilTest.java
+++ 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/PropertyUtilTest.java
@@ -246,6 +246,17 @@ public class PropertyUtilTest {
     }
 
     @Test
+    public void testParseParametersFromStringWithNoValues() throws Exception {
+        Map<String, String> result = 
PropertyUtil.parseParameters("http://www.example.com?option=&another=";);
+
+        assertTrue(result.size() == 2);
+        assertTrue(result.containsKey("option"));
+        assertTrue(result.containsKey("another"));
+        assertEquals("", result.get("option"));
+        assertEquals("", result.get("another"));
+    }
+
+    @Test
     public void testParseParametersFromURIStringWithNoQuery() throws Exception 
{
         Map<String, String> result = 
PropertyUtil.parseParameters("http://www.example.com";);
         assertNotNull(result);

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/669cfff8/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/SimplePojo.java
----------------------------------------------------------------------
diff --git 
a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/SimplePojo.java 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/SimplePojo.java
new file mode 100644
index 0000000..00598da
--- /dev/null
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/SimplePojo.java
@@ -0,0 +1,73 @@
+/*
+ * 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.jms.util;
+
+import java.io.Serializable;
+
+public class SimplePojo implements Serializable {
+
+    private static final long serialVersionUID = 3258560248864895099L;
+
+    private Object payload;
+
+    public SimplePojo() {
+    }
+
+    public SimplePojo(Object payload) {
+        this.payload = payload;
+    }
+
+    public Object getPayload() {
+        return payload;
+    }
+
+    public void setPayload(Object payload) {
+        this.payload = payload;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((payload == null) ? 0 : payload.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+
+        SimplePojo other = (SimplePojo) obj;
+        if (payload == null) {
+            if (other.payload != null) {
+                return false;
+            }
+        } else if (!payload.equals(other.payload)) {
+            return false;
+        }
+
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/669cfff8/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/URISupportTest.java
----------------------------------------------------------------------
diff --git 
a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/URISupportTest.java 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/URISupportTest.java
index b936b90..6495858 100644
--- a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/URISupportTest.java
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/URISupportTest.java
@@ -16,22 +16,28 @@
  */
 package org.apache.qpid.jms.util;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.HashMap;
 import java.util.Map;
 
-import junit.framework.TestCase;
-
 import org.apache.qpid.jms.util.URISupport.CompositeData;
+import org.junit.Test;
 
-public class URISupportTest extends TestCase {
+public class URISupportTest {
 
+    @Test
     public void testEmptyCompositePath() throws Exception {
         CompositeData data = URISupport.parseComposite(new 
URI("broker:()/localhost?persistent=false"));
         assertEquals(0, data.getComponents().size());
     }
 
+    @Test
     public void testCompositePath() throws Exception {
         CompositeData data = URISupport.parseComposite(new 
URI("test:(path)/path"));
         assertEquals("path", data.getPath());
@@ -39,17 +45,20 @@ public class URISupportTest extends TestCase {
         assertNull(data.getPath());
     }
 
+    @Test
     public void testSimpleComposite() throws Exception {
         CompositeData data = URISupport.parseComposite(new URI("test:part1"));
         assertEquals(1, data.getComponents().size());
     }
 
+    @Test
     public void testComposite() throws Exception {
         URI uri = new 
URI("test:(part1://host,part2://(sub1://part,sube2:part))");
         CompositeData data = URISupport.parseComposite(uri);
         assertEquals(2, data.getComponents().size());
     }
 
+    @Test
     public void testEmptyCompositeWithParenthesisInParam() throws Exception {
         URI uri = new URI("failover://()?updateURIsURL=file:/C:/Dir(1)/a.csv");
         CompositeData data = URISupport.parseComposite(uri);
@@ -59,6 +68,7 @@ public class URISupportTest extends TestCase {
         assertEquals("file:/C:/Dir(1)/a.csv", 
data.getParameters().get("updateURIsURL"));
     }
 
+    @Test
     public void testCompositeWithParenthesisInParam() throws Exception {
         URI uri = new 
URI("failover://(test)?updateURIsURL=file:/C:/Dir(1)/a.csv");
         CompositeData data = URISupport.parseComposite(uri);
@@ -68,6 +78,7 @@ public class URISupportTest extends TestCase {
         assertEquals("file:/C:/Dir(1)/a.csv", 
data.getParameters().get("updateURIsURL"));
     }
 
+    @Test
     public void testCompositeWithComponentParam() throws Exception {
         CompositeData data = URISupport.parseComposite(new 
URI("test:(part1://host?part1=true)?outside=true"));
         assertEquals(1, data.getComponents().size());
@@ -77,6 +88,7 @@ public class URISupportTest extends TestCase {
         assertTrue(part1Params.containsKey("part1"));
     }
 
+    @Test
     public void testParsingURI() throws Exception {
         URI source = new 
URI("tcp://localhost:61626/foo/bar?cheese=Edam&x=123");
 
@@ -91,16 +103,33 @@ public class URISupportTest extends TestCase {
         assertEquals("result", new URI("tcp://localhost:61626/foo/bar"), 
result);
     }
 
+    @Test
+    public void testParsingURIWithEmptyValuesInOptions() throws Exception {
+        URI source = new URI("tcp://localhost:61626/foo/bar?cheese=&x=");
+
+        Map<String, String> map = PropertyUtil.parseParameters(source);
+
+        assertEquals("Size: " + map, 2, map.size());
+        assertMapKey(map, "cheese", "");
+        assertMapKey(map, "x", "");
+
+        URI result = URISupport.removeQuery(source);
+
+        assertEquals("result", new URI("tcp://localhost:61626/foo/bar"), 
result);
+    }
+
     protected void assertMapKey(Map<String, String> map, String key, Object 
expected) {
         assertEquals("Map key: " + key, map.get(key), expected);
     }
 
+    @Test
     public void testParsingCompositeURI() throws URISyntaxException {
         CompositeData data = URISupport.parseComposite(new 
URI("broker://(tcp://localhost:61616)?name=foo"));
         assertEquals("one component", 1, data.getComponents().size());
         assertEquals("Size: " + data.getParameters(), 1, 
data.getParameters().size());
     }
 
+    @Test
     public void testCheckParenthesis() throws Exception {
         String str = "fred:(((ddd))";
         assertFalse(URISupport.checkParenthesis(str));
@@ -108,6 +137,7 @@ public class URISupportTest extends TestCase {
         assertTrue(URISupport.checkParenthesis(str));
     }
 
+    @Test
     public void testCreateWithQuery() throws Exception {
         URI source = new URI("vm://localhost");
         URI dest = PropertyUtil.replaceQuery(source, "network=true&one=two");
@@ -118,6 +148,7 @@ public class URISupportTest extends TestCase {
         assertFalse("same uri, ssp", 
dest.getQuery().equals(source.getQuery()));
     }
 
+    @Test
     public void testParsingParams() throws Exception {
         URI uri = new 
URI("static:(http://localhost:61617?proxyHost=jo&proxyPort=90)?proxyHost=localhost&proxyPort=80");
         Map<String,String>parameters = URISupport.parseParameters(uri);
@@ -129,6 +160,7 @@ public class URISupportTest extends TestCase {
         parameters = URISupport.parseParameters(uri);
     }
 
+    @Test
     public void testCompositeCreateURIWithQuery() throws Exception {
         String queryString = "query=value";
         URI originalURI = new URI("outerscheme:(innerscheme:innerssp)");
@@ -151,6 +183,7 @@ public class URISupportTest extends TestCase {
         assertEquals(new URI(querylessURI + "?" + queryString), 
PropertyUtil.replaceQuery(originalURI, queryString));
     }
 
+    @Test
     public void testApplyParameters() throws Exception {
 
         URI uri = new URI("http://0.0.0.0:61616";);
@@ -178,6 +211,7 @@ public class URISupportTest extends TestCase {
         assertEquals(parameters.get("proxyPort"), "80");
     }
 
+    @Test
     public void testIsCompositeURIWithQueryNoSlashes() throws 
URISyntaxException {
         URI[] compositeURIs = new URI[] { new 
URI("test:(part1://host?part1=true)?outside=true"), new 
URI("broker:(tcp://localhost:61616)?name=foo") };
         for (URI uri : compositeURIs) {
@@ -185,6 +219,7 @@ public class URISupportTest extends TestCase {
         }
     }
 
+    @Test
     public void testIsCompositeURIWithQueryAndSlashes() throws 
URISyntaxException {
         URI[] compositeURIs = new URI[] { new 
URI("test://(part1://host?part1=true)?outside=true"), new 
URI("broker://(tcp://localhost:61616)?name=foo") };
         for (URI uri : compositeURIs) {
@@ -192,6 +227,7 @@ public class URISupportTest extends TestCase {
         }
     }
 
+    @Test
     public void testIsCompositeURINoQueryNoSlashes() throws URISyntaxException 
{
         URI[] compositeURIs = new URI[] { new 
URI("test:(part1://host,part2://(sub1://part,sube2:part))"), new 
URI("test:(path)/path") };
         for (URI uri : compositeURIs) {
@@ -199,10 +235,12 @@ public class URISupportTest extends TestCase {
         }
     }
 
+    @Test
     public void testIsCompositeURINoQueryNoSlashesNoParentheses() throws 
URISyntaxException {
         assertFalse("test:part1" + " must be detected as non-composite URI", 
URISupport.isCompositeURI(new URI("test:part1")));
     }
 
+    @Test
     public void testIsCompositeURINoQueryWithSlashes() throws 
URISyntaxException {
         URI[] compositeURIs = new URI[] { new 
URI("failover://(tcp://bla:61616,tcp://bla:61617)"),
                 new 
URI("failover://(tcp://localhost:61616,ssl://anotherhost:61617)") };
@@ -210,5 +248,4 @@ public class URISupportTest extends TestCase {
             assertTrue(uri + " must be detected as composite URI", 
URISupport.isCompositeURI(uri));
         }
     }
-
 }

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/669cfff8/qpid-jms-docs/Configuration.md
----------------------------------------------------------------------
diff --git a/qpid-jms-docs/Configuration.md b/qpid-jms-docs/Configuration.md
index 6e04a6b..6ff5820 100644
--- a/qpid-jms-docs/Configuration.md
+++ b/qpid-jms-docs/Configuration.md
@@ -99,7 +99,7 @@ The options apply to the behaviour of the JMS objects such as 
Connection, Sessio
 + **jms.connectionIDPrefix** Optional prefix value that is used for generated 
Connection ID values when a new Connection is created for the JMS 
ConnectionFactory.  This connection ID is used when logging some information 
from the JMS Connection object so a configurable prefix can make breadcrumbing 
the logs easier.  The default prefix is 'ID:'.
 + **jms.populateJMSXUserID** Controls whether a MessageProducer will populate 
the JMSXUserID value for each sent message using the authenticated username 
from the connection.  This value defaults to false and the JMSXUserID for all 
sent message will not be populated.
 
-These values control how many messages the remote peer can send to the client 
and be held in a prefetch buffer for each consumer instance.
+The Prefetch Policy controls how many messages the remote peer can send to the 
client and be held in a prefetch buffer for each consumer instance.
 
 + **jms.prefetchPolicy.queuePrefetch** defaults to 1000
 + **jms.prefetchPolicy.topicPrefetch** defaults to 1000
@@ -107,7 +107,7 @@ These values control how many messages the remote peer can 
send to the client an
 + **jms.prefetchPolicy.durableTopicPrefetch** defaults to 1000
 + **jms.prefetchPolicy.all** used to set all prefetch values at once.
 
-The RedeliveryPolicy controls how redelivered messages are handled on the 
client.
+The Redelivery Policy controls how redelivered messages are handled on the 
client.
 
 + **jms.redeliveryPolicy.maxRedeliveries** controls when an incoming message 
is rejected based on the number of times it has been redelivered, the default 
value is (-1) disabled.  A value of zero would indicate no message redeliveries 
are accepted, a value of five would allow a message to be redelivered five 
times, etc.
 
@@ -115,7 +115,7 @@ The MessageID Policy controls the type of the Message ID 
assigned to messages se
 
 + **jms.messageIDPolicy.messageIDType** By default a generated String value is 
used for the MessageID on outgoing messages. Other available types are UUID and 
UUID_STRING.
 
-The PresettlePolicy controls when a producer or consumer instance will be 
configured to use AMQP presettled messaging semantics.
+The Presettle Policy controls when a producer or consumer instance will be 
configured to use AMQP presettled messaging semantics.
 
 + **jms.presettlePolicy.presettleAll** when true all producers and 
non-transacted consumers created operate in presettled mode, defaults to false.
 + **jms.presettlePolicy.presettleProducers** when true all producers operate 
in presettled mode, defaults to false.
@@ -126,6 +126,11 @@ The PresettlePolicy controls when a producer or consumer 
instance will be config
 + **jms.presettlePolicy.presettleTopicConsumers** when true any consumer that 
is receiving from a Topic or Temporary Topic destination will operate in 
presettled mode, defaults to false.
 + **jms.presettlePolicy.presettleQueueConsumers** when true any consumer that 
is receiving from a Queue or Temporary Queue destination will operate in 
presettled mode, defaults to false.
 
+The Deserialization Policy provides a means of controlling which types are 
trusted to be deserialized from the object stream while retrieving the body 
from an incoming JMS ObjectMessage composed of serialized Java Object content. 
By default all types are trusted during attempt to deserialize the body. The 
default Deserialization Policy object provides URI options that allow 
specifying a whitelist and a blacklist of Java class or package names.
+
+**jms.deserializationPolicy.whiteList** A comma separated list of 
class/package names that should be allowed when deserializing the contents of a 
JMS ObjectMessage, unless overridden by the blackList. The names in this list 
are not pattern values, the exact class or package name must be configured, e.g 
"java.util.Map" or "java.util". Package matches include sub-packages. Default 
is to allow all.
+**jms.deserializationPolicy.blackList** A comma separated list of 
class/package names that should be rejected when deserializing the contents of 
a JMS ObjectMessage. The names in this list are not pattern values, the exact 
class or package name must be configured, e.g "java.util.Map" or "java.util". 
Package matches include sub-packages. Default is to prevent none.
+
 ### TCP Transport Configuration options
 
 When connected to a remote using plain TCP these options configure the 
behaviour of the underlying socket.  These options are appended to the 
connection URI along with the other configuration options, for example:


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to