diff --git a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java index c71f310148b..417b7564aa5 100644 --- a/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java +++ b/hessian-lite/src/main/java/com/alibaba/com/caucho/hessian/io/HessianInput.java @@ -56,6 +56,7 @@ import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; /** * Input stream for Hessian requests. @@ -999,7 +1000,15 @@ private HashMap readFault() @Override public Object readObject(Class cl) throws IOException { - if (cl == null || cl == Object.class) + return readObject(cl, null, null); + } + + /** + * Reads an object from the input stream with an expected type. + */ + public Object readObject(Class expectedClass, Class... expectedTypes) + throws IOException { + if (expectedClass == null || expectedClass == Object.class) return readObject(); int tag = read(); @@ -1011,17 +1020,23 @@ public Object readObject(Class cl) case 'M': { String type = readType(); + boolean keyValuePair = expectedTypes != null && expectedTypes.length == 2; + // hessian/3386 if ("".equals(type)) { Deserializer reader; - reader = _serializerFactory.getDeserializer(cl); + reader = _serializerFactory.getDeserializer(expectedClass); - return reader.readMap(this); + return reader.readMap(this + , keyValuePair ? expectedTypes[0] : null + , keyValuePair ? expectedTypes[1] : null); } else { Deserializer reader; - reader = _serializerFactory.getObjectDeserializer(type, cl); + reader = _serializerFactory.getObjectDeserializer(type, expectedClass); - return reader.readMap(this); + return reader.readMap(this + , keyValuePair ? expectedTypes[0] : null + , keyValuePair ? expectedTypes[1] : null); } } @@ -1032,12 +1047,14 @@ public Object readObject(Class cl) Deserializer reader; reader = _serializerFactory.getObjectDeserializer(type); - if (cl != reader.getType() && cl.isAssignableFrom(reader.getType())) - return reader.readList(this, length); + boolean valueType = expectedTypes != null && expectedTypes.length == 1; + + if (expectedClass != reader.getType() && expectedClass.isAssignableFrom(reader.getType())) + return reader.readList(this, length, valueType ? expectedTypes[0] : null); - reader = _serializerFactory.getDeserializer(cl); + reader = _serializerFactory.getDeserializer(expectedClass); - Object v = reader.readList(this, length); + Object v = reader.readList(this, length, valueType ? expectedTypes[0] : null); return v; } @@ -1061,7 +1078,7 @@ public Object readObject(Class cl) // hessian/332i vs hessian/3406 //return readObject(); - Object value = _serializerFactory.getDeserializer(cl).readObject(this); + Object value = _serializerFactory.getDeserializer(expectedClass).readObject(this); return value; } @@ -1073,6 +1090,15 @@ public Object readObject(Class cl) @Override public Object readObject() throws IOException { + return readObject((List>) null); + } + + /** + * Reads an arbitrary object from the input stream when the type + * is unknown. + */ + public Object readObject(List> expectedTypes) + throws IOException { int tag = read(); switch (tag) { @@ -1137,13 +1163,29 @@ public Object readObject() String type = readType(); int length = readLength(); - return _serializerFactory.readList(this, length, type); + Deserializer reader; + reader = _serializerFactory.getObjectDeserializer(type); + + boolean valueType = expectedTypes != null && expectedTypes.size() == 1; + + if (List.class != reader.getType() && List.class.isAssignableFrom(reader.getType())) + return reader.readList(this, length, valueType ? expectedTypes.get(0) : null); + + reader = _serializerFactory.getDeserializer(List.class); + + Object v = reader.readList(this, length, valueType ? expectedTypes.get(0) : null); + + return v; } case 'M': { String type = readType(); - return _serializerFactory.readMap(this, type); + boolean keyValuePair = expectedTypes != null && expectedTypes.size() == 2; + + return _serializerFactory.readMap(this, type + , keyValuePair ? expectedTypes.get(0) : null + , keyValuePair ? expectedTypes.get(1) : null); } case 'R': { diff --git a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian1StringShortTest.java b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian1StringShortTest.java new file mode 100644 index 00000000000..dfacf345b2d --- /dev/null +++ b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian1StringShortTest.java @@ -0,0 +1,210 @@ +/* + * 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 com.alibaba.com.caucho.hessian.io; + +import com.alibaba.com.caucho.hessian.io.base.SerializeTestBase; +import com.alibaba.com.caucho.hessian.io.beans.Hessian2StringShortType; +import com.alibaba.com.caucho.hessian.io.beans.PersonType; + +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; + +public class Hessian1StringShortTest extends SerializeTestBase { + + @Test + public void serialize_string_short_map_then_deserialize() throws Exception { + + Hessian2StringShortType stringShort = new Hessian2StringShortType(); + Map stringShortMap = new HashMap(); + stringShortMap.put("first", (short)0); + stringShortMap.put("last", (short)60); + stringShort.stringShortMap = stringShortMap; + + Hessian2StringShortType deserialize = baseHessionSerialize(stringShort); + assertTrue(deserialize.stringShortMap != null); + assertTrue(deserialize.stringShortMap.size() == 2); + assertTrue(deserialize.stringShortMap.get("last") instanceof Short); + assertEquals(Short.valueOf((short)0), deserialize.stringShortMap.get("first")); + assertEquals(Short.valueOf((short)60), deserialize.stringShortMap.get("last")); + } + + @Test + public void serialize_string_byte_map_then_deserialize() throws Exception { + + Hessian2StringShortType stringShort = new Hessian2StringShortType(); + Map stringByteMap = new HashMap(); + stringByteMap.put("first", (byte)0); + stringByteMap.put("last", (byte)60); + stringShort.stringByteMap = stringByteMap; + + Hessian2StringShortType deserialize = baseHessionSerialize(stringShort); + assertTrue(deserialize.stringByteMap != null); + assertTrue(deserialize.stringByteMap.size() == 2); + assertTrue(deserialize.stringByteMap.get("last") instanceof Byte); + assertEquals(Byte.valueOf((byte)0), deserialize.stringByteMap.get("first")); + assertEquals(Byte.valueOf((byte) 60), deserialize.stringByteMap.get("last")); + } + + @Test + public void serialize_map_then_deserialize() throws Exception { + + Map stringShortMap = new HashMap(); + stringShortMap.put("first", (short)0); + stringShortMap.put("last", (short)60); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + HessianOutput out = new HessianOutput(bout); + + out.writeObject(stringShortMap); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + HessianInput input = new HessianInput(bin); + Map deserialize = (Map) input.readObject(HashMap.class, String.class, Short.class); + assertTrue(deserialize != null); + assertTrue(deserialize.size() == 2); + assertTrue(deserialize.get("last") instanceof Short); + assertEquals(Short.valueOf((short)0), deserialize.get("first")); + assertEquals(Short.valueOf((short)60), deserialize.get("last")); + } + + @Test + public void serialize_map_then_deserialize0() throws Exception { + + Map stringShortMap = new HashMap(); + stringShortMap.put("first", (short)0); + stringShortMap.put("last", (short)60); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + HessianOutput out = new HessianOutput(bout); + + out.writeObject(stringShortMap); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + HessianInput input = new HessianInput(bin); + List> keyValueType = new ArrayList>(); + keyValueType.add(String.class); + keyValueType.add(short.class); + + Map deserialize = (Map) input.readObject(keyValueType); + assertTrue(deserialize != null); + assertTrue(deserialize.size() == 2); + assertTrue(deserialize.get("last") instanceof Short); + assertEquals(Short.valueOf((short)0), deserialize.get("first")); + assertEquals(Short.valueOf((short)60), deserialize.get("last")); + } + + @Test + public void serialize_string_person_map_then_deserialize() throws Exception { + + Hessian2StringShortType stringShort = new Hessian2StringShortType(); + Map stringPersonTypeMap = new HashMap(); + stringPersonTypeMap.put("first", new PersonType( + "jason.shang", 26, (double) 0.1, (short)1, (byte)2, Arrays.asList((short)1,(short)1) + )); + stringPersonTypeMap.put("last", new PersonType( + "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, Arrays.asList((short)2,(short)2) + )); + stringShort.stringPersonTypeMap = stringPersonTypeMap; + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + HessianOutput out = new HessianOutput(bout); + + out.writeObject(stringShort); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + HessianInput input = new HessianInput(bin); + + Hessian2StringShortType deserialize = (Hessian2StringShortType) input.readObject(); + assertTrue(deserialize.stringPersonTypeMap != null); + assertTrue(deserialize.stringPersonTypeMap.size() == 2); + assertTrue(deserialize.stringPersonTypeMap.get("last") instanceof PersonType); + + + assertEquals(new PersonType( + "jason.shang", 26, (double) 0.1, (short)1, (byte)2, Arrays.asList((short)1,(short)1) + ), deserialize.stringPersonTypeMap.get("first")); + + assertEquals(new PersonType( + "jason.shang2", 52, (double) 0.2, (short)2, (byte)4, Arrays.asList((short)2,(short)2) + ), deserialize.stringPersonTypeMap.get("last")); + + } + + @Test + public void serialize_list_then_deserialize() throws Exception { + + List shortList = new ArrayList(); + shortList.add((short)0); + shortList.add((short)60); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + HessianOutput out = new HessianOutput(bout); + + out.writeObject(shortList); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + HessianInput input = new HessianInput(bin); + List deserialize = (List) input.readObject(ArrayList.class, Short.class); + assertTrue(deserialize != null); + assertTrue(deserialize.size() == 2); + assertTrue(deserialize.get(1) instanceof Short); + assertEquals(Short.valueOf((short)0), deserialize.get(0)); + assertEquals(Short.valueOf((short)60), deserialize.get(1)); + } + + @Test + public void serialize_list_then_deserialize0() throws Exception { + + List shortList = new ArrayList(); + shortList.add((short)0); + shortList.add((short)60); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + HessianOutput out = new HessianOutput(bout); + + out.writeObject(shortList); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + HessianInput input = new HessianInput(bin); + + List> valueType = new ArrayList>(); + valueType.add(short.class); + + List deserialize = (List) input.readObject(valueType); + assertTrue(deserialize != null); + assertTrue(deserialize.size() == 2); + assertTrue(deserialize.get(1) instanceof Short); + assertEquals(Short.valueOf((short)0), deserialize.get(0)); + assertEquals(Short.valueOf((short)60), deserialize.get(1)); + } + +} diff --git a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java index b2a55e4067b..69f56c186e0 100644 --- a/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java +++ b/hessian-lite/src/test/java/com/alibaba/com/caucho/hessian/io/Hessian2StringShortTest.java @@ -92,6 +92,34 @@ public void serialize_map_then_deserialize() throws Exception { assertEquals(Short.valueOf((short)60), deserialize.get("last")); } + @Test + public void serialize_map_then_deserialize0() throws Exception { + + Map stringShortMap = new HashMap(); + stringShortMap.put("first", (short)0); + stringShortMap.put("last", (short)60); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + Hessian2Output out = new Hessian2Output(bout); + + out.writeObject(stringShortMap); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + Hessian2Input input = new Hessian2Input(bin); + + List> keyValueType = new ArrayList>(); + keyValueType.add(String.class); + keyValueType.add(short.class); + + Map deserialize = (Map) input.readObject(keyValueType); + assertTrue(deserialize != null); + assertTrue(deserialize.size() == 2); + assertTrue(deserialize.get("last") instanceof Short); + assertEquals(Short.valueOf((short)0), deserialize.get("first")); + assertEquals(Short.valueOf((short)60), deserialize.get("last")); + } + @Test public void serialize_string_person_map_then_deserialize() throws Exception { @@ -153,4 +181,30 @@ public void serialize_list_then_deserialize() throws Exception { assertEquals(Short.valueOf((short)60), deserialize.get(1)); } + @Test + public void serialize_list_then_deserialize0() throws Exception { + + List shortList = new ArrayList(); + shortList.add((short)0); + shortList.add((short)60); + + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + Hessian2Output out = new Hessian2Output(bout); + + out.writeObject(shortList); + out.flush(); + + ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); + Hessian2Input input = new Hessian2Input(bin); + + List> valueType = new ArrayList>(); + valueType.add(short.class); + + List deserialize = (List) input.readObject(valueType); + assertTrue(deserialize != null); + assertTrue(deserialize.size() == 2); + assertTrue(deserialize.get(1) instanceof Short); + assertEquals(Short.valueOf((short)0), deserialize.get(0)); + assertEquals(Short.valueOf((short)60), deserialize.get(1)); + } }