From 2079ba8364adcd710d8947cf066831728e1c38b0 Mon Sep 17 00:00:00 2001 From: wenshao Date: Wed, 31 Jul 2013 11:06:18 +0800 Subject: [PATCH] bug fixed for superClass not public --- pom.xml | 4 +- .../alibaba/fastjson/parser/ParserConfig.java | 1118 +++++++++-------- .../alibaba/json/bvt/bug/Bug_for_yangqi.java | 49 + 3 files changed, 622 insertions(+), 549 deletions(-) create mode 100644 src/test/java/com/alibaba/json/bvt/bug/Bug_for_yangqi.java diff --git a/pom.xml b/pom.xml index 82cb51b0f..67dcb2bd5 100755 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.alibaba fastjson - 1.1.35 + 1.1.36-SNAPSHOT jar fastjson @@ -313,7 +313,7 @@ org.springframework spring-test - 3.2.2.RELEASE + 3.2.3.RELEASE test diff --git a/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java b/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java index 128c76823..1a1521626 100755 --- a/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java +++ b/src/main/java/com/alibaba/fastjson/parser/ParserConfig.java @@ -1,547 +1,571 @@ -/* - * Copyright 1999-2101 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.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -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.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.JSONArray; -import com.alibaba.fastjson.JSONException; -import com.alibaba.fastjson.JSONObject; -import com.alibaba.fastjson.annotation.JSONType; -import com.alibaba.fastjson.asm.ASMException; -import com.alibaba.fastjson.parser.deserializer.ASMDeserializerFactory; -import com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer; -import com.alibaba.fastjson.parser.deserializer.ArrayDeserializer; -import com.alibaba.fastjson.parser.deserializer.ArrayListTypeFieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.AtomicIntegerArrayDeserializer; -import com.alibaba.fastjson.parser.deserializer.AtomicLongArrayDeserializer; -import com.alibaba.fastjson.parser.deserializer.AutowiredObjectDeserializer; -import com.alibaba.fastjson.parser.deserializer.BigDecimalDeserializer; -import com.alibaba.fastjson.parser.deserializer.BigIntegerDeserializer; -import com.alibaba.fastjson.parser.deserializer.BooleanDeserializer; -import com.alibaba.fastjson.parser.deserializer.BooleanFieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.CalendarDeserializer; -import com.alibaba.fastjson.parser.deserializer.CharArrayDeserializer; -import com.alibaba.fastjson.parser.deserializer.CharacterDeserializer; -import com.alibaba.fastjson.parser.deserializer.CharsetDeserializer; -import com.alibaba.fastjson.parser.deserializer.ClassDerializer; -import com.alibaba.fastjson.parser.deserializer.CollectionDeserializer; -import com.alibaba.fastjson.parser.deserializer.ColorDeserializer; -import com.alibaba.fastjson.parser.deserializer.DateDeserializer; -import com.alibaba.fastjson.parser.deserializer.DateFormatDeserializer; -import com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.EnumDeserializer; -import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.FileDeserializer; -import com.alibaba.fastjson.parser.deserializer.FloatDeserializer; -import com.alibaba.fastjson.parser.deserializer.FontDeserializer; -import com.alibaba.fastjson.parser.deserializer.InetAddressDeserializer; -import com.alibaba.fastjson.parser.deserializer.InetSocketAddressDeserializer; -import com.alibaba.fastjson.parser.deserializer.IntegerDeserializer; -import com.alibaba.fastjson.parser.deserializer.IntegerFieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.JSONArrayDeserializer; -import com.alibaba.fastjson.parser.deserializer.JSONObjectDeserializer; -import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer; -import com.alibaba.fastjson.parser.deserializer.JavaObjectDeserializer; -import com.alibaba.fastjson.parser.deserializer.LocaleDeserializer; -import com.alibaba.fastjson.parser.deserializer.LongDeserializer; -import com.alibaba.fastjson.parser.deserializer.LongFieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.MapDeserializer; -import com.alibaba.fastjson.parser.deserializer.NumberDeserializer; -import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; -import com.alibaba.fastjson.parser.deserializer.PatternDeserializer; -import com.alibaba.fastjson.parser.deserializer.PointDeserializer; -import com.alibaba.fastjson.parser.deserializer.RectangleDeserializer; -import com.alibaba.fastjson.parser.deserializer.ReferenceDeserializer; -import com.alibaba.fastjson.parser.deserializer.SqlDateDeserializer; -import com.alibaba.fastjson.parser.deserializer.StackTraceElementDeserializer; -import com.alibaba.fastjson.parser.deserializer.StringDeserializer; -import com.alibaba.fastjson.parser.deserializer.StringFieldDeserializer; -import com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer; -import com.alibaba.fastjson.parser.deserializer.TimeDeserializer; -import com.alibaba.fastjson.parser.deserializer.TimeZoneDeserializer; -import com.alibaba.fastjson.parser.deserializer.TimestampDeserializer; -import com.alibaba.fastjson.parser.deserializer.URIDeserializer; -import com.alibaba.fastjson.parser.deserializer.URLDeserializer; -import com.alibaba.fastjson.parser.deserializer.UUIDDeserializer; -import com.alibaba.fastjson.util.ASMUtils; -import com.alibaba.fastjson.util.DeserializeBeanInfo; -import com.alibaba.fastjson.util.FieldInfo; -import com.alibaba.fastjson.util.IdentityHashMap; -import com.alibaba.fastjson.util.ServiceLoader; - -/** - * @author wenshao - */ -public class ParserConfig { - - public static ParserConfig getGlobalInstance() { - return global; - } - - private final Set> primitiveClasses = new HashSet>(); - - private static ParserConfig global = new ParserConfig(); - - private final IdentityHashMap derializers = new IdentityHashMap(); - - private boolean asmEnable = !ASMUtils.isAndroid(); - - protected final SymbolTable symbolTable = new SymbolTable(); - - public ParserConfig(){ - primitiveClasses.add(boolean.class); - primitiveClasses.add(Boolean.class); - - primitiveClasses.add(char.class); - primitiveClasses.add(Character.class); - - primitiveClasses.add(byte.class); - primitiveClasses.add(Byte.class); - - primitiveClasses.add(short.class); - primitiveClasses.add(Short.class); - - primitiveClasses.add(int.class); - primitiveClasses.add(Integer.class); - - primitiveClasses.add(long.class); - primitiveClasses.add(Long.class); - - primitiveClasses.add(float.class); - primitiveClasses.add(Float.class); - - primitiveClasses.add(double.class); - primitiveClasses.add(Double.class); - - primitiveClasses.add(BigInteger.class); - primitiveClasses.add(BigDecimal.class); - - primitiveClasses.add(String.class); - primitiveClasses.add(java.util.Date.class); - primitiveClasses.add(java.sql.Date.class); - primitiveClasses.add(java.sql.Time.class); - primitiveClasses.add(java.sql.Timestamp.class); - - derializers.put(SimpleDateFormat.class, DateFormatDeserializer.instance); - derializers.put(java.sql.Timestamp.class, TimestampDeserializer.instance); - derializers.put(java.sql.Date.class, SqlDateDeserializer.instance); - derializers.put(java.sql.Time.class, TimeDeserializer.instance); - derializers.put(java.util.Date.class, DateDeserializer.instance); - derializers.put(Calendar.class, CalendarDeserializer.instance); - - derializers.put(JSONObject.class, JSONObjectDeserializer.instance); - derializers.put(JSONArray.class, JSONArrayDeserializer.instance); - - derializers.put(Map.class, MapDeserializer.instance); - derializers.put(HashMap.class, MapDeserializer.instance); - derializers.put(LinkedHashMap.class, MapDeserializer.instance); - derializers.put(TreeMap.class, MapDeserializer.instance); - derializers.put(ConcurrentMap.class, MapDeserializer.instance); - derializers.put(ConcurrentHashMap.class, MapDeserializer.instance); - - derializers.put(Collection.class, CollectionDeserializer.instance); - derializers.put(List.class, CollectionDeserializer.instance); - derializers.put(ArrayList.class, CollectionDeserializer.instance); - - derializers.put(Object.class, JavaObjectDeserializer.instance); - derializers.put(String.class, StringDeserializer.instance); - derializers.put(char.class, CharacterDeserializer.instance); - derializers.put(Character.class, CharacterDeserializer.instance); - derializers.put(byte.class, NumberDeserializer.instance); - derializers.put(Byte.class, NumberDeserializer.instance); - derializers.put(short.class, NumberDeserializer.instance); - derializers.put(Short.class, NumberDeserializer.instance); - derializers.put(int.class, IntegerDeserializer.instance); - derializers.put(Integer.class, IntegerDeserializer.instance); - derializers.put(long.class, LongDeserializer.instance); - derializers.put(Long.class, LongDeserializer.instance); - derializers.put(BigInteger.class, BigIntegerDeserializer.instance); - derializers.put(BigDecimal.class, BigDecimalDeserializer.instance); - derializers.put(float.class, FloatDeserializer.instance); - derializers.put(Float.class, FloatDeserializer.instance); - derializers.put(double.class, NumberDeserializer.instance); - derializers.put(Double.class, NumberDeserializer.instance); - derializers.put(boolean.class, BooleanDeserializer.instance); - derializers.put(Boolean.class, BooleanDeserializer.instance); - derializers.put(Class.class, ClassDerializer.instance); - derializers.put(char[].class, CharArrayDeserializer.instance); - - derializers.put(AtomicBoolean.class, BooleanDeserializer.instance); - derializers.put(AtomicInteger.class, IntegerDeserializer.instance); - derializers.put(AtomicLong.class, LongDeserializer.instance); - derializers.put(AtomicReference.class, ReferenceDeserializer.instance); - - derializers.put(WeakReference.class, ReferenceDeserializer.instance); - derializers.put(SoftReference.class, ReferenceDeserializer.instance); - - derializers.put(UUID.class, UUIDDeserializer.instance); - derializers.put(TimeZone.class, TimeZoneDeserializer.instance); - derializers.put(Locale.class, LocaleDeserializer.instance); - derializers.put(InetAddress.class, InetAddressDeserializer.instance); - derializers.put(Inet4Address.class, InetAddressDeserializer.instance); - derializers.put(Inet6Address.class, InetAddressDeserializer.instance); - derializers.put(InetSocketAddress.class, InetSocketAddressDeserializer.instance); - derializers.put(File.class, FileDeserializer.instance); - derializers.put(URI.class, URIDeserializer.instance); - derializers.put(URL.class, URLDeserializer.instance); - derializers.put(Pattern.class, PatternDeserializer.instance); - derializers.put(Charset.class, CharsetDeserializer.instance); - derializers.put(Number.class, NumberDeserializer.instance); - derializers.put(AtomicIntegerArray.class, AtomicIntegerArrayDeserializer.instance); - derializers.put(AtomicLongArray.class, AtomicLongArrayDeserializer.instance); - derializers.put(StackTraceElement.class, StackTraceElementDeserializer.instance); - - derializers.put(Serializable.class, JavaObjectDeserializer.instance); - derializers.put(Cloneable.class, JavaObjectDeserializer.instance); - derializers.put(Comparable.class, JavaObjectDeserializer.instance); - derializers.put(Closeable.class, JavaObjectDeserializer.instance); - - try { - derializers.put(Class.forName("java.awt.Point"), PointDeserializer.instance); - derializers.put(Class.forName("java.awt.Font"), FontDeserializer.instance); - derializers.put(Class.forName("java.awt.Rectangle"), RectangleDeserializer.instance); - derializers.put(Class.forName("java.awt.Color"), ColorDeserializer.instance); - } catch (Throwable e) { - // skip - } - } - - public boolean isAsmEnable() { - return asmEnable; - } - - public void setAsmEnable(boolean asmEnable) { - this.asmEnable = asmEnable; - } - - public SymbolTable getSymbolTable() { - return symbolTable; - } - - public IdentityHashMap getDerializers() { - return derializers; - } - - public ObjectDeserializer getDeserializer(Type type) { - ObjectDeserializer derializer = this.derializers.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 = derializers.get(type); - if (derializer != null) { - return derializer; - } - - if (type == null) { - type = clazz; - } - - derializer = derializers.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 = derializers.get(clazz); - } - - if (derializer != null) { - return derializer; - } - - final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - try { - for (AutowiredObjectDeserializer autowired : ServiceLoader.load(AutowiredObjectDeserializer.class, - classLoader)) { - for (Type forType : autowired.getAutowiredFor()) { - derializers.put(forType, autowired); - } - } - } catch (Exception ex) { - // skip - } - - derializer = derializers.get(type); - if (derializer != null) { - return derializer; - } - - if (clazz.isEnum()) { - derializer = new EnumDeserializer(clazz); - } else if (clazz.isArray()) { - return ArrayDeserializer.instance; - } else if (clazz == Set.class || clazz == HashSet.class || clazz == Collection.class || clazz == List.class - || clazz == ArrayList.class) { - derializer = CollectionDeserializer.instance; - } else if (Collection.class.isAssignableFrom(clazz)) { - derializer = CollectionDeserializer.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; - } - - public ObjectDeserializer createJavaBeanDeserializer(Class clazz, Type type) { - boolean asmEnable = this.asmEnable; - if (asmEnable && !Modifier.isPublic(clazz.getModifiers())) { - asmEnable = false; - } - - if (clazz.getTypeParameters().length != 0) { - asmEnable = false; - } - - if (ASMDeserializerFactory.getInstance().isExternalClass(clazz)) { - asmEnable = false; - } - - if (asmEnable) { - if (clazz.isInterface()) { - asmEnable = false; - } - DeserializeBeanInfo beanInfo = DeserializeBeanInfo.computeSetters(clazz, type); - if (beanInfo.getFieldList().size() > 200) { - asmEnable = false; - } - - Constructor defaultConstructor = beanInfo.getDefaultConstructor(); - if (defaultConstructor == null && !clazz.isInterface()) { - asmEnable = false; - } - - for (FieldInfo fieldInfo : beanInfo.getFieldList()) { - if (fieldInfo.isGetOnly()) { - asmEnable = false; - break; - } - - Class fieldClass = fieldInfo.getFieldClass(); - if (!Modifier.isPublic(fieldClass.getModifiers())) { - asmEnable = false; - break; - } - - if (fieldClass.isMemberClass() && !Modifier.isStatic(fieldClass.getModifiers())) { - asmEnable = false; - } - } - } - - if (asmEnable) { - if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) { - asmEnable = false; - } - } - - if (!asmEnable) { - return new JavaBeanDeserializer(this, clazz, type); - } - - try { - return ASMDeserializerFactory.getInstance().createJavaBeanDeserializer(this, clazz, type); - // } catch (VerifyError e) { - // e.printStackTrace(); - // return new JavaBeanDeserializer(this, clazz, type); - } catch (ASMException asmError) { - return new JavaBeanDeserializer(this, clazz, type); - } catch (Exception e) { - throw new JSONException("create asm deserializer error, " + clazz.getName(), e); - } - } - - public FieldDeserializer createFieldDeserializer(ParserConfig mapping, Class clazz, FieldInfo fieldInfo) { - boolean asmEnable = this.asmEnable; - - if (!Modifier.isPublic(clazz.getModifiers())) { - asmEnable = false; - } - - if (fieldInfo.getFieldClass() == Class.class) { - asmEnable = false; - } - - if (ASMDeserializerFactory.getInstance().isExternalClass(clazz)) { - asmEnable = false; - } - - if (!asmEnable) { - return createFieldDeserializerWithoutASM(mapping, clazz, fieldInfo); - } - - try { - return ASMDeserializerFactory.getInstance().createFieldDeserializer(mapping, clazz, fieldInfo); - } catch (Throwable e) { - // skip - } - - return createFieldDeserializerWithoutASM(mapping, clazz, fieldInfo); - } - - public FieldDeserializer createFieldDeserializerWithoutASM(ParserConfig mapping, Class clazz, FieldInfo fieldInfo) { - Class fieldClass = fieldInfo.getFieldClass(); - - if (fieldClass == boolean.class || fieldClass == Boolean.class) { - return new BooleanFieldDeserializer(mapping, clazz, fieldInfo); - } - - if (fieldClass == int.class || fieldClass == Integer.class) { - return new IntegerFieldDeserializer(mapping, clazz, fieldInfo); - } - - if (fieldClass == long.class || fieldClass == Long.class) { - return new LongFieldDeserializer(mapping, clazz, fieldInfo); - } - - if (fieldClass == String.class) { - return new StringFieldDeserializer(mapping, clazz, fieldInfo); - } - - if (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) { - derializers.put(type, deserializer); - } - - public ObjectDeserializer getDeserializer(FieldInfo fieldInfo) { - return getDeserializer(fieldInfo.getFieldClass(), fieldInfo.getFieldType()); - } - - public boolean isPrimitive(Class clazz) { - return primitiveClasses.contains(clazz); - } - - public static Field getField(Class clazz, String fieldName) { - Field field = getField0(clazz, fieldName); - if (field == null) { - field = getField0(clazz, "_" + fieldName); - } - if (field == null) { - field = getField0(clazz, "m_" + fieldName); - } - return field; - } - - private static Field getField0(Class clazz, String fieldName) { - for (Field item : clazz.getDeclaredFields()) { - if (fieldName.equals(item.getName())) { - return item; - } - } - if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) { - return getField(clazz.getSuperclass(), fieldName); - } - - return null; - } - - public Map getFieldDeserializers(Class clazz) { - ObjectDeserializer deserizer = getDeserializer(clazz); - - if (deserizer instanceof JavaBeanDeserializer) { - return ((JavaBeanDeserializer) deserizer).getFieldDeserializerMap(); - } else if (deserizer instanceof ASMJavaBeanDeserializer) { - return ((ASMJavaBeanDeserializer) deserizer).getInnterSerializer().getFieldDeserializerMap(); - } else { - return Collections.emptyMap(); - } - } - -} +/* + * Copyright 1999-2101 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.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +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.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.JSONArray; +import com.alibaba.fastjson.JSONException; +import com.alibaba.fastjson.JSONObject; +import com.alibaba.fastjson.annotation.JSONType; +import com.alibaba.fastjson.asm.ASMException; +import com.alibaba.fastjson.parser.deserializer.ASMDeserializerFactory; +import com.alibaba.fastjson.parser.deserializer.ASMJavaBeanDeserializer; +import com.alibaba.fastjson.parser.deserializer.ArrayDeserializer; +import com.alibaba.fastjson.parser.deserializer.ArrayListTypeFieldDeserializer; +import com.alibaba.fastjson.parser.deserializer.AtomicIntegerArrayDeserializer; +import com.alibaba.fastjson.parser.deserializer.AtomicLongArrayDeserializer; +import com.alibaba.fastjson.parser.deserializer.AutowiredObjectDeserializer; +import com.alibaba.fastjson.parser.deserializer.BigDecimalDeserializer; +import com.alibaba.fastjson.parser.deserializer.BigIntegerDeserializer; +import com.alibaba.fastjson.parser.deserializer.BooleanDeserializer; +import com.alibaba.fastjson.parser.deserializer.BooleanFieldDeserializer; +import com.alibaba.fastjson.parser.deserializer.CalendarDeserializer; +import com.alibaba.fastjson.parser.deserializer.CharArrayDeserializer; +import com.alibaba.fastjson.parser.deserializer.CharacterDeserializer; +import com.alibaba.fastjson.parser.deserializer.CharsetDeserializer; +import com.alibaba.fastjson.parser.deserializer.ClassDerializer; +import com.alibaba.fastjson.parser.deserializer.CollectionDeserializer; +import com.alibaba.fastjson.parser.deserializer.ColorDeserializer; +import com.alibaba.fastjson.parser.deserializer.DateDeserializer; +import com.alibaba.fastjson.parser.deserializer.DateFormatDeserializer; +import com.alibaba.fastjson.parser.deserializer.DefaultFieldDeserializer; +import com.alibaba.fastjson.parser.deserializer.EnumDeserializer; +import com.alibaba.fastjson.parser.deserializer.FieldDeserializer; +import com.alibaba.fastjson.parser.deserializer.FileDeserializer; +import com.alibaba.fastjson.parser.deserializer.FloatDeserializer; +import com.alibaba.fastjson.parser.deserializer.FontDeserializer; +import com.alibaba.fastjson.parser.deserializer.InetAddressDeserializer; +import com.alibaba.fastjson.parser.deserializer.InetSocketAddressDeserializer; +import com.alibaba.fastjson.parser.deserializer.IntegerDeserializer; +import com.alibaba.fastjson.parser.deserializer.IntegerFieldDeserializer; +import com.alibaba.fastjson.parser.deserializer.JSONArrayDeserializer; +import com.alibaba.fastjson.parser.deserializer.JSONObjectDeserializer; +import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer; +import com.alibaba.fastjson.parser.deserializer.JavaObjectDeserializer; +import com.alibaba.fastjson.parser.deserializer.LocaleDeserializer; +import com.alibaba.fastjson.parser.deserializer.LongDeserializer; +import com.alibaba.fastjson.parser.deserializer.LongFieldDeserializer; +import com.alibaba.fastjson.parser.deserializer.MapDeserializer; +import com.alibaba.fastjson.parser.deserializer.NumberDeserializer; +import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; +import com.alibaba.fastjson.parser.deserializer.PatternDeserializer; +import com.alibaba.fastjson.parser.deserializer.PointDeserializer; +import com.alibaba.fastjson.parser.deserializer.RectangleDeserializer; +import com.alibaba.fastjson.parser.deserializer.ReferenceDeserializer; +import com.alibaba.fastjson.parser.deserializer.SqlDateDeserializer; +import com.alibaba.fastjson.parser.deserializer.StackTraceElementDeserializer; +import com.alibaba.fastjson.parser.deserializer.StringDeserializer; +import com.alibaba.fastjson.parser.deserializer.StringFieldDeserializer; +import com.alibaba.fastjson.parser.deserializer.ThrowableDeserializer; +import com.alibaba.fastjson.parser.deserializer.TimeDeserializer; +import com.alibaba.fastjson.parser.deserializer.TimeZoneDeserializer; +import com.alibaba.fastjson.parser.deserializer.TimestampDeserializer; +import com.alibaba.fastjson.parser.deserializer.URIDeserializer; +import com.alibaba.fastjson.parser.deserializer.URLDeserializer; +import com.alibaba.fastjson.parser.deserializer.UUIDDeserializer; +import com.alibaba.fastjson.util.ASMUtils; +import com.alibaba.fastjson.util.DeserializeBeanInfo; +import com.alibaba.fastjson.util.FieldInfo; +import com.alibaba.fastjson.util.IdentityHashMap; +import com.alibaba.fastjson.util.ServiceLoader; + +/** + * @author wenshao + */ +public class ParserConfig { + + public static ParserConfig getGlobalInstance() { + return global; + } + + private final Set> primitiveClasses = new HashSet>(); + + private static ParserConfig global = new ParserConfig(); + + private final IdentityHashMap derializers = new IdentityHashMap(); + + private boolean asmEnable = !ASMUtils.isAndroid(); + + protected final SymbolTable symbolTable = new SymbolTable(); + + public ParserConfig(){ + primitiveClasses.add(boolean.class); + primitiveClasses.add(Boolean.class); + + primitiveClasses.add(char.class); + primitiveClasses.add(Character.class); + + primitiveClasses.add(byte.class); + primitiveClasses.add(Byte.class); + + primitiveClasses.add(short.class); + primitiveClasses.add(Short.class); + + primitiveClasses.add(int.class); + primitiveClasses.add(Integer.class); + + primitiveClasses.add(long.class); + primitiveClasses.add(Long.class); + + primitiveClasses.add(float.class); + primitiveClasses.add(Float.class); + + primitiveClasses.add(double.class); + primitiveClasses.add(Double.class); + + primitiveClasses.add(BigInteger.class); + primitiveClasses.add(BigDecimal.class); + + primitiveClasses.add(String.class); + primitiveClasses.add(java.util.Date.class); + primitiveClasses.add(java.sql.Date.class); + primitiveClasses.add(java.sql.Time.class); + primitiveClasses.add(java.sql.Timestamp.class); + + derializers.put(SimpleDateFormat.class, DateFormatDeserializer.instance); + derializers.put(java.sql.Timestamp.class, TimestampDeserializer.instance); + derializers.put(java.sql.Date.class, SqlDateDeserializer.instance); + derializers.put(java.sql.Time.class, TimeDeserializer.instance); + derializers.put(java.util.Date.class, DateDeserializer.instance); + derializers.put(Calendar.class, CalendarDeserializer.instance); + + derializers.put(JSONObject.class, JSONObjectDeserializer.instance); + derializers.put(JSONArray.class, JSONArrayDeserializer.instance); + + derializers.put(Map.class, MapDeserializer.instance); + derializers.put(HashMap.class, MapDeserializer.instance); + derializers.put(LinkedHashMap.class, MapDeserializer.instance); + derializers.put(TreeMap.class, MapDeserializer.instance); + derializers.put(ConcurrentMap.class, MapDeserializer.instance); + derializers.put(ConcurrentHashMap.class, MapDeserializer.instance); + + derializers.put(Collection.class, CollectionDeserializer.instance); + derializers.put(List.class, CollectionDeserializer.instance); + derializers.put(ArrayList.class, CollectionDeserializer.instance); + + derializers.put(Object.class, JavaObjectDeserializer.instance); + derializers.put(String.class, StringDeserializer.instance); + derializers.put(char.class, CharacterDeserializer.instance); + derializers.put(Character.class, CharacterDeserializer.instance); + derializers.put(byte.class, NumberDeserializer.instance); + derializers.put(Byte.class, NumberDeserializer.instance); + derializers.put(short.class, NumberDeserializer.instance); + derializers.put(Short.class, NumberDeserializer.instance); + derializers.put(int.class, IntegerDeserializer.instance); + derializers.put(Integer.class, IntegerDeserializer.instance); + derializers.put(long.class, LongDeserializer.instance); + derializers.put(Long.class, LongDeserializer.instance); + derializers.put(BigInteger.class, BigIntegerDeserializer.instance); + derializers.put(BigDecimal.class, BigDecimalDeserializer.instance); + derializers.put(float.class, FloatDeserializer.instance); + derializers.put(Float.class, FloatDeserializer.instance); + derializers.put(double.class, NumberDeserializer.instance); + derializers.put(Double.class, NumberDeserializer.instance); + derializers.put(boolean.class, BooleanDeserializer.instance); + derializers.put(Boolean.class, BooleanDeserializer.instance); + derializers.put(Class.class, ClassDerializer.instance); + derializers.put(char[].class, CharArrayDeserializer.instance); + + derializers.put(AtomicBoolean.class, BooleanDeserializer.instance); + derializers.put(AtomicInteger.class, IntegerDeserializer.instance); + derializers.put(AtomicLong.class, LongDeserializer.instance); + derializers.put(AtomicReference.class, ReferenceDeserializer.instance); + + derializers.put(WeakReference.class, ReferenceDeserializer.instance); + derializers.put(SoftReference.class, ReferenceDeserializer.instance); + + derializers.put(UUID.class, UUIDDeserializer.instance); + derializers.put(TimeZone.class, TimeZoneDeserializer.instance); + derializers.put(Locale.class, LocaleDeserializer.instance); + derializers.put(InetAddress.class, InetAddressDeserializer.instance); + derializers.put(Inet4Address.class, InetAddressDeserializer.instance); + derializers.put(Inet6Address.class, InetAddressDeserializer.instance); + derializers.put(InetSocketAddress.class, InetSocketAddressDeserializer.instance); + derializers.put(File.class, FileDeserializer.instance); + derializers.put(URI.class, URIDeserializer.instance); + derializers.put(URL.class, URLDeserializer.instance); + derializers.put(Pattern.class, PatternDeserializer.instance); + derializers.put(Charset.class, CharsetDeserializer.instance); + derializers.put(Number.class, NumberDeserializer.instance); + derializers.put(AtomicIntegerArray.class, AtomicIntegerArrayDeserializer.instance); + derializers.put(AtomicLongArray.class, AtomicLongArrayDeserializer.instance); + derializers.put(StackTraceElement.class, StackTraceElementDeserializer.instance); + + derializers.put(Serializable.class, JavaObjectDeserializer.instance); + derializers.put(Cloneable.class, JavaObjectDeserializer.instance); + derializers.put(Comparable.class, JavaObjectDeserializer.instance); + derializers.put(Closeable.class, JavaObjectDeserializer.instance); + + try { + derializers.put(Class.forName("java.awt.Point"), PointDeserializer.instance); + derializers.put(Class.forName("java.awt.Font"), FontDeserializer.instance); + derializers.put(Class.forName("java.awt.Rectangle"), RectangleDeserializer.instance); + derializers.put(Class.forName("java.awt.Color"), ColorDeserializer.instance); + } catch (Throwable e) { + // skip + } + } + + public boolean isAsmEnable() { + return asmEnable; + } + + public void setAsmEnable(boolean asmEnable) { + this.asmEnable = asmEnable; + } + + public SymbolTable getSymbolTable() { + return symbolTable; + } + + public IdentityHashMap getDerializers() { + return derializers; + } + + public ObjectDeserializer getDeserializer(Type type) { + ObjectDeserializer derializer = this.derializers.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 = derializers.get(type); + if (derializer != null) { + return derializer; + } + + if (type == null) { + type = clazz; + } + + derializer = derializers.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 = derializers.get(clazz); + } + + if (derializer != null) { + return derializer; + } + + final ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try { + for (AutowiredObjectDeserializer autowired : ServiceLoader.load(AutowiredObjectDeserializer.class, + classLoader)) { + for (Type forType : autowired.getAutowiredFor()) { + derializers.put(forType, autowired); + } + } + } catch (Exception ex) { + // skip + } + + derializer = derializers.get(type); + if (derializer != null) { + return derializer; + } + + if (clazz.isEnum()) { + derializer = new EnumDeserializer(clazz); + } else if (clazz.isArray()) { + return ArrayDeserializer.instance; + } else if (clazz == Set.class || clazz == HashSet.class || clazz == Collection.class || clazz == List.class + || clazz == ArrayList.class) { + derializer = CollectionDeserializer.instance; + } else if (Collection.class.isAssignableFrom(clazz)) { + derializer = CollectionDeserializer.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; + } + + public ObjectDeserializer createJavaBeanDeserializer(Class clazz, Type type) { + boolean asmEnable = this.asmEnable; + if (asmEnable) { + Class superClass = clazz; + + for (;;) { + if(!Modifier.isPublic(superClass.getModifiers())) { + asmEnable = false; + break; + } + + superClass = superClass.getSuperclass(); + if (superClass == Object.class) { + break; + } + } + } + + if (clazz.getTypeParameters().length != 0) { + asmEnable = false; + } + + if (ASMDeserializerFactory.getInstance().isExternalClass(clazz)) { + asmEnable = false; + } + + if (asmEnable) { + if (clazz.isInterface()) { + asmEnable = false; + } + DeserializeBeanInfo beanInfo = DeserializeBeanInfo.computeSetters(clazz, type); + if (beanInfo.getFieldList().size() > 200) { + asmEnable = false; + } + + Constructor defaultConstructor = beanInfo.getDefaultConstructor(); + if (defaultConstructor == null && !clazz.isInterface()) { + asmEnable = false; + } + + for (FieldInfo fieldInfo : beanInfo.getFieldList()) { + if (fieldInfo.isGetOnly()) { + asmEnable = false; + break; + } + + Class fieldClass = fieldInfo.getFieldClass(); + if (!Modifier.isPublic(fieldClass.getModifiers())) { + asmEnable = false; + break; + } + + if (fieldClass.isMemberClass() && !Modifier.isStatic(fieldClass.getModifiers())) { + asmEnable = false; + } + } + } + + if (asmEnable) { + if (clazz.isMemberClass() && !Modifier.isStatic(clazz.getModifiers())) { + asmEnable = false; + } + } + + if (!asmEnable) { + return new JavaBeanDeserializer(this, clazz, type); + } + + try { + return ASMDeserializerFactory.getInstance().createJavaBeanDeserializer(this, clazz, type); + // } catch (VerifyError e) { + // e.printStackTrace(); + // return new JavaBeanDeserializer(this, clazz, type); + } catch (ASMException asmError) { + return new JavaBeanDeserializer(this, clazz, type); + } catch (Exception e) { + throw new JSONException("create asm deserializer error, " + clazz.getName(), e); + } + } + + public FieldDeserializer createFieldDeserializer(ParserConfig mapping, Class clazz, FieldInfo fieldInfo) { + boolean asmEnable = this.asmEnable; + + if (asmEnable) { + Class superClass = clazz; + + for (;;) { + if(!Modifier.isPublic(superClass.getModifiers())) { + asmEnable = false; + break; + } + + superClass = superClass.getSuperclass(); + if (superClass == Object.class) { + break; + } + } + } + + if (fieldInfo.getFieldClass() == Class.class) { + asmEnable = false; + } + + if (ASMDeserializerFactory.getInstance().isExternalClass(clazz)) { + asmEnable = false; + } + + if (!asmEnable) { + return createFieldDeserializerWithoutASM(mapping, clazz, fieldInfo); + } + + try { + return ASMDeserializerFactory.getInstance().createFieldDeserializer(mapping, clazz, fieldInfo); + } catch (Throwable e) { + // skip + } + + return createFieldDeserializerWithoutASM(mapping, clazz, fieldInfo); + } + + public FieldDeserializer createFieldDeserializerWithoutASM(ParserConfig mapping, Class clazz, FieldInfo fieldInfo) { + Class fieldClass = fieldInfo.getFieldClass(); + + if (fieldClass == boolean.class || fieldClass == Boolean.class) { + return new BooleanFieldDeserializer(mapping, clazz, fieldInfo); + } + + if (fieldClass == int.class || fieldClass == Integer.class) { + return new IntegerFieldDeserializer(mapping, clazz, fieldInfo); + } + + if (fieldClass == long.class || fieldClass == Long.class) { + return new LongFieldDeserializer(mapping, clazz, fieldInfo); + } + + if (fieldClass == String.class) { + return new StringFieldDeserializer(mapping, clazz, fieldInfo); + } + + if (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) { + derializers.put(type, deserializer); + } + + public ObjectDeserializer getDeserializer(FieldInfo fieldInfo) { + return getDeserializer(fieldInfo.getFieldClass(), fieldInfo.getFieldType()); + } + + public boolean isPrimitive(Class clazz) { + return primitiveClasses.contains(clazz); + } + + public static Field getField(Class clazz, String fieldName) { + Field field = getField0(clazz, fieldName); + if (field == null) { + field = getField0(clazz, "_" + fieldName); + } + if (field == null) { + field = getField0(clazz, "m_" + fieldName); + } + return field; + } + + private static Field getField0(Class clazz, String fieldName) { + for (Field item : clazz.getDeclaredFields()) { + if (fieldName.equals(item.getName())) { + return item; + } + } + if (clazz.getSuperclass() != null && clazz.getSuperclass() != Object.class) { + return getField(clazz.getSuperclass(), fieldName); + } + + return null; + } + + public Map getFieldDeserializers(Class clazz) { + ObjectDeserializer deserizer = getDeserializer(clazz); + + if (deserizer instanceof JavaBeanDeserializer) { + return ((JavaBeanDeserializer) deserizer).getFieldDeserializerMap(); + } else if (deserizer instanceof ASMJavaBeanDeserializer) { + return ((ASMJavaBeanDeserializer) deserizer).getInnterSerializer().getFieldDeserializerMap(); + } else { + return Collections.emptyMap(); + } + } + +} diff --git a/src/test/java/com/alibaba/json/bvt/bug/Bug_for_yangqi.java b/src/test/java/com/alibaba/json/bvt/bug/Bug_for_yangqi.java new file mode 100644 index 000000000..cd6be8f07 --- /dev/null +++ b/src/test/java/com/alibaba/json/bvt/bug/Bug_for_yangqi.java @@ -0,0 +1,49 @@ +package com.alibaba.json.bvt.bug; + +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import com.alibaba.fastjson.JSON; + +public class Bug_for_yangqi extends TestCase { + + public void test_for_bug() throws Exception { + B b = JSON.parseObject("{\"id\":123,\"values\":[{}]}", B.class); + } + + abstract static class A { + + private int id; + private List values = new ArrayList(); + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + + public List getValues() { + return values; + } + + + public void setValues(List values) { + this.values = values; + } + + + } + + public static class B extends A { + + } + + public static class Value { + + } +}