Merge branch 'apache-3.1' into apache-3.2

This commit is contained in:
Albumen Kevin 2023-04-11 22:58:05 +08:00
commit bc34399771
23 changed files with 1972 additions and 48 deletions

View File

@ -74,20 +74,20 @@ public class ClassUtils {
* @since 2.7.6
*/
public static final Set<Class<?>> SIMPLE_TYPES = ofSet(
Void.class,
Boolean.class,
Character.class,
Byte.class,
Short.class,
Integer.class,
Long.class,
Float.class,
Double.class,
String.class,
BigDecimal.class,
BigInteger.class,
Date.class,
Object.class
Void.class,
Boolean.class,
Character.class,
Byte.class,
Short.class,
Integer.class,
Long.class,
Float.class,
Double.class,
String.class,
BigDecimal.class,
BigInteger.class,
Date.class,
Object.class
);
/**
* Prefix for internal array class names: "[L"
@ -118,8 +118,8 @@ public class ClassUtils {
Set<Class<?>> primitiveTypeNames = new HashSet<>(32);
primitiveTypeNames.addAll(PRIMITIVE_WRAPPER_TYPE_MAP.values());
primitiveTypeNames.addAll(Arrays
.asList(boolean[].class, byte[].class, char[].class, double[].class,
float[].class, int[].class, long[].class, short[].class));
.asList(boolean[].class, byte[].class, char[].class, double[].class,
float[].class, int[].class, long[].class, short[].class));
for (Class<?> primitiveTypeName : primitiveTypeNames) {
PRIMITIVE_TYPE_NAME_MAP.put(primitiveTypeName.getName(), primitiveTypeName);
}
@ -137,12 +137,12 @@ public class ClassUtils {
private static final char PACKAGE_SEPARATOR_CHAR = '.';
public static Class<?> forNameWithThreadContextClassLoader(String name)
throws ClassNotFoundException {
throws ClassNotFoundException {
return forName(name, Thread.currentThread().getContextClassLoader());
}
public static Class<?> forNameWithCallerClassLoader(String name, Class<?> caller)
throws ClassNotFoundException {
throws ClassNotFoundException {
return forName(name, caller.getClassLoader());
}
@ -224,7 +224,7 @@ public class ClassUtils {
* @see Class#forName(String, boolean, ClassLoader)
*/
public static Class<?> forName(String name, ClassLoader classLoader)
throws ClassNotFoundException, LinkageError {
throws ClassNotFoundException, LinkageError {
Class<?> clazz = resolvePrimitiveClassName(name);
if (clazz != null) {
@ -244,7 +244,7 @@ public class ClassUtils {
String elementClassName = null;
if (internalArrayMarker == 0) {
elementClassName = name
.substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1);
.substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1);
} else if (name.startsWith("[")) {
elementClassName = name.substring(1);
}
@ -354,7 +354,7 @@ public class ClassUtils {
*/
public static boolean isTypeMatch(Class<?> type, String value) {
if ((type == boolean.class || type == Boolean.class)
&& !("true".equals(value) || "false".equals(value))) {
&& !("true".equals(value) || "false".equals(value))) {
return false;
}
return true;
@ -408,18 +408,18 @@ public class ClassUtils {
if (isNotEmpty(interfaces)) {
// add current interfaces
Arrays.stream(interfaces)
.filter(resolved::add)
.forEach(cls -> {
allInterfaces.add(cls);
waitResolve.add(cls);
});
.filter(resolved::add)
.forEach(cls -> {
allInterfaces.add(cls);
waitResolve.add(cls);
});
}
// add all super classes to waitResolve
getAllSuperClasses(clazz)
.stream()
.filter(resolved::add)
.forEach(waitResolve::add);
.stream()
.filter(resolved::add)
.forEach(waitResolve::add);
clazz = waitResolve.poll();
}
@ -535,7 +535,7 @@ public class ClassUtils {
}
Method[] methods = Arrays.stream(tClass.getMethods())
.collect(Collectors.toList())
.toArray(new Method[] {});
.toArray(new Method[]{});
List<String> mns = new ArrayList<>(); // method names.
boolean hasMethod = hasMethods(methods);
if (hasMethod) {
@ -551,6 +551,44 @@ public class ClassUtils {
return mns.toArray(new String[0]);
}
public static boolean isMatch(Class<?> from, Class<?> to) {
if (from == to) {
return true;
}
boolean isMatch;
if (from.isPrimitive()) {
isMatch = matchPrimitive(from, to);
} else if (to.isPrimitive()) {
isMatch = matchPrimitive(to, from);
} else {
isMatch = to.isAssignableFrom(from);
}
return isMatch;
}
private static boolean matchPrimitive(Class<?> from, Class<?> to) {
if (from == boolean.class) {
return to == Boolean.class;
} else if (from == byte.class) {
return to == Byte.class;
} else if (from == char.class) {
return to == Character.class;
} else if (from == short.class) {
return to == Short.class;
} else if (from == int.class) {
return to == Integer.class;
} else if (from == long.class) {
return to == Long.class;
} else if (from == float.class) {
return to == Float.class;
} else if (from == double.class) {
return to == Double.class;
} else if (from == void.class) {
return to == Void.class;
}
return false;
}
/**
* get method name array.
*
@ -562,7 +600,7 @@ public class ClassUtils {
}
Method[] methods = Arrays.stream(tClass.getMethods())
.collect(Collectors.toList())
.toArray(new Method[] {});
.toArray(new Method[]{});
List<String> dmns = new ArrayList<>(); // method names.
boolean hasMethod = hasMethods(methods);
if (hasMethod) {

View File

@ -418,7 +418,7 @@ public class ExchangeCodec extends TelnetCodec {
}
private void encodeEventData(ObjectOutput out, Object data) throws IOException {
out.writeEvent(data);
out.writeEvent((String) data);
}
@Deprecated

View File

@ -37,6 +37,7 @@ import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
@ -261,6 +262,7 @@ class ExchangeCodecTest extends TelnetCodecTest {
}
@Test
@Disabled("Event should not be object.")
void test_Decode_Return_Request_Event_Object() throws IOException {
//|10011111|20-stats=ok|id=0|length=0
byte[] header = new byte[]{MAGIC_HIGH, MAGIC_LOW, (byte) (SERIALIZATION_BYTE | (byte) 0xe0), 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -306,6 +308,7 @@ class ExchangeCodecTest extends TelnetCodecTest {
}
@Test
@Disabled("Event should not be object.")
void test_Decode_Return_Request_Object() throws IOException {
//|10011111|20-stats=ok|id=0|length=0
byte[] header = new byte[]{MAGIC_HIGH, MAGIC_LOW, (byte) (SERIALIZATION_BYTE | (byte) 0xe0), 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -393,6 +396,7 @@ class ExchangeCodecTest extends TelnetCodecTest {
}
@Test
@Disabled("Event should not be object.")
void test_Encode_Response() throws IOException {
DefaultFuture future = DefaultFuture.newFuture(Mockito.mock(Channel.class), new Request(1001), 100000, null);

View File

@ -79,7 +79,6 @@ public final class TripleHttp2ClientResponseHandler extends
@Override
public void channelInactive(ChannelHandlerContext ctx) {
transportListener.cancelByRemote(Http2Error.NO_ERROR.code());
ctx.close();
}

View File

@ -78,8 +78,8 @@ public interface ObjectInput extends DataInput {
return (Throwable) obj;
}
default Object readEvent() throws IOException, ClassNotFoundException {
return readObject();
default String readEvent() throws IOException, ClassNotFoundException {
return readUTF();
}
default Map<String, Object> readAttachments() throws IOException, ClassNotFoundException {

View File

@ -45,11 +45,11 @@ public interface ObjectOutput extends DataOutput {
* restricting the content of headers / attachments to Ascii strings and uses ISO_8859_1 to encode them.
* https://tools.ietf.org/html/rfc7540#section-8.1.2
*/
default void writeThrowable(Object obj) throws IOException {
default void writeThrowable(Throwable obj) throws IOException {
writeObject(obj);
}
default void writeEvent(Object data) throws IOException {
default void writeEvent(String data) throws IOException {
writeObject(data);
}

View File

@ -45,5 +45,4 @@ limitations under the License.
<artifactId>fastjson2</artifactId>
</dependency>
</dependencies>
</project>

View File

@ -16,15 +16,16 @@
*/
package org.apache.dubbo.common.serialize.fastjson2;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.utils.ClassUtils;
import com.alibaba.fastjson2.JSONB;
import com.alibaba.fastjson2.JSONReader;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;
/**
* FastJson object input implementation
*/
@ -112,22 +113,28 @@ public class FastJson2ObjectInput implements ObjectInput {
throw new IllegalArgumentException("deserialize failed. expected read length: " + length + " but actual read: " + read);
}
Fastjson2SecurityManager.Handler securityFilter = fastjson2SecurityManager.getSecurityFilter();
T result;
if (securityFilter.isCheckSerializable()) {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
result = JSONB.parseObject(bytes, cls, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.IgnoreAutoTypeNotMatch,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
} else {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
result = JSONB.parseObject(bytes, cls, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.IgnoreAutoTypeNotMatch,
JSONReader.Feature.FieldBased);
}
if (result != null && cls != null && !ClassUtils.isMatch(result.getClass(), cls)) {
throw new IllegalArgumentException("deserialize failed. expected class: " + cls + " but actual class: " + result.getClass());
}
return result;
}
@Override
@SuppressWarnings("unchecked")
public <T> T readObject(Class<T> cls, Type type) throws IOException, ClassNotFoundException {
updateClassLoaderIfNeed();
int length = readLength();
@ -137,18 +144,25 @@ public class FastJson2ObjectInput implements ObjectInput {
throw new IllegalArgumentException("deserialize failed. expected read length: " + length + " but actual read: " + read);
}
Fastjson2SecurityManager.Handler securityFilter = fastjson2SecurityManager.getSecurityFilter();
T result;
if (securityFilter.isCheckSerializable()) {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
result = JSONB.parseObject(bytes, cls, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.ErrorOnNoneSerializable,
JSONReader.Feature.IgnoreAutoTypeNotMatch,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.FieldBased);
} else {
return (T) JSONB.parseObject(bytes, Object.class, securityFilter,
result = JSONB.parseObject(bytes, cls, securityFilter,
JSONReader.Feature.UseDefaultConstructorAsPossible,
JSONReader.Feature.UseNativeObject,
JSONReader.Feature.IgnoreAutoTypeNotMatch,
JSONReader.Feature.FieldBased);
}
if (result != null && cls != null && !ClassUtils.isMatch(result.getClass(), cls)) {
throw new IllegalArgumentException("deserialize failed. expected class: " + cls + " but actual class: " + result.getClass());
}
return result;
}
private void updateClassLoaderIfNeed() {

View File

@ -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 com.example.test;
import java.io.Serializable;
import java.util.Objects;
public class TestPojo implements Serializable {
private final String data;
public TestPojo(String data) {
this.data = data;
}
@Override
public String toString() {
throw new IllegalAccessError();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestPojo testPojo = (TestPojo) o;
return Objects.equals(data, testPojo.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,583 @@
/*
* 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.dubbo.common.serialize.fastjson2;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.serialize.ObjectOutput;
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.common.utils.SerializeCheckStatus;
import org.apache.dubbo.common.utils.SerializeSecurityManager;
import org.apache.dubbo.rpc.model.FrameworkModel;
import com.example.test.TestPojo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
public class FastJson2SerializationTest {
@Test
void testReadString() throws IOException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write string, read string
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject("hello");
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals("hello", objectInput.readUTF());
}
// write string, read string
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(null);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertNull(objectInput.readUTF());
}
// write date, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readUTF);
}
// write pojo, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new TrustedPojo(ThreadLocalRandom.current().nextDouble()));
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(String.class, objectInput.readUTF());
}
// write map, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readUTF);
}
// write list, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new LinkedList<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(String.class, objectInput.readUTF());
}
frameworkModel.destroy();
}
@Test
void testReadEvent() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write string, read event
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject("hello");
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals("hello", objectInput.readEvent());
}
// write date, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readEvent);
}
// write pojo, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new TrustedPojo(ThreadLocalRandom.current().nextDouble()));
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(String.class, objectInput.readEvent());
}
// write map, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readEvent);
}
// write list, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new LinkedList<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(String.class, objectInput.readEvent());
}
frameworkModel.destroy();
}
@Test
void testReadByte() throws IOException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write byte, read byte
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject((byte) 11);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals((byte) 11, objectInput.readByte());
}
// write date, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new Date());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readByte);
}
// write pojo, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new TrustedPojo(ThreadLocalRandom.current().nextDouble()));
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readByte);
}
// write map, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readByte);
}
// write list, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new LinkedList<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readByte);
}
frameworkModel.destroy();
}
@Test
void testReadObject() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write pojo, read pojo
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(trustedPojo, objectInput.readObject());
}
// write list, read list
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(pojos, objectInput.readObject());
}
// write pojo, read pojo
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(trustedPojo, objectInput.readObject(TrustedPojo.class));
}
// write list, read list
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(pojos, objectInput.readObject(List.class));
}
// write list, read list
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(pojos, objectInput.readObject(LinkedList.class));
}
frameworkModel.destroy();
}
@Test
void testReadObjectNotMatched() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).setCheckStatus(SerializeCheckStatus.STRICT);
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write pojo, read list failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(List.class));
}
// write pojo, read list failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(LinkedList.class));
}
// write pojo, read string failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(String.class, objectInput.readObject(String.class));
}
// write pojo, read other failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(TrustedNotSerializable.class));
}
// write pojo, read same field failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(TrustedPojo2.class));
}
// write pojo, read map failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(Map.class));
}
// write list, read pojo failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(TrustedPojo.class));
}
// write list, read map failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(Map.class));
}
frameworkModel.destroy();
}
@Test
void testLimit1() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write trusted, read trusted
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(trustedPojo, objectInput.readObject());
frameworkModel.destroy();
}
@Test
void testLimit4() throws IOException, ClassNotFoundException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// write force untrusted, read failed
{
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
TestPojo trustedPojo = new TestPojo("12345");
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).addToAllowed(trustedPojo.getClass().getName());
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
frameworkModel.destroy();
}
{
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
byte[] bytes = outputStream.toByteArray();
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).setCheckStatus(SerializeCheckStatus.STRICT);
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readObject);
frameworkModel.destroy();
}
}
@Test
void testLimit5() throws IOException, ClassNotFoundException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// write force un-serializable, read failed
{
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
TrustedNotSerializable trustedPojo = new TrustedNotSerializable(ThreadLocalRandom.current().nextDouble());
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).setCheckSerializable(false);
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
frameworkModel.destroy();
}
{
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
byte[] bytes = outputStream.toByteArray();
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).setCheckStatus(SerializeCheckStatus.STRICT);
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, objectInput::readObject);
frameworkModel.destroy();
}
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.dubbo.common.serialize.fastjson2;
import java.util.Objects;
public class TrustedNotSerializable {
private final double data;
public TrustedNotSerializable(double data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrustedNotSerializable that = (TrustedNotSerializable) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.common.serialize.fastjson2;
import java.io.Serializable;
import java.util.Objects;
public class TrustedPojo implements Serializable {
private final double data;
public TrustedPojo(double data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrustedPojo that = (TrustedPojo) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.common.serialize.fastjson2;
import java.io.Serializable;
import java.util.Objects;
public class TrustedPojo2 implements Serializable {
private final double data;
public TrustedPojo2(double data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrustedPojo2 that = (TrustedPojo2) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,159 @@
/*
* 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.dubbo.common.serialize.fastjson2;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.serialize.DataInput;
import org.apache.dubbo.common.serialize.DataOutput;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.serialize.ObjectOutput;
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
class TypeMatchTest {
static class DataProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
List<Object> datas = new LinkedList<>();
List<Method> readMethods = new LinkedList<>();
List<Method> writeMethods = new LinkedList<>();
datas.add(true);
datas.add(false);
datas.add((byte) 123);
datas.add((byte) 234);
datas.add((short) 12345);
datas.add((short) 23456);
datas.add(123456);
datas.add(234567);
datas.add(1234567L);
datas.add(2345678L);
datas.add(0.123F);
datas.add(1.234F);
datas.add(0.1234D);
datas.add(1.2345D);
datas.add("hello");
datas.add("world");
datas.add("hello".getBytes());
datas.add("world".getBytes());
for (Method method : ObjectInput.class.getMethods()) {
if (method.getName().startsWith("read") && method.getParameterTypes().length == 0 && !method.getReturnType().equals(Object.class)) {
readMethods.add(method);
}
}
for (Method method : DataInput.class.getMethods()) {
if (method.getName().startsWith("read") && method.getParameterTypes().length == 0 && !method.getReturnType().equals(Object.class)) {
readMethods.add(method);
}
}
for (Method method : ObjectOutput.class.getMethods()) {
if (method.getName().startsWith("write") && method.getParameterTypes().length == 1 && !method.getParameterTypes()[0].equals(Object.class)) {
writeMethods.add(method);
}
}
for (Method method : DataOutput.class.getMethods()) {
if (method.getName().startsWith("write") && method.getParameterTypes().length == 1 && !method.getParameterTypes()[0].equals(Object.class)) {
writeMethods.add(method);
}
}
Map<Class<?>, Class<?>> primitiveWrapperTypeMap = new HashMap<>(16);
primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
primitiveWrapperTypeMap.put(Byte.class, byte.class);
primitiveWrapperTypeMap.put(Character.class, char.class);
primitiveWrapperTypeMap.put(Double.class, double.class);
primitiveWrapperTypeMap.put(Float.class, float.class);
primitiveWrapperTypeMap.put(Integer.class, int.class);
primitiveWrapperTypeMap.put(Long.class, long.class);
primitiveWrapperTypeMap.put(Short.class, short.class);
primitiveWrapperTypeMap.put(Void.class, void.class);
List<Arguments> argumentsList = new LinkedList<>();
for (Object data : datas) {
for (Method input : readMethods) {
for (Method output : writeMethods) {
if (output.getParameterTypes()[0].isAssignableFrom(data.getClass())) {
argumentsList.add(Arguments.arguments(data, input, output));
}
if (primitiveWrapperTypeMap.containsKey(data.getClass()) &&
output.getParameterTypes()[0].isAssignableFrom(primitiveWrapperTypeMap.get(data.getClass()))) {
argumentsList.add(Arguments.arguments(data, input, output));
}
}
}
}
return argumentsList.stream();
}
}
@ParameterizedTest
@ArgumentsSource(DataProvider.class)
void test(Object data, Method input, Method output) throws Exception {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("fastjson2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
output.invoke(objectOutput, data);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
if (output.getParameterTypes()[0].equals(input.getReturnType())) {
Object result = input.invoke(objectInput);
if (data.getClass().isArray()) {
Assertions.assertArrayEquals((byte[]) data, (byte[]) result);
} else {
Assertions.assertEquals(data, result);
}
} else {
try {
Object result = input.invoke(objectInput);
if (data.getClass().isArray()) {
Assertions.assertNotEquals(data.getClass(), result.getClass());
} else {
Assertions.assertNotEquals(data, result);
}
} catch (Exception e) {
// ignore
}
}
frameworkModel.destroy();
}
}

View File

@ -20,6 +20,8 @@ import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.dubbo.common.utils.DefaultSerializeClassChecker;
import org.apache.dubbo.common.utils.SerializeCheckStatus;
import org.apache.dubbo.common.utils.SerializeSecurityManager;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.FrameworkModel;
@ -33,9 +35,11 @@ public class Hessian2FactoryManager {
private volatile SerializerFactory SYSTEM_SERIALIZER_FACTORY;
private final Map<ClassLoader, SerializerFactory> CL_2_SERIALIZER_FACTORY = new ConcurrentHashMap<>();
private final SerializeSecurityManager serializeSecurityManager;
private final DefaultSerializeClassChecker defaultSerializeClassChecker;
public Hessian2FactoryManager(FrameworkModel frameworkModel) {
serializeSecurityManager = frameworkModel.getBeanFactory().getOrRegisterBean(SerializeSecurityManager.class);
defaultSerializeClassChecker = frameworkModel.getBeanFactory().getOrRegisterBean(DefaultSerializeClassChecker.class);
}
@ -89,14 +93,17 @@ public class Hessian2FactoryManager {
if (StringUtils.isNotEmpty(allowPattern)) {
for (String pattern : allowPattern.split(";")) {
serializerFactory.getClassFactory().allow(pattern);
serializeSecurityManager.addToAlwaysAllowed(pattern);
}
}
serializeSecurityManager.setCheckStatus(SerializeCheckStatus.STRICT);
} else {
serializerFactory.getClassFactory().setWhitelist(false);
String denyPattern = System.getProperty(DENY);
if (StringUtils.isNotEmpty(denyPattern)) {
for (String pattern : denyPattern.split(";")) {
serializerFactory.getClassFactory().deny(pattern);
serializeSecurityManager.addToDisAllowed(pattern);
}
}
}

View File

@ -27,6 +27,8 @@ public class Hessian2ScopeModelInitializer implements ScopeModelInitializer {
public void initializeFrameworkModel(FrameworkModel frameworkModel) {
ScopeBeanFactory beanFactory = frameworkModel.getBeanFactory();
beanFactory.registerBean(Hessian2FactoryManager.class);
frameworkModel.addClassLoaderListener(new Hessian2ClassLoaderListener());
}
@Override

View File

@ -52,7 +52,7 @@ public class Hessian2SerializerFactory extends SerializerFactory {
}
if (!Serializable.class.isAssignableFrom(cl)
&& (!isAllowNonSerializable() || !defaultSerializeClassChecker.isCheckSerializable())) {
&& (!isAllowNonSerializable() || defaultSerializeClassChecker.isCheckSerializable())) {
throw new IllegalStateException("Serialized class " + cl.getName() + " must implement java.io.Serializable");
}

View File

@ -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 com.example.test;
import java.io.Serializable;
import java.util.Objects;
public class TestPojo implements Serializable {
private final String data;
public TestPojo(String data) {
this.data = data;
}
@Override
public String toString() {
throw new IllegalAccessError();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TestPojo testPojo = (TestPojo) o;
return Objects.equals(data, testPojo.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,615 @@
/*
* 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.dubbo.common.serialize.hessian2;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.serialize.ObjectOutput;
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.common.utils.SerializeCheckStatus;
import org.apache.dubbo.common.utils.SerializeSecurityManager;
import org.apache.dubbo.rpc.model.FrameworkModel;
import com.example.test.TestPojo;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ThreadLocalRandom;
class Hessian2SerializationTest {
@Test
void testReadString() throws IOException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write string, read string
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject("hello");
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals("hello", objectInput.readUTF());
}
// write string, read string
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(null);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertNull(objectInput.readUTF());
}
// write date, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new Date());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readUTF);
}
// write pojo, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new TrustedPojo(ThreadLocalRandom.current().nextDouble()));
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readUTF);
}
// write map, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readUTF);
}
// write list, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new LinkedList<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readUTF);
}
frameworkModel.destroy();
}
@Test
void testReadEvent() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write string, read event
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject("hello");
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals("hello", objectInput.readEvent());
}
// write date, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new Date());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readEvent);
}
// write pojo, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new TrustedPojo(ThreadLocalRandom.current().nextDouble()));
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readEvent);
}
// write map, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readEvent);
}
// write list, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new LinkedList<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readEvent);
}
frameworkModel.destroy();
}
@Test
void testReadByte() throws IOException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write byte, read byte
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject((byte) 11);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals((byte) 11, objectInput.readByte());
}
// write date, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new Date());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readByte);
}
// write pojo, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new TrustedPojo(ThreadLocalRandom.current().nextDouble()));
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readByte);
}
// write map, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new HashMap<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readByte);
}
// write list, read failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(new LinkedList<>());
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(IOException.class, objectInput::readByte);
}
frameworkModel.destroy();
}
@Test
void testReadObject() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write pojo, read pojo
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(trustedPojo, objectInput.readObject());
}
// write list, read list
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(pojos, objectInput.readObject());
}
// write pojo, read pojo
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(trustedPojo, objectInput.readObject(TrustedPojo.class));
}
// write list, read list
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(pojos, objectInput.readObject(List.class));
}
// write list, read list
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(pojos, objectInput.readObject(LinkedList.class));
}
frameworkModel.destroy();
}
@Test
void testReadObjectNotMatched() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write pojo, read list failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(List.class));
}
// write pojo, read list failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(LinkedList.class));
}
// write pojo, read string failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(String.class));
}
// write pojo, read other failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(TrustedNotSerializable.class));
}
// write pojo, read same field failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(TrustedPojo2.class, objectInput.readObject(TrustedPojo2.class));
}
// write pojo, read map failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(Map.class, objectInput.readObject(Map.class));
}
// write list, read pojo failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(TrustedPojo.class));
}
// write list, read map failed
{
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
LinkedList<TrustedPojo> pojos = new LinkedList<>();
pojos.add(trustedPojo);
objectOutput.writeObject(pojos);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertThrows(RuntimeException.class, () -> objectInput.readObject(Map.class));
}
frameworkModel.destroy();
}
@Test
void testLimit1() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write trusted, read trusted
TrustedPojo trustedPojo = new TrustedPojo(ThreadLocalRandom.current().nextDouble());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertEquals(trustedPojo, objectInput.readObject());
frameworkModel.destroy();
}
@Test
void testLimit2() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).setCheckStatus(SerializeCheckStatus.STRICT);
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write untrusted failed
TestPojo trustedPojo = new TestPojo("12345");
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
Assertions.assertThrows(IllegalArgumentException.class, () -> objectOutput.writeObject(trustedPojo));
frameworkModel.destroy();
}
@Test
void testLimit3() throws IOException, ClassNotFoundException {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
// write un-serializable failed
TrustedNotSerializable trustedPojo = new TrustedNotSerializable(ThreadLocalRandom.current().nextDouble());
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
Assertions.assertThrows(IllegalArgumentException.class, () -> objectOutput.writeObject(trustedPojo));
frameworkModel.destroy();
}
@Test
void testLimit4() throws IOException, ClassNotFoundException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// write force untrusted, read failed
{
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
TestPojo trustedPojo = new TestPojo("12345");
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).addToAllowed(trustedPojo.getClass().getName());
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
frameworkModel.destroy();
}
{
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
byte[] bytes = outputStream.toByteArray();
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).setCheckStatus(SerializeCheckStatus.STRICT);
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(Map.class, objectInput.readObject());
frameworkModel.destroy();
}
}
@Test
void testLimit5() throws IOException, ClassNotFoundException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
// write force un-serializable, read failed
{
System.setProperty("dubbo.hessian.allowNonSerializable", "true");
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
TrustedNotSerializable trustedPojo = new TrustedNotSerializable(ThreadLocalRandom.current().nextDouble());
frameworkModel.getBeanFactory().getBean(SerializeSecurityManager.class).setCheckSerializable(false);
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
objectOutput.writeObject(trustedPojo);
objectOutput.flushBuffer();
frameworkModel.destroy();
System.clearProperty("dubbo.hessian.allowNonSerializable");
}
{
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
Assertions.assertInstanceOf(Map.class, objectInput.readObject());
frameworkModel.destroy();
}
}
}

View File

@ -0,0 +1,41 @@
/*
* 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.dubbo.common.serialize.hessian2;
import java.util.Objects;
public class TrustedNotSerializable {
private final double data;
public TrustedNotSerializable(double data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrustedNotSerializable that = (TrustedNotSerializable) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.common.serialize.hessian2;
import java.io.Serializable;
import java.util.Objects;
public class TrustedPojo implements Serializable {
private final double data;
public TrustedPojo(double data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrustedPojo that = (TrustedPojo) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.dubbo.common.serialize.hessian2;
import java.io.Serializable;
import java.util.Objects;
public class TrustedPojo2 implements Serializable {
private final double data;
public TrustedPojo2(double data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TrustedPojo2 that = (TrustedPojo2) o;
return Objects.equals(data, that.data);
}
@Override
public int hashCode() {
return Objects.hash(data);
}
}

View File

@ -0,0 +1,162 @@
/*
* 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.dubbo.common.serialize.hessian2;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.serialize.DataInput;
import org.apache.dubbo.common.serialize.DataOutput;
import org.apache.dubbo.common.serialize.ObjectInput;
import org.apache.dubbo.common.serialize.ObjectOutput;
import org.apache.dubbo.common.serialize.Serialization;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import org.junit.jupiter.params.provider.ArgumentsSources;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;
class TypeMatchTest {
static class DataProvider implements ArgumentsProvider {
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
List<Object> datas = new LinkedList<>();
List<Method> readMethods = new LinkedList<>();
List<Method> writeMethods = new LinkedList<>();
datas.add(true);
datas.add(false);
datas.add((byte) 123);
datas.add((byte) 234);
datas.add((short) 12345);
datas.add((short) 23456);
datas.add(123456);
datas.add(234567);
datas.add(1234567L);
datas.add(2345678L);
datas.add(0.123F);
datas.add(1.234F);
datas.add(0.1234D);
datas.add(1.2345D);
datas.add("hello");
datas.add("world");
datas.add("hello".getBytes());
datas.add("world".getBytes());
for (Method method : ObjectInput.class.getMethods()) {
if (method.getName().startsWith("read") && method.getParameterTypes().length == 0 && !method.getReturnType().equals(Object.class)) {
readMethods.add(method);
}
}
for (Method method : DataInput.class.getMethods()) {
if (method.getName().startsWith("read") && method.getParameterTypes().length == 0 && !method.getReturnType().equals(Object.class)) {
readMethods.add(method);
}
}
for (Method method : ObjectOutput.class.getMethods()) {
if (method.getName().startsWith("write") && method.getParameterTypes().length == 1 && !method.getParameterTypes()[0].equals(Object.class)) {
writeMethods.add(method);
}
}
for (Method method : DataOutput.class.getMethods()) {
if (method.getName().startsWith("write") && method.getParameterTypes().length == 1 && !method.getParameterTypes()[0].equals(Object.class)) {
writeMethods.add(method);
}
}
Map<Class<?>, Class<?>> primitiveWrapperTypeMap = new HashMap<>(16);
primitiveWrapperTypeMap.put(Boolean.class, boolean.class);
primitiveWrapperTypeMap.put(Byte.class, byte.class);
primitiveWrapperTypeMap.put(Character.class, char.class);
primitiveWrapperTypeMap.put(Double.class, double.class);
primitiveWrapperTypeMap.put(Float.class, float.class);
primitiveWrapperTypeMap.put(Integer.class, int.class);
primitiveWrapperTypeMap.put(Long.class, long.class);
primitiveWrapperTypeMap.put(Short.class, short.class);
primitiveWrapperTypeMap.put(Void.class, void.class);
List<Arguments> argumentsList = new LinkedList<>();
for (Object data : datas) {
for (Method input : readMethods) {
for (Method output : writeMethods) {
if (output.getParameterTypes()[0].isAssignableFrom(data.getClass())) {
argumentsList.add(Arguments.arguments(data, input, output));
}
if (primitiveWrapperTypeMap.containsKey(data.getClass()) &&
output.getParameterTypes()[0].isAssignableFrom(primitiveWrapperTypeMap.get(data.getClass()))) {
argumentsList.add(Arguments.arguments(data, input, output));
}
}
}
}
return argumentsList.stream();
}
}
@ParameterizedTest
@ArgumentsSource(DataProvider.class)
void test(Object data, Method input, Method output) throws Exception {
FrameworkModel frameworkModel = new FrameworkModel();
Serialization serialization = frameworkModel.getExtensionLoader(Serialization.class).getExtension("hessian2");
URL url = URL.valueOf("").setScopeModel(frameworkModel);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
ObjectOutput objectOutput = serialization.serialize(url, outputStream);
output.invoke(objectOutput, data);
objectOutput.flushBuffer();
byte[] bytes = outputStream.toByteArray();
ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
ObjectInput objectInput = serialization.deserialize(url, inputStream);
if (output.getParameterTypes()[0].equals(input.getReturnType())) {
Object result = input.invoke(objectInput);
if (data.getClass().isArray()) {
Assertions.assertArrayEquals((byte[]) data, (byte[]) result);
} else {
Assertions.assertEquals(data, result);
}
} else {
try {
Object result = input.invoke(objectInput);
if (data.getClass().isArray()) {
Assertions.assertNotEquals(data.getClass(), result.getClass());
} else {
Assertions.assertNotEquals(data, result);
}
} catch (Exception e) {
// ignore
}
}
frameworkModel.destroy();
}
}