/* * Copyright 1999-2017 Alibaba Group. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.alibaba.fastjson.parser; import java.io.Closeable; import java.io.File; import java.io.Serializable; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.math.BigDecimal; import java.math.BigInteger; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; import java.nio.charset.Charset; import java.security.AccessControlException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.Currency; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.TimeZone; import java.util.TreeMap; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicIntegerArray; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLongArray; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; import com.alibaba.fastjson.*; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.parser.deserializer.*; import com.alibaba.fastjson.serializer.AtomicCodec; import com.alibaba.fastjson.serializer.AwtCodec; import com.alibaba.fastjson.serializer.BigDecimalCodec; import com.alibaba.fastjson.serializer.BigIntegerCodec; import com.alibaba.fastjson.serializer.BooleanCodec; import com.alibaba.fastjson.serializer.CalendarCodec; import com.alibaba.fastjson.serializer.CharArrayCodec; import com.alibaba.fastjson.serializer.CharacterCodec; import com.alibaba.fastjson.serializer.CollectionCodec; import com.alibaba.fastjson.serializer.DateCodec; import com.alibaba.fastjson.serializer.FloatCodec; import com.alibaba.fastjson.serializer.IntegerCodec; import com.alibaba.fastjson.serializer.LongCodec; import com.alibaba.fastjson.serializer.MiscCodec; import com.alibaba.fastjson.serializer.ObjectArrayCodec; import com.alibaba.fastjson.serializer.ReferenceCodec; import com.alibaba.fastjson.serializer.StringCodec; import com.alibaba.fastjson.util.*; import javax.sql.DataSource; import javax.xml.datatype.XMLGregorianCalendar; /** * @author wenshao[szujobs@hotmail.com] */ public class ParserConfig { public final static String DENY_PROPERTY = "fastjson.parser.deny"; public final static String AUTOTYPE_ACCEPT = "fastjson.parser.autoTypeAccept"; public final static String AUTOTYPE_SUPPORT_PROPERTY = "fastjson.parser.autoTypeSupport"; public static final String[] DENYS; private static final String[] AUTO_TYPE_ACCEPT_LIST; public static final boolean AUTO_SUPPORT; static { { String property = IOUtils.getStringProperty(DENY_PROPERTY); DENYS = splitItemsFormProperty(property); } { String property = IOUtils.getStringProperty(AUTOTYPE_SUPPORT_PROPERTY); AUTO_SUPPORT = "true".equals(property); } { String property = IOUtils.getStringProperty(AUTOTYPE_ACCEPT); String[] items = splitItemsFormProperty(property); if (items == null) { items = new String[0]; } AUTO_TYPE_ACCEPT_LIST = items; } } public static ParserConfig getGlobalInstance() { return global; } public static ParserConfig global = new ParserConfig(); private final IdentityHashMap<Type, ObjectDeserializer> deserializers = new IdentityHashMap<Type, ObjectDeserializer>(); private boolean asmEnable = !ASMUtils.IS_ANDROID; public final SymbolTable symbolTable = new SymbolTable(4096); public PropertyNamingStrategy propertyNamingStrategy; protected ClassLoader defaultClassLoader; protected ASMDeserializerFactory asmFactory; private static boolean awtError = false; private static boolean jdk8Error = false; private boolean autoTypeSupport = AUTO_SUPPORT; private String[] denyList = "bsh,com.mchange,com.sun.,java.lang.Thread,java.net.Socket,java.rmi,javax.xml,org.apache.bcel,org.apache.commons.beanutils,org.apache.commons.collections.Transformer,org.apache.commons.collections.functors,org.apache.commons.collections4.comparators,org.apache.commons.fileupload,org.apache.myfaces.context.servlet,org.apache.tomcat,org.apache.wicket.util,org.codehaus.groovy.runtime,org.hibernate,org.jboss,org.mozilla.javascript,org.python.core,org.springframework".split(","); private String[] acceptList = AUTO_TYPE_ACCEPT_LIST; private int maxTypeNameLength = 256; public final boolean fieldBased; public boolean compatibleWithJavaBean = TypeUtils.compatibleWithJavaBean; public ParserConfig(){ this(false); } public ParserConfig(boolean fieldBase){ this(null, null, fieldBase); } public ParserConfig(ClassLoader parentClassLoader){ this(null, parentClassLoader, false); } public ParserConfig(ASMDeserializerFactory asmFactory){ this(asmFactory, null, false); } private ParserConfig(ASMDeserializerFactory asmFactory, ClassLoader parentClassLoader, boolean fieldBased){ this.fieldBased = fieldBased; if (asmFactory == null && !ASMUtils.IS_ANDROID) { try { if (parentClassLoader == null) { asmFactory = new ASMDeserializerFactory(new ASMClassLoader()); } else { asmFactory = new ASMDeserializerFactory(parentClassLoader); } } catch (ExceptionInInitializerError error) { // skip } catch (AccessControlException error) { // skip } catch (NoClassDefFoundError error) { // skip } } this.asmFactory = asmFactory; if (asmFactory == null) { asmEnable = false; } deserializers.put(SimpleDateFormat.class, MiscCodec.instance); deserializers.put(java.sql.Timestamp.class, SqlDateDeserializer.instance_timestamp); deserializers.put(java.sql.Date.class, SqlDateDeserializer.instance); deserializers.put(java.sql.Time.class, TimeDeserializer.instance); deserializers.put(java.util.Date.class, DateCodec.instance); deserializers.put(Calendar.class, CalendarCodec.instance); deserializers.put(XMLGregorianCalendar.class, CalendarCodec.instance); deserializers.put(JSONObject.class, MapDeserializer.instance); deserializers.put(JSONArray.class, CollectionCodec.instance); deserializers.put(Map.class, MapDeserializer.instance); deserializers.put(HashMap.class, MapDeserializer.instance); deserializers.put(LinkedHashMap.class, MapDeserializer.instance); deserializers.put(TreeMap.class, MapDeserializer.instance); deserializers.put(ConcurrentMap.class, MapDeserializer.instance); deserializers.put(ConcurrentHashMap.class, MapDeserializer.instance); deserializers.put(Collection.class, CollectionCodec.instance); deserializers.put(List.class, CollectionCodec.instance); deserializers.put(ArrayList.class, CollectionCodec.instance); deserializers.put(Object.class, JavaObjectDeserializer.instance); deserializers.put(String.class, StringCodec.instance); deserializers.put(StringBuffer.class, StringCodec.instance); deserializers.put(StringBuilder.class, StringCodec.instance); deserializers.put(char.class, CharacterCodec.instance); deserializers.put(Character.class, CharacterCodec.instance); deserializers.put(byte.class, NumberDeserializer.instance); deserializers.put(Byte.class, NumberDeserializer.instance); deserializers.put(short.class, NumberDeserializer.instance); deserializers.put(Short.class, NumberDeserializer.instance); deserializers.put(int.class, IntegerCodec.instance); deserializers.put(Integer.class, IntegerCodec.instance); deserializers.put(long.class, LongCodec.instance); deserializers.put(Long.class, LongCodec.instance); deserializers.put(BigInteger.class, BigIntegerCodec.instance); deserializers.put(BigDecimal.class, BigDecimalCodec.instance); deserializers.put(float.class, FloatCodec.instance); deserializers.put(Float.class, FloatCodec.instance); deserializers.put(double.class, NumberDeserializer.instance); deserializers.put(Double.class, NumberDeserializer.instance); deserializers.put(boolean.class, BooleanCodec.instance); deserializers.put(Boolean.class, BooleanCodec.instance); deserializers.put(Class.class, MiscCodec.instance); deserializers.put(char[].class, new CharArrayCodec()); deserializers.put(AtomicBoolean.class, BooleanCodec.instance); deserializers.put(AtomicInteger.class, IntegerCodec.instance); deserializers.put(AtomicLong.class, LongCodec.instance); deserializers.put(AtomicReference.class, ReferenceCodec.instance); deserializers.put(WeakReference.class, ReferenceCodec.instance); deserializers.put(SoftReference.class, ReferenceCodec.instance); deserializers.put(UUID.class, MiscCodec.instance); deserializers.put(TimeZone.class, MiscCodec.instance); deserializers.put(Locale.class, MiscCodec.instance); deserializers.put(Currency.class, MiscCodec.instance); deserializers.put(InetAddress.class, MiscCodec.instance); deserializers.put(Inet4Address.class, MiscCodec.instance); deserializers.put(Inet6Address.class, MiscCodec.instance); deserializers.put(InetSocketAddress.class, MiscCodec.instance); deserializers.put(File.class, MiscCodec.instance); deserializers.put(URI.class, MiscCodec.instance); deserializers.put(URL.class, MiscCodec.instance); deserializers.put(Pattern.class, MiscCodec.instance); deserializers.put(Charset.class, MiscCodec.instance); deserializers.put(JSONPath.class, MiscCodec.instance); deserializers.put(Number.class, NumberDeserializer.instance); deserializers.put(AtomicIntegerArray.class, AtomicCodec.instance); deserializers.put(AtomicLongArray.class, AtomicCodec.instance); deserializers.put(StackTraceElement.class, StackTraceElementDeserializer.instance); deserializers.put(Serializable.class, JavaObjectDeserializer.instance); deserializers.put(Cloneable.class, JavaObjectDeserializer.instance); deserializers.put(Comparable.class, JavaObjectDeserializer.instance); deserializers.put(Closeable.class, JavaObjectDeserializer.instance); deserializers.put(JSONPObject.class, new JSONPDeserializer()); addItemsToDeny(DENYS); addItemsToAccept(AUTO_TYPE_ACCEPT_LIST); } private static String[] splitItemsFormProperty(final String property ){ if (property != null && property.length() > 0) { return property.split(","); } return null; } public void configFromPropety(Properties properties) { { String property = properties.getProperty(DENY_PROPERTY); String[] items = splitItemsFormProperty(property); addItemsToDeny(items); } { String property = properties.getProperty(AUTOTYPE_ACCEPT); String[] items = splitItemsFormProperty(property); addItemsToAccept(items); } { String property = properties.getProperty(AUTOTYPE_SUPPORT_PROPERTY); if ("true".equals(property)) { this.autoTypeSupport = true; } else if ("false".equals(property)) { this.autoTypeSupport = false; } } } private void addItemsToDeny(final String[] items){ if (items == null){ return; } for (int i = 0; i < items.length; ++i) { String item = items[i]; this.addDeny(item); } } private void addItemsToAccept(final String[] items){ if (items == null){ return; } for (int i = 0; i < items.length; ++i) { String item = items[i]; this.addAccept(item); } } public boolean isAutoTypeSupport() { return autoTypeSupport; } public void setAutoTypeSupport(boolean autoTypeSupport) { this.autoTypeSupport = autoTypeSupport; } public boolean isAsmEnable() { return asmEnable; } public void setAsmEnable(boolean asmEnable) { this.asmEnable = asmEnable; } public IdentityHashMap<Type, ObjectDeserializer> getDeserializers() { return deserializers; } public ObjectDeserializer getDeserializer(Type type) { ObjectDeserializer derializer = this.deserializers.get(type); if (derializer != null) { return derializer; } if (type instanceof Class<?>) { return getDeserializer((Class<?>) type, type); } if (type instanceof ParameterizedType) { Type rawType = ((ParameterizedType) type).getRawType(); if (rawType instanceof Class<?>) { return getDeserializer((Class<?>) rawType, type); } else { return getDeserializer(rawType); } } return JavaObjectDeserializer.instance; } public ObjectDeserializer getDeserializer(Class<?> clazz, Type type) { ObjectDeserializer derializer = deserializers.get(type); if (derializer != null) { return derializer; } if (type == null) { type = clazz; } derializer = deserializers.get(type); if (derializer != null) { return derializer; } { JSONType annotation = clazz.getAnnotation(JSONType.class); if (annotation != null) { Class<?> mappingTo = annotation.mappingTo(); if (mappingTo != Void.class) { return getDeserializer(mappingTo, mappingTo); } } } if (type instanceof WildcardType || type instanceof TypeVariable || type instanceof ParameterizedType) { derializer = deserializers.get(clazz); } if (derializer != null) { return derializer; } String className = clazz.getName(); className = className.replace('$', '.'); if (className.startsWith("java.awt.") // && AwtCodec.support(clazz)) { if (!awtError) { try { deserializers.put(Class.forName("java.awt.Point"), AwtCodec.instance); deserializers.put(Class.forName("java.awt.Font"), AwtCodec.instance); deserializers.put(Class.forName("java.awt.Rectangle"), AwtCodec.instance); deserializers.put(Class.forName("java.awt.Color"), AwtCodec.instance); } catch (Throwable e) { // skip awtError = true; } derializer = AwtCodec.instance; } } if (!jdk8Error) { try { if (className.startsWith("java.time.")) { deserializers.put(Class.forName("java.time.LocalDateTime"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.LocalDate"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.LocalTime"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.ZonedDateTime"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.OffsetDateTime"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.OffsetTime"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.ZoneOffset"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.ZoneRegion"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.ZoneId"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.Period"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.Duration"), Jdk8DateCodec.instance); deserializers.put(Class.forName("java.time.Instant"), Jdk8DateCodec.instance); derializer = deserializers.get(clazz); } else if (className.startsWith("java.util.Optional")) { deserializers.put(Class.forName("java.util.Optional"), OptionalCodec.instance); deserializers.put(Class.forName("java.util.OptionalDouble"), OptionalCodec.instance); deserializers.put(Class.forName("java.util.OptionalInt"), OptionalCodec.instance); deserializers.put(Class.forName("java.util.OptionalLong"), OptionalCodec.instance); derializer = deserializers.get(clazz); } } catch (Throwable e) { // skip jdk8Error = true; } } if (className.equals("java.nio.file.Path")) { deserializers.put(clazz, MiscCodec.instance); } if (clazz == Map.Entry.class) { deserializers.put(clazz, MiscCodec.instance); } final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); try { for (AutowiredObjectDeserializer autowired : ServiceLoader.load(AutowiredObjectDeserializer.class, classLoader)) { for (Type forType : autowired.getAutowiredFor()) { deserializers.put(forType, autowired); } } } catch (Exception ex) { // skip } if (derializer == null) { derializer = deserializers.get(type); } if (derializer != null) { return derializer; } if (clazz.isEnum()) { derializer = new EnumDeserializer(clazz); } else if (clazz.isArray()) { derializer = ObjectArrayCodec.instance; } else if (clazz == Set.class || clazz == HashSet.class || clazz == Collection.class || clazz == List.class || clazz == ArrayList.class) { derializer = CollectionCodec.instance; } else if (Collection.class.isAssignableFrom(clazz)) { derializer = CollectionCodec.instance; } else if (Map.class.isAssignableFrom(clazz)) { derializer = MapDeserializer.instance; } else if (Throwable.class.isAssignableFrom(clazz)) { derializer = new ThrowableDeserializer(this, clazz); } else { derializer = createJavaBeanDeserializer(clazz, type); } putDeserializer(type, derializer); return derializer; } /** * * @since 1.2.25 */ public void initJavaBeanDeserializers(Class<?>... classes) { if (classes == null) { return; } for (Class<?> type : classes) { if (type == null) { continue; } ObjectDeserializer deserializer = createJavaBeanDeserializer(type, type); putDeserializer(type, deserializer); } } public ObjectDeserializer createJavaBeanDeserializer(Class<?> clazz, Type type) { boolean asmEnable = this.asmEnable & !this.fieldBased; if (asmEnable) { JSONType jsonType = clazz.getAnnotation(JSONType.class); if (jsonType != null) { Class<?> deserializerClass = jsonType.deserializer(); if (deserializerClass != Void.class) { try { Object deseralizer = deserializerClass.newInstance(); if (deseralizer instanceof ObjectDeserializer) { return (ObjectDeserializer) deseralizer; } } catch (Throwable e) { // skip } } asmEnable = jsonType.asm(); } if (asmEnable) { Class<?> superClass = JavaBeanInfo.getBuilderClass(jsonType); if (superClass == null) { superClass = clazz; } for (;;) { if (!Modifier.isPublic(superClass.getModifiers())) { asmEnable = false; break; } superClass = superClass.getSuperclass(); if (superClass == Object.class || superClass == null) { break; } } } } if (clazz.getTypeParameters().length != 0) { asmEnable = false; } if (asmEnable && asmFactory != null && asmFactory.classLoader.isExternalClass(clazz)) { asmEnable = false; } if (asmEnable) { asmEnable = ASMUtils.checkName(clazz.getSimpleName()); } if (asmEnable) { if (clazz.isInterface()) { asmEnable = false; } JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy); if (asmEnable && beanInfo.fields.length > 200) { asmEnable = false; } Constructor<?> defaultConstructor = beanInfo.defaultConstructor; if (asmEnable && defaultConstructor == null && !clazz.isInterface()) { asmEnable = false; } for (FieldInfo fieldInfo : beanInfo.fields) { if (fieldInfo.getOnly) { asmEnable = false; break; } Class<?> fieldClass = fieldInfo.fieldClass; if (!Modifier.isPublic(fieldClass.getModifiers())) { asmEnable = false; break; } if (fieldClass.isMemberClass() && !Modifier.isStatic(fieldClass.getModifiers())) { asmEnable = false; break; } if (fieldInfo.getMember() != null // && !ASMUtils.checkName(fieldInfo.getMember().getName())) { asmEnable = false; break; } JSONField annotation = fieldInfo.getAnnotation(); if (annotation != null // && ((!ASMUtils.checkName(annotation.name())) // || annotation.format().length() != 0 // || annotation.deserializeUsing() != Void.class // || annotation.unwrapped())) { asmEnable = false; break; } if (fieldClass.isEnum()) { // EnumDeserializer ObjectDeserializer fieldDeser = this.getDeserializer(fieldClass); if (!(fieldDeser instanceof EnumDeserializer)) { asmEnable = false; break; } } } } if (asmEnable) { if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) { asmEnable = false; } } if (!asmEnable) { return new JavaBeanDeserializer(this, clazz, type); } JavaBeanInfo beanInfo = JavaBeanInfo.build(clazz, type, propertyNamingStrategy); try { return asmFactory.createJavaBeanDeserializer(this, beanInfo); // } catch (VerifyError e) { // e.printStackTrace(); // return new JavaBeanDeserializer(this, clazz, type); } catch (NoSuchMethodException ex) { return new JavaBeanDeserializer(this, clazz, type); } catch (JSONException asmError) { return new JavaBeanDeserializer(this, beanInfo); } catch (Exception e) { throw new JSONException("create asm deserializer error, " + clazz.getName(), e); } } public FieldDeserializer createFieldDeserializer(ParserConfig mapping, // JavaBeanInfo beanInfo, // FieldInfo fieldInfo) { Class<?> clazz = beanInfo.clazz; Class<?> fieldClass = fieldInfo.fieldClass; Class<?> deserializeUsing = null; JSONField annotation = fieldInfo.getAnnotation(); if (annotation != null) { deserializeUsing = annotation.deserializeUsing(); if (deserializeUsing == Void.class) { deserializeUsing = null; } } if (deserializeUsing == null && (fieldClass == List.class || fieldClass == ArrayList.class)) { return new ArrayListTypeFieldDeserializer(mapping, clazz, fieldInfo); } return new DefaultFieldDeserializer(mapping, clazz, fieldInfo); } public void putDeserializer(Type type, ObjectDeserializer deserializer) { deserializers.put(type, deserializer); } public ObjectDeserializer getDeserializer(FieldInfo fieldInfo) { return getDeserializer(fieldInfo.fieldClass, fieldInfo.fieldType); } /** * @deprecated internal method, dont call */ public boolean isPrimitive(Class<?> clazz) { return isPrimitive2(clazz); } /** * @deprecated internal method, dont call */ public static boolean isPrimitive2(Class<?> clazz) { return clazz.isPrimitive() // || clazz == Boolean.class // || clazz == Character.class // || clazz == Byte.class // || clazz == Short.class // || clazz == Integer.class // || clazz == Long.class // || clazz == Float.class // || clazz == Double.class // || clazz == BigInteger.class // || clazz == BigDecimal.class // || clazz == String.class // || clazz == java.util.Date.class // || clazz == java.sql.Date.class // || clazz == java.sql.Time.class // || clazz == java.sql.Timestamp.class // || clazz.isEnum() // ; } /** * fieldName,field ,先生成fieldName的快照,减少之后的findField的轮询 * * @param clazz * @param fieldCacheMap :map<fieldName ,Field> */ public static void parserAllFieldToCache(Class<?> clazz,Map</**fieldName*/String , Field> fieldCacheMap){ Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { String fieldName = field.getName(); if (!fieldCacheMap.containsKey(fieldName)) { fieldCacheMap.put(fieldName, field); } } if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) { parserAllFieldToCache(clazz.getSuperclass(), fieldCacheMap); } } public static Field getFieldFromCache(String fieldName, Map<String, Field> fieldCacheMap) { Field field = fieldCacheMap.get(fieldName); if (field == null) { field = fieldCacheMap.get("_" + fieldName); } if (field == null) { field = fieldCacheMap.get("m_" + fieldName); } if (field == null) { char c0 = fieldName.charAt(0); if (c0 >= 'a' && c0 <= 'z') { char[] chars = fieldName.toCharArray(); chars[0] -= 32; // lower String fieldNameX = new String(chars); field = fieldCacheMap.get(fieldNameX); } } return field; } public ClassLoader getDefaultClassLoader() { return defaultClassLoader; } public void setDefaultClassLoader(ClassLoader defaultClassLoader) { this.defaultClassLoader = defaultClassLoader; } public void addDeny(String name) { if (name == null || name.length() == 0) { return; } for (String item : denyList) { if (name.equals(item)) { return; // skip duplication } } String[] denyList = new String[this.denyList.length + 1]; System.arraycopy(this.denyList, 0, denyList, 0, this.denyList.length); denyList[denyList.length - 1] = name; this.denyList = denyList; } public void addAccept(String name) { if (name == null || name.length() == 0) { return; } for (String item : acceptList) { if (name.equals(item)) { return; // skip duplication } } String[] acceptList = new String[this.acceptList.length + 1]; System.arraycopy(this.acceptList, 0, acceptList, 0, this.acceptList.length); acceptList[acceptList.length - 1] = name; this.acceptList = acceptList; } public Class<?> checkAutoType(String typeName, Class<?> expectClass) { if (typeName == null) { return null; } if (typeName.length() >= maxTypeNameLength) { throw new JSONException("autoType is not support. " + typeName); } final String className = typeName.replace('$', '.'); if (autoTypeSupport || expectClass != null) { for (int i = 0; i < acceptList.length; ++i) { String accept = acceptList[i]; if (className.startsWith(accept)) { return TypeUtils.loadClass(typeName, defaultClassLoader); } } for (int i = 0; i < denyList.length; ++i) { String deny = denyList[i]; if (className.startsWith(deny)) { throw new JSONException("autoType is not support. " + typeName); } } } Class<?> clazz = TypeUtils.getClassFromMapping(typeName); if (clazz == null) { clazz = deserializers.findClass(typeName); } if (clazz != null) { if (expectClass != null && !expectClass.isAssignableFrom(clazz)) { throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName()); } return clazz; } if (!autoTypeSupport) { for (int i = 0; i < denyList.length; ++i) { String deny = denyList[i]; if (className.startsWith(deny)) { throw new JSONException("autoType is not support. " + typeName); } } for (int i = 0; i < acceptList.length; ++i) { String accept = acceptList[i]; if (className.startsWith(accept)) { clazz = TypeUtils.loadClass(typeName, defaultClassLoader); if (expectClass != null && expectClass.isAssignableFrom(clazz)) { throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName()); } return clazz; } } } if (autoTypeSupport || expectClass != null) { clazz = TypeUtils.loadClass(typeName, defaultClassLoader); } if (clazz != null) { if (ClassLoader.class.isAssignableFrom(clazz) // classloader is danger || DataSource.class.isAssignableFrom(clazz) // dataSource can load jdbc driver ) { throw new JSONException("autoType is not support. " + typeName); } if (expectClass != null) { if (expectClass.isAssignableFrom(clazz)) { return clazz; } else { throw new JSONException("type not match. " + typeName + " -> " + expectClass.getName()); } } } if (!autoTypeSupport) { throw new JSONException("autoType is not support. " + typeName); } return clazz; } }