Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/sb compatible #107

Merged
merged 12 commits into from
Nov 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,27 @@ public void writeInstance(Object obj, AbstractHessianOutput out)
* @return
*/
protected Field[] getFieldsForSerialize(Class cl) {
List<Field> fields = new ArrayList<Field>();
ArrayList primitiveFields = new ArrayList();
ArrayList compoundFields = new ArrayList();
for (; cl != null; cl = cl.getSuperclass()) {
Field[] originFields = cl.getDeclaredFields();
for (int i = 0; i < originFields.length; i++) {
Field field = originFields[i];
if (Modifier.isTransient(field.getModifiers()) || Modifier.isStatic(field.getModifiers())) {
continue;
}
fields.add(field);

if (field.getType().isPrimitive() ||
field.getType().getName().startsWith("java.lang.") &&
!field.getType().equals(Object.class))
primitiveFields.add(field);
else
compoundFields.add(field);
}
}
List<Field> fields = new ArrayList<Field>();
fields.addAll(primitiveFields);
fields.addAll(compoundFields);
return fields.toArray(new Field[0]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
/*
* Ant Group
* Copyright (c) 2004-2023 All Rights Reserved.
*/
package com.caucho.hessian.io;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
*
* @author junyuan
* @version AbstractStringBuilderDeserializer.java, v 0.1 2023年10月20日 11:31 junyuan Exp $
*/
public class AbstractStringBuilderDeserializer extends JavaDeserializer {

Check warning on line 19 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L19

Added line #L19 was not covered by tests
private static final Logger log = Logger.getLogger(AbstractStringBuilderDeserializer.class.getName());

private static final boolean ENABLE = judgeAvailability();
/** String 的 value field, 用以判断是否需要用当前 deserializer */
private static Field stringValueField;
/** String 的 coder field, 用以从中间 String 变量中获取 coder */
private static Field stringCoderField;

static {
try {
stringCoderField = String.class.getDeclaredField("coder");
stringCoderField.setAccessible(true);

Check warning on line 31 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L31

Added line #L31 was not covered by tests
} catch (Throwable t) {
log.log(Level.WARNING,
"coder field not found or not accessible, will skip coder check, error is " + t.getMessage());
}

Check warning on line 35 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L35

Added line #L35 was not covered by tests
}

/**
* 判断是否要使用该反序列化器, 当 String.value 类型不为 char[] 时需要使用
* @return
*/
private static boolean judgeAvailability() {
try {
stringValueField = String.class.getDeclaredField("value");
stringValueField.setAccessible(true);
} catch (Throwable t) {
return false;

Check warning on line 47 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L46-L47

Added lines #L46 - L47 were not covered by tests
}

if (byte[].class.equals(stringValueField.getType())) {
return true;

Check warning on line 51 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L51

Added line #L51 was not covered by tests
}

return false;
}

public static boolean isEnable() {
return ENABLE;
}

public AbstractStringBuilderDeserializer(Class<?> cl) {
super(cl);
}

Check warning on line 63 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L62-L63

Added lines #L62 - L63 were not covered by tests

@Override
protected HashMap getFieldMap(Class cl) {
HashMap fieldMap = super.getFieldMap(cl);
Field valueField = null;
valueField = getAbstractStringBuilderField(cl, "value");

Check warning on line 69 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L67-L69

Added lines #L67 - L69 were not covered by tests
if (valueField == null) {
log.log(Level.WARNING, "get value field failed");
return fieldMap;

Check warning on line 72 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L71-L72

Added lines #L71 - L72 were not covered by tests
}

Field coderField = null;

Check warning on line 75 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L75

Added line #L75 was not covered by tests
if (fieldMap.containsKey("coder")) {
coderField = getAbstractStringBuilderField(cl, "coder");

Check warning on line 77 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L77

Added line #L77 was not covered by tests
}

fieldMap.put("value", new StringBuilderValueFieldDeserializer(valueField, coderField));
return fieldMap;

Check warning on line 81 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L80-L81

Added lines #L80 - L81 were not covered by tests
}

/**
* 获取 AbstractStingBuilder 类内的 field
* @param cl
* @param fieldName
* @return
*/
private Field getAbstractStringBuilderField(Class cl, String fieldName) {
Field field = null;

Check warning on line 91 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L91

Added line #L91 was not covered by tests
try {
field = cl.getSuperclass().getDeclaredField(fieldName);
field.setAccessible(true);
} catch (Throwable t) {
log.log(Level.WARNING, "get " + fieldName + " field failed", t);
return null;
}
return field;

Check warning on line 99 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L93-L99

Added lines #L93 - L99 were not covered by tests
}

/**
* 针对 value field 定制的 field deserializer
* 读取 value field 时, 根据传入数据进行读取, 读取到值后进行转换
*/
static class StringBuilderValueFieldDeserializer extends FieldDeserializer {
/**
* 这个 _field 会是 AbstractStringBuilder.value
*/
private final Field _field;

/**
* _coderField 会是 AbstractStringBuilder.coder 字段
*/
private final Field _coderField;

StringBuilderValueFieldDeserializer(Field value, Field coder) {
_field = value;
_coderField = coder;
}

Check warning on line 120 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L117-L120

Added lines #L117 - L120 were not covered by tests

@Override
void deserialize(AbstractHessianInput in, Object obj) throws IOException {
Object value = null;

Check warning on line 124 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L124

Added line #L124 was not covered by tests

try {
// hessian 在读取 char 时会用 utf-8 编码
value = in.readObject();

Check warning on line 128 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L128

Added line #L128 was not covered by tests
if (value == null) {
return;

Check warning on line 130 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L130

Added line #L130 was not covered by tests
}

// 理论上获取到的值有两种情况: String 或者 byte[]
if (value instanceof String) {
dealWithStringValue((String) value, obj);

Check warning on line 135 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L135

Added line #L135 was not covered by tests
} else if (value instanceof byte[]) {
_field.set(obj, value);

Check warning on line 137 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L137

Added line #L137 was not covered by tests
} else {
throw new UnsupportedEncodingException("未知的编码类型" + value.getClass());

Check warning on line 139 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L139

Added line #L139 was not covered by tests
}
} catch (Exception e) {
logDeserializeError(_field, obj, value, e);
}
}

Check warning on line 144 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L141-L144

Added lines #L141 - L144 were not covered by tests

/**
* 如果读取到的是 String, 需要通过 String.coder 进行编码
*/
public void dealWithStringValue(String value, Object obj) {
try {
byte[] res = (byte[]) stringValueField.get(value);
_field.set(obj, res);

Check warning on line 152 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L151-L152

Added lines #L151 - L152 were not covered by tests

if (stringCoderField != null) {
byte coder = (byte) stringCoderField.getByte(value);
_coderField.set(obj, coder);

Check warning on line 156 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L155-L156

Added lines #L155 - L156 were not covered by tests
}
} catch (Throwable t) {

Check warning on line 158 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L158

Added line #L158 was not covered by tests

}
}

Check warning on line 161 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderDeserializer.java#L160-L161

Added lines #L160 - L161 were not covered by tests
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Ant Group
* Copyright (c) 2004-2023 All Rights Reserved.
*/
package com.caucho.hessian.io;

import java.io.IOException;
import java.lang.reflect.Field;
import java.util.logging.Level;

/**
*
* @author junyuan
* @version AbstractStringBuilderSerializer.java, v 0.1 2023年10月20日 11:31 junyuan Exp $
*/
public class AbstractStringBuilderSerializer extends AbstractFieldAdaptorSerializer {

private static final boolean ENABLE = judgeAvailability();

public static boolean isEnable() {
return ENABLE;
}

public AbstractStringBuilderSerializer(Class cl) {
super(cl);

Check warning on line 25 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L25

Added line #L25 was not covered by tests
for (Field field : _fields) {
try {
field.setAccessible(true);
} catch (Throwable t) {
log.log(Level.WARNING, "unable to set field {} accessible", field.getName());
}

Check warning on line 31 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L28-L31

Added lines #L28 - L31 were not covered by tests
}

}

Check warning on line 34 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L34

Added line #L34 was not covered by tests

@Override
protected void serializeField(AbstractHessianOutput out, Object obj, Field field)
throws IOException {
if ("value".equals(field.getName())) {
serializeValueArray(out, obj);

Check warning on line 40 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L40

Added line #L40 was not covered by tests
} else {
serializeNormalField(out, obj, field);

Check warning on line 42 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L42

Added line #L42 was not covered by tests
}
}

Check warning on line 44 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L44

Added line #L44 was not covered by tests

/**
* 将底层 value 数组转为 char数组, 并以 writeString 方式进行序列化
* 保证序列化结果与普通 JavaSerializer 保持一致
*
* @param out
* @param obj
* @throws IOException
*/
protected void serializeValueArray(AbstractHessianOutput out, Object obj)
throws IOException {
if (obj instanceof StringBuilder) {
StringBuilder sb = (StringBuilder) obj;

Check warning on line 57 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L57

Added line #L57 was not covered by tests
// 要用实际底层 value 数据的长度以保持一致
char[] dst = new char[sb.capacity()];
sb.getChars(0, sb.length(), dst, 0);

Check warning on line 60 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L59-L60

Added lines #L59 - L60 were not covered by tests

out.writeString(dst, 0, dst.length);

Check warning on line 62 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L62

Added line #L62 was not covered by tests
} else if (obj instanceof StringBuffer) {
StringBuffer sb = (StringBuffer) obj;
char[] dst = new char[sb.capacity()];
sb.getChars(0, sb.length(), dst, 0);

Check warning on line 66 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L64-L66

Added lines #L64 - L66 were not covered by tests

out.writeString(dst, 0, dst.length);
} else {
throw new UnsupportedOperationException("only support AbstractStringBuilder but got " + obj.getClass());

Check warning on line 70 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L68-L70

Added lines #L68 - L70 were not covered by tests
}
}

Check warning on line 72 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L72

Added line #L72 was not covered by tests

/**
* 常规字段以 object 的方式序列化
* @param out
* @param obj
* @param field
* @throws IOException
*/
private void serializeNormalField(AbstractHessianOutput out, Object obj, Field field) throws IOException {
Object value = null;

Check warning on line 82 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L82

Added line #L82 was not covered by tests

try {
value = field.get(obj);
} catch (IllegalAccessException e) {
log.log(Level.FINE, e.toString(), e);
}

Check warning on line 88 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L85-L88

Added lines #L85 - L88 were not covered by tests

out.writeObject(value);
}

Check warning on line 91 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L90-L91

Added lines #L90 - L91 were not covered by tests

/**
* 判断是否要使用该反序列化器, 当 String.value 类型为 byte[] 时需要使用
* @return
*/
private static boolean judgeAvailability() {
Field field = null;
try {
field = String.class.getDeclaredField("value");
} catch (Throwable t) {
return false;

Check warning on line 102 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L101-L102

Added lines #L101 - L102 were not covered by tests
}

if (byte[].class.equals(field.getType())) {
return true;

Check warning on line 106 in src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/AbstractStringBuilderSerializer.java#L106

Added line #L106 was not covered by tests
}

return false;
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/caucho/hessian/io/SerializerFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,8 @@
addCurrencySupport();
}

addAbstractStringBuilderSupport();

}

/**
Expand Down Expand Up @@ -740,6 +742,24 @@
}
}

protected static void addAbstractStringBuilderSupport() {
try {
if (AbstractStringBuilderSerializer.isEnable()) {
_staticSerializerMap.put(StringBuilder.class, new AbstractStringBuilderSerializer(StringBuilder.class));
_staticSerializerMap.put(StringBuffer.class, new AbstractStringBuilderSerializer(StringBuffer.class));

Check warning on line 749 in src/main/java/com/caucho/hessian/io/SerializerFactory.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/SerializerFactory.java#L748-L749

Added lines #L748 - L749 were not covered by tests
}

if (AbstractStringBuilderDeserializer.isEnable()) {
_staticDeserializerMap.put(StringBuilder.class, new AbstractStringBuilderDeserializer(

Check warning on line 753 in src/main/java/com/caucho/hessian/io/SerializerFactory.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/SerializerFactory.java#L753

Added line #L753 was not covered by tests
StringBuilder.class));
_staticDeserializerMap.put(StringBuffer.class,

Check warning on line 755 in src/main/java/com/caucho/hessian/io/SerializerFactory.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/SerializerFactory.java#L755

Added line #L755 was not covered by tests
new AbstractStringBuilderDeserializer(StringBuffer.class));
}
} catch (Throwable t) {
log.info(String.valueOf(t.getCause()));

Check warning on line 759 in src/main/java/com/caucho/hessian/io/SerializerFactory.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/SerializerFactory.java#L758-L759

Added lines #L758 - L759 were not covered by tests
}
}

private static boolean isZoneId(Class cl) {
try {
return isHigherThanJdk8 && Class.forName("java.time.ZoneId").isAssignableFrom(cl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@

@Override
protected Field[] getFieldsForSerialize(Class cl) {
List<Field> fields = new ArrayList<Field>();
ArrayList primitiveFields = new ArrayList();
ArrayList compoundFields = new ArrayList();
for (; cl != null; cl = cl.getSuperclass()) {
Field[] originFields = cl.getDeclaredFields();
for (int i = 0; i < originFields.length; i++) {
Expand All @@ -102,9 +103,18 @@
if ("format".equals(field.getName())) {
continue;
}
fields.add(field);

if (field.getType().isPrimitive() ||
field.getType().getName().startsWith("java.lang.") &&
!field.getType().equals(Object.class))
primitiveFields.add(field);
else
compoundFields.add(field);

Check warning on line 112 in src/main/java/com/caucho/hessian/io/throwable/StackTraceElementSerializer.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/com/caucho/hessian/io/throwable/StackTraceElementSerializer.java#L112

Added line #L112 was not covered by tests
}
}
List<Field> fields = new ArrayList<Field>();
fields.addAll(primitiveFields);
fields.addAll(compoundFields);
return fields.toArray(new Field[0]);
}
}
Loading
Loading