shade.com.alibaba.fastjson2.reader.ObjectReaderException Maven / Gradle / Ivy
package com.alibaba.fastjson2.reader;
import com.alibaba.fastjson2.*;
import com.alibaba.fastjson2.codec.FieldInfo;
import com.alibaba.fastjson2.internal.asm.ASMUtils;
import com.alibaba.fastjson2.util.BeanUtils;
import com.alibaba.fastjson2.util.Fnv;
import java.lang.reflect.Constructor;
import java.lang.reflect.Parameter;
import java.lang.reflect.Type;
import java.time.format.DateTimeParseException;
import java.util.*;
final class ObjectReaderException
extends ObjectReaderAdapter {
static final long HASH_TYPE = Fnv.hashCode64("@type");
static final long HASH_MESSAGE = Fnv.hashCode64("message");
static final long HASH_DETAIL_MESSAGE = Fnv.hashCode64("detailMessage");
static final long HASH_LOCALIZED_MESSAGE = Fnv.hashCode64("localizedMessage");
static final long HASH_CAUSE = Fnv.hashCode64("cause");
static final long HASH_STACKTRACE = Fnv.hashCode64("stackTrace");
static final long HASH_SUPPRESSED_EXCEPTIONS = Fnv.hashCode64("suppressedExceptions");
private final FieldReader fieldReaderStackTrace;
final List constructors;
final Constructor constructorDefault;
final Constructor constructorMessage;
final Constructor constructorMessageCause;
final Constructor constructorCause;
final List constructorParameters;
ObjectReaderException(Class objectClass) {
this(
objectClass,
Arrays.asList(BeanUtils.getConstructor(objectClass)),
ObjectReaders.fieldReader("stackTrace", StackTraceElement[].class, Throwable::setStackTrace)
);
}
ObjectReaderException(
Class objectClass,
List constructors,
FieldReader... fieldReaders
) {
super(objectClass, null, objectClass.getName(), 0, null, null, null, fieldReaders);
this.constructors = constructors;
Constructor constructorDefault = null;
Constructor constructorMessage = null;
Constructor constructorMessageCause = null;
Constructor constructorCause = null;
for (Constructor constructor : constructors) {
if (constructor != null && constructorMessageCause == null) {
int paramCount = constructor.getParameterCount();
if (paramCount == 0) {
constructorDefault = constructor;
continue;
}
Class[] paramTypes = constructor.getParameterTypes();
Class paramType0 = paramTypes[0];
if (paramCount == 1) {
if (paramType0 == String.class) {
constructorMessage = constructor;
} else if (Throwable.class.isAssignableFrom(paramType0)) {
constructorCause = constructor;
}
}
if (paramCount == 2
&& paramType0 == String.class
&& Throwable.class.isAssignableFrom(paramTypes[1])
) {
constructorMessageCause = constructor;
}
}
}
this.constructorDefault = constructorDefault;
this.constructorMessage = constructorMessage;
this.constructorMessageCause = constructorMessageCause;
this.constructorCause = constructorCause;
constructors.sort((Constructor left, Constructor right) -> {
int x = left.getParameterCount();
int y = right.getParameterCount();
return Integer.compare(y, x);
});
constructorParameters = new ArrayList<>(constructors.size());
for (Constructor constructor : constructors) {
int paramCount = constructor.getParameterCount();
String[] parameterNames = null;
if (paramCount > 0) {
parameterNames = ASMUtils.lookupParameterNames(constructor);
Parameter[] parameters = constructor.getParameters();
FieldInfo fieldInfo = new FieldInfo();
for (int i = 0; i < parameters.length && i < parameterNames.length; i++) {
fieldInfo.init();
Parameter parameter = parameters[i];
ObjectReaderProvider provider = JSONFactory.getDefaultObjectReaderProvider();
provider.getFieldInfo(fieldInfo, objectClass, constructor, i, parameter);
if (fieldInfo.fieldName != null) {
parameterNames[i] = fieldInfo.fieldName;
}
}
}
constructorParameters.add(parameterNames);
}
FieldReader fieldReaderStackTrace = null;
for (FieldReader fieldReader : fieldReaders) {
if ("stackTrace".equals(fieldReader.fieldName) && fieldReader.fieldClass == StackTraceElement[].class) {
fieldReaderStackTrace = fieldReader;
}
}
this.fieldReaderStackTrace = fieldReaderStackTrace;
}
@Override
public T readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
boolean objectStart = jsonReader.nextIfObjectStart();
if (!objectStart) {
if (jsonReader.nextIfNullOrEmptyString()) {
return null;
}
}
String message = null, localizedMessage = null;
Throwable cause = null;
StackTraceElement[] stackTrace = null;
List suppressedExceptions = null;
String stackTraceReference = null;
String suppressedExceptionsReference = null;
String causeReference = null;
Map fieldValues = null;
Map references = null;
for (int i = 0; ; ++i) {
if (jsonReader.nextIfObjectEnd()) {
break;
}
long hash = jsonReader.readFieldNameHashCode();
if (i == 0 && hash == HASH_TYPE && jsonReader.isSupportAutoType(features)) {
long typeHash = jsonReader.readTypeHashCode();
JSONReader.Context context = jsonReader.getContext();
ObjectReader reader = autoType(context, typeHash);
String typeName;
if (reader == null) {
typeName = jsonReader.getString();
reader = context.getObjectReaderAutoType(typeName, objectClass, features);
if (reader == null) {
throw new JSONException(jsonReader.info("No suitable ObjectReader found for" + typeName));
}
}
if (reader == this) {
continue;
}
return (T) reader.readObject(jsonReader);
} else if (hash == HASH_MESSAGE || hash == HASH_DETAIL_MESSAGE) {
message = jsonReader.readString();
} else if (hash == HASH_LOCALIZED_MESSAGE) {
localizedMessage = jsonReader.readString();
} else if (hash == HASH_CAUSE) {
if (jsonReader.isReference()) {
causeReference = jsonReader.readReference();
} else {
cause = jsonReader.read(Throwable.class);
}
} else if (hash == HASH_STACKTRACE) {
if (jsonReader.isReference()) {
stackTraceReference = jsonReader.readReference();
} else {
stackTrace = jsonReader.read(StackTraceElement[].class);
}
} else if (hash == HASH_SUPPRESSED_EXCEPTIONS) {
if (jsonReader.isReference()) {
suppressedExceptionsReference = jsonReader.readReference();
} else if (jsonReader.getType() == JSONB.Constants.BC_TYPED_ANY) {
suppressedExceptions = (List) jsonReader.readAny();
} else {
suppressedExceptions = jsonReader.readArray(Throwable.class);
}
} else {
FieldReader fieldReader = getFieldReader(hash);
if (fieldValues == null) {
fieldValues = new HashMap<>();
}
String name;
if (fieldReader != null) {
name = fieldReader.fieldName;
} else {
name = jsonReader.getFieldName();
}
Object fieldValue;
if (jsonReader.isReference()) {
String reference = jsonReader.readReference();
if (references == null) {
references = new HashMap<>();
}
references.put(name, reference);
continue;
}
if (fieldReader != null) {
fieldValue = fieldReader.readFieldValue(jsonReader);
} else {
fieldValue = jsonReader.readAny();
}
fieldValues.put(name, fieldValue);
}
}
Throwable object = createObject(message, cause);
if (object == null) {
for (int i = 0; i < constructors.size(); i++) {
String[] paramNames = constructorParameters.get(i);
if (paramNames == null || paramNames.length == 0) {
continue;
}
boolean matchAll = true;
for (String paramName : paramNames) {
if (paramName == null) {
matchAll = false;
break;
}
switch (paramName) {
case "message":
case "cause":
break;
case "errorIndex":
if (objectClass == DateTimeParseException.class) {
break;
}
if (!fieldValues.containsKey(paramName)) {
matchAll = false;
}
break;
default:
if (!fieldValues.containsKey(paramName)) {
matchAll = false;
}
break;
}
}
if (!matchAll) {
continue;
}
Object[] args = new Object[paramNames.length];
for (int j = 0; j < paramNames.length; j++) {
String paramName = paramNames[j];
Object fieldValue;
switch (paramName) {
case "message":
fieldValue = message;
break;
case "cause":
fieldValue = cause;
break;
case "errorIndex":
fieldValue = fieldValues.get(paramName);
if (fieldValue == null && objectClass == DateTimeParseException.class) {
fieldValue = 0;
}
break;
default:
fieldValue = fieldValues.get(paramName);
break;
}
args[j] = fieldValue;
}
Constructor constructor = constructors.get(i);
try {
object = (Throwable) constructor.newInstance(args);
break;
} catch (Throwable e) {
throw new JSONException("create error, objectClass " + constructor + ", " + e.getMessage(), e);
}
}
}
if (object == null) {
throw new JSONException(jsonReader.info(jsonReader.info("not support : " + objectClass.getName())));
}
if (stackTrace != null) {
int nullCount = 0;
for (StackTraceElement item : stackTrace) {
if (item == null) {
nullCount++;
}
}
if (stackTrace.length == 0 || nullCount != stackTrace.length) {
object.setStackTrace(stackTrace);
}
}
if (stackTraceReference != null) {
jsonReader.addResolveTask(fieldReaderStackTrace, object, JSONPath.of(stackTraceReference));
}
if (fieldValues != null) {
for (Map.Entry entry : fieldValues.entrySet()) {
FieldReader fieldReader = getFieldReader(entry.getKey());
if (fieldReader != null) {
fieldReader.accept(object, entry.getValue());
}
}
}
if (references != null) {
for (Map.Entry entry : references.entrySet()) {
FieldReader fieldReader = getFieldReader(entry.getKey());
if (fieldReader == null) {
continue;
}
fieldReader.addResolveTask(jsonReader, object, entry.getValue());
}
}
return (T) object;
}
@Override
public T createInstance(Map map, long features) {
if (map == null) {
return null;
}
return readObject(JSONReader.of(JSON.toJSONString(map)), features);
}
@Override
public T readJSONBObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
if (jsonReader.getType() == JSONB.Constants.BC_TYPED_ANY) {
JSONReader.Context context = jsonReader.getContext();
if (jsonReader.isSupportAutoType(features) || context.getContextAutoTypeBeforeHandler() != null) {
jsonReader.next();
long typeHash = jsonReader.readTypeHashCode();
ObjectReader autoTypeObjectReader = context.getObjectReaderAutoType(typeHash);
if (autoTypeObjectReader == null) {
String typeName = jsonReader.getString();
autoTypeObjectReader = context.getObjectReaderAutoType(typeName, null);
if (autoTypeObjectReader == null) {
throw new JSONException("auoType not support : " + typeName + ", offset " + jsonReader.getOffset());
}
}
return (T) autoTypeObjectReader.readJSONBObject(jsonReader, fieldType, fieldName, 0);
}
}
return readObject(jsonReader, fieldType, fieldName, features);
}
private Throwable createObject(String message, Throwable cause) {
try {
if (constructorMessageCause != null) {
if (cause != null && message != null) {
return (Throwable) constructorMessageCause.newInstance(message, cause);
}
}
if (constructorMessage != null) {
if (message != null) {
return (Throwable) constructorMessage.newInstance(message);
}
}
if (constructorCause != null) {
if (cause != null) {
return (Throwable) constructorCause.newInstance(cause);
}
}
if (constructorMessageCause != null) {
if (cause != null || message != null) {
return (Throwable) constructorMessageCause.newInstance(message, cause);
}
}
if (constructorDefault != null) {
return (Throwable) constructorDefault.newInstance();
}
if (constructorMessageCause != null) {
return (Throwable) constructorMessageCause.newInstance(message, cause);
}
if (constructorMessage != null) {
return (Throwable) constructorMessage.newInstance(message);
}
if (constructorCause != null) {
return (Throwable) constructorCause.newInstance(cause);
}
} catch (Throwable e) {
throw new JSONException("create Exception error, class " + objectClass.getName() + ", " + e.getMessage(), e);
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy