/* * 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.util; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; 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.security.AccessControlException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONException; import com.alibaba.fastjson.JSONObject; import com.alibaba.fastjson.PropertyNamingStrategy; import com.alibaba.fastjson.annotation.JSONField; import com.alibaba.fastjson.annotation.JSONType; import com.alibaba.fastjson.parser.Feature; import com.alibaba.fastjson.parser.JSONScanner; import com.alibaba.fastjson.parser.ParserConfig; import com.alibaba.fastjson.parser.deserializer.JavaBeanDeserializer; import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer; import com.alibaba.fastjson.serializer.CalendarCodec; import com.alibaba.fastjson.serializer.DateCodec; import com.alibaba.fastjson.serializer.SerializeBeanInfo; import com.alibaba.fastjson.serializer.SerializerFeature; /** * @author wenshao[szujobs@hotmail.com] */ public class TypeUtils { public static boolean compatibleWithJavaBean = false; /** 根据field name的大小写输出输入数据*/ public static boolean compatibleWithFieldName = false; private static boolean setAccessibleEnable = true; private static boolean oracleTimestampMethodInited = false; private static Method oracleTimestampMethod; private static boolean oracleDateMethodInited = false; private static Method oracleDateMethod; private static boolean optionalClassInited = false; private static Class<?> optionalClass; private static boolean transientClassInited = false; private static Class<? extends Annotation> transientClass; private static Class<? extends Annotation> class_OneToMany = null; private static boolean class_OneToMany_error = false; private static Method method_HibernateIsInitialized = null; private static boolean method_HibernateIsInitialized_error = false; static { try { TypeUtils.compatibleWithJavaBean = "true".equals(IOUtils.getStringProperty(IOUtils.FASTJSON_COMPATIBLEWITHJAVABEAN)); TypeUtils.compatibleWithFieldName = "true".equals(IOUtils.getStringProperty(IOUtils.FASTJSON_COMPATIBLEWITHFIELDNAME)); } catch (Throwable e) { // skip } } public static String castToString(Object value) { if (value == null) { return null; } return value.toString(); } public static Byte castToByte(Object value) { if (value == null) { return null; } if (value instanceof Number) { return ((Number) value).byteValue(); } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } return Byte.parseByte(strVal); } throw new JSONException("can not cast to byte, value : " + value); } public static Character castToChar(Object value) { if (value == null) { return null; } if (value instanceof Character) { return (Character) value; } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0) { return null; } if (strVal.length() != 1) { throw new JSONException("can not cast to char, value : " + value); } return strVal.charAt(0); } throw new JSONException("can not cast to char, value : " + value); } public static Short castToShort(Object value) { if (value == null) { return null; } if (value instanceof Number) { return ((Number) value).shortValue(); } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } return Short.parseShort(strVal); } throw new JSONException("can not cast to short, value : " + value); } public static BigDecimal castToBigDecimal(Object value) { if (value == null) { return null; } if (value instanceof BigDecimal) { return (BigDecimal) value; } if (value instanceof BigInteger) { return new BigDecimal((BigInteger) value); } String strVal = value.toString(); if (strVal.length() == 0) { return null; } if (value instanceof Map && ((Map) value).size() == 0) { return null; } return new BigDecimal(strVal); } public static BigInteger castToBigInteger(Object value) { if (value == null) { return null; } if (value instanceof BigInteger) { return (BigInteger) value; } if (value instanceof Float || value instanceof Double) { return BigInteger.valueOf(((Number) value).longValue()); } String strVal = value.toString(); if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } return new BigInteger(strVal); } public static Float castToFloat(Object value) { if (value == null) { return null; } if (value instanceof Number) { return ((Number) value).floatValue(); } if (value instanceof String) { String strVal = value.toString(); if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if (strVal.indexOf(',') != 0) { strVal = strVal.replaceAll(",", ""); } return Float.parseFloat(strVal); } throw new JSONException("can not cast to float, value : " + value); } public static Double castToDouble(Object value) { if (value == null) { return null; } if (value instanceof Number) { return ((Number) value).doubleValue(); } if (value instanceof String) { String strVal = value.toString(); if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if (strVal.indexOf(',') != 0) { strVal = strVal.replaceAll(",", ""); } return Double.parseDouble(strVal); } throw new JSONException("can not cast to double, value : " + value); } public static Date castToDate(Object value) { if (value == null) { return null; } if (value instanceof Date) { // 使用频率最高的,应优先处理 return (Date) value; } if (value instanceof Calendar) { return ((Calendar) value).getTime(); } long longValue = -1; if (value instanceof Number) { longValue = ((Number) value).longValue(); return new Date(longValue); } if (value instanceof String) { String strVal = (String) value; JSONScanner dateLexer = new JSONScanner(strVal); try { if (dateLexer.scanISO8601DateIfMatch(false)) { Calendar calendar = dateLexer.getCalendar(); return calendar.getTime(); } } finally { dateLexer.close(); } if (strVal.startsWith("/Date(") && strVal.endsWith(")/")) { String dotnetDateStr = strVal.substring(6, strVal.length() - 2); strVal = dotnetDateStr; } if (strVal.indexOf('-') != -1) { String format; if (strVal.length() == JSON.DEFFAULT_DATE_FORMAT.length()) { format = JSON.DEFFAULT_DATE_FORMAT; } else if (strVal.length() == 10) { format = "yyyy-MM-dd"; } else if (strVal.length() == "yyyy-MM-dd HH:mm:ss".length()) { format = "yyyy-MM-dd HH:mm:ss"; } else { format = "yyyy-MM-dd HH:mm:ss.SSS"; } SimpleDateFormat dateFormat = new SimpleDateFormat(format, JSON.defaultLocale); dateFormat.setTimeZone(JSON.defaultTimeZone); try { return (Date) dateFormat.parse(strVal); } catch (ParseException e) { throw new JSONException("can not cast to Date, value : " + strVal); } } if (strVal.length() == 0) { return null; } longValue = Long.parseLong(strVal); } if (longValue < 0) { Class<?> clazz = value.getClass(); if ("oracle.sql.TIMESTAMP".equals(clazz.getName())) { if (oracleTimestampMethod == null && !oracleTimestampMethodInited) { try { oracleTimestampMethod = clazz.getMethod("toJdbc"); } catch (NoSuchMethodException e) { // skip } finally { oracleTimestampMethodInited = true; } } Object result; try { result = oracleTimestampMethod.invoke(value); } catch (Exception e) { throw new JSONException("can not cast oracle.sql.TIMESTAMP to Date", e); } return (Date) result; } if ("oracle.sql.DATE".equals(clazz.getName())) { if (oracleDateMethod == null && !oracleDateMethodInited) { try { oracleDateMethod = clazz.getMethod("toJdbc"); } catch (NoSuchMethodException e) { // skip } finally { oracleDateMethodInited = true; } } Object result; try { result = oracleDateMethod.invoke(value); } catch (Exception e) { throw new JSONException("can not cast oracle.sql.DATE to Date", e); } return (Date) result; } throw new JSONException("can not cast to Date, value : " + value); } return new Date(longValue); } public static java.sql.Date castToSqlDate(Object value) { if (value == null) { return null; } if (value instanceof java.sql.Date) { return (java.sql.Date) value; } if (value instanceof java.util.Date) { return new java.sql.Date(((java.util.Date) value).getTime()); } if (value instanceof Calendar) { return new java.sql.Date(((Calendar) value).getTimeInMillis()); } long longValue = 0; if (value instanceof Number) { longValue = ((Number) value).longValue(); } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if (isNumber(strVal)) { longValue = Long.parseLong(strVal); } else { JSONScanner scanner = new JSONScanner(strVal); if (scanner.scanISO8601DateIfMatch(false)) { longValue = scanner.getCalendar().getTime().getTime(); } else { throw new JSONException("can not cast to Timestamp, value : " + strVal); } } } if (longValue <= 0) { throw new JSONException("can not cast to Date, value : " + value); // TODO 忽略 1970-01-01 之前的时间处理? } return new java.sql.Date(longValue); } public static java.sql.Timestamp castToTimestamp(Object value) { if (value == null) { return null; } if (value instanceof Calendar) { return new java.sql.Timestamp(((Calendar) value).getTimeInMillis()); } if (value instanceof java.sql.Timestamp) { return (java.sql.Timestamp) value; } if (value instanceof java.util.Date) { return new java.sql.Timestamp(((java.util.Date) value).getTime()); } long longValue = 0; if (value instanceof Number) { longValue = ((Number) value).longValue(); } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if (isNumber(strVal)) { longValue = Long.parseLong(strVal); } else { JSONScanner scanner = new JSONScanner(strVal); if (scanner.scanISO8601DateIfMatch(false)) { longValue = scanner.getCalendar().getTime().getTime(); } else { throw new JSONException("can not cast to Timestamp, value : " + strVal); } } } if (longValue <= 0) { throw new JSONException("can not cast to Timestamp, value : " + value); } return new java.sql.Timestamp(longValue); } public static boolean isNumber(String str) { for (int i = 0; i < str.length(); ++i) { char ch = str.charAt(i); if (ch == '+' || ch == '-') { if (i != 0) { return false; } else { continue; } } else if (ch < '0' || ch > '9') { return false; } } return true; } public static Long castToLong(Object value) { if (value == null) { return null; } if (value instanceof Number) { return ((Number) value).longValue(); } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if (strVal.indexOf(',') != 0) { strVal = strVal.replaceAll(",", ""); } try { return Long.parseLong(strVal); } catch (NumberFormatException ex) { // } JSONScanner dateParser = new JSONScanner(strVal); Calendar calendar = null; if (dateParser.scanISO8601DateIfMatch(false)) { calendar = dateParser.getCalendar(); } dateParser.close(); if (calendar != null) { return calendar.getTimeInMillis(); } } if (value instanceof Map) { Map map = (Map) value; if (map.size() == 2 && map.containsKey("andIncrement") && map.containsKey("andDecrement")) { Iterator iter = map.values().iterator(); iter.next(); Object value2 = iter.next(); return castToLong(value2); } } throw new JSONException("can not cast to long, value : " + value); } public static Integer castToInt(Object value) { if (value == null) { return null; } if (value instanceof Integer) { return (Integer) value; } if (value instanceof Number) { return ((Number) value).intValue(); } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if (strVal.indexOf(',') != 0) { strVal = strVal.replaceAll(",", ""); } return Integer.parseInt(strVal); } if (value instanceof Boolean) { return ((Boolean) value).booleanValue() ? 1 : 0; } if (value instanceof Map) { Map map = (Map) value; if (map.size() == 2 && map.containsKey("andIncrement") && map.containsKey("andDecrement")) { Iterator iter = map.values().iterator(); iter.next(); Object value2 = iter.next(); return castToInt(value2); } } throw new JSONException("can not cast to int, value : " + value); } public static byte[] castToBytes(Object value) { if (value instanceof byte[]) { return (byte[]) value; } if (value instanceof String) { return IOUtils.decodeBase64((String) value); } throw new JSONException("can not cast to int, value : " + value); } public static Boolean castToBoolean(Object value) { if (value == null) { return null; } if (value instanceof Boolean) { return (Boolean) value; } if (value instanceof Number) { return ((Number) value).intValue() == 1; } if (value instanceof String) { String strVal = (String) value; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if ("true".equalsIgnoreCase(strVal) // || "1".equals(strVal)) { return Boolean.TRUE; } if ("false".equalsIgnoreCase(strVal) // || "0".equals(strVal)) { return Boolean.FALSE; } if ("Y".equalsIgnoreCase(strVal) // || "T".equals(strVal)) { return Boolean.TRUE; } if ("F".equalsIgnoreCase(strVal) // || "N".equals(strVal)) { return Boolean.FALSE; } } throw new JSONException("can not cast to boolean, value : " + value); } public static <T> T castToJavaBean(Object obj, Class<T> clazz) { return cast(obj, clazz, ParserConfig.getGlobalInstance()); } @SuppressWarnings({ "unchecked", "rawtypes" }) public static <T> T cast(Object obj, Class<T> clazz, ParserConfig config) { if (obj == null) { return null; } if (clazz == null) { throw new IllegalArgumentException("clazz is null"); } if (clazz == obj.getClass()) { return (T) obj; } if (obj instanceof Map) { if (clazz == Map.class) { return (T) obj; } Map map = (Map) obj; if (clazz == Object.class && !map.containsKey(JSON.DEFAULT_TYPE_KEY)) { return (T) obj; } return castToJavaBean((Map<String, Object>) obj, clazz, config); } if (clazz.isArray()) { if (obj instanceof Collection) { Collection collection = (Collection) obj; int index = 0; Object array = Array.newInstance(clazz.getComponentType(), collection.size()); for (Object item : collection) { Object value = cast(item, clazz.getComponentType(), config); Array.set(array, index, value); index++; } return (T) array; } if (clazz == byte[].class) { return (T) castToBytes(obj); } } if (clazz.isAssignableFrom(obj.getClass())) { return (T) obj; } if (clazz == boolean.class || clazz == Boolean.class) { return (T) castToBoolean(obj); } if (clazz == byte.class || clazz == Byte.class) { return (T) castToByte(obj); } // if (clazz == char.class || clazz == Character.class) { // return (T) castToCharacter(obj); // } if (clazz == short.class || clazz == Short.class) { return (T) castToShort(obj); } if (clazz == int.class || clazz == Integer.class) { return (T) castToInt(obj); } if (clazz == long.class || clazz == Long.class) { return (T) castToLong(obj); } if (clazz == float.class || clazz == Float.class) { return (T) castToFloat(obj); } if (clazz == double.class || clazz == Double.class) { return (T) castToDouble(obj); } if (clazz == String.class) { return (T) castToString(obj); } if (clazz == BigDecimal.class) { return (T) castToBigDecimal(obj); } if (clazz == BigInteger.class) { return (T) castToBigInteger(obj); } if (clazz == Date.class) { return (T) castToDate(obj); } if (clazz == java.sql.Date.class) { return (T) castToSqlDate(obj); } if (clazz == java.sql.Timestamp.class) { return (T) castToTimestamp(obj); } if (clazz.isEnum()) { return (T) castToEnum(obj, clazz, config); } if (Calendar.class.isAssignableFrom(clazz)) { Date date = castToDate(obj); Calendar calendar; if (clazz == Calendar.class) { calendar = Calendar.getInstance(JSON.defaultTimeZone, JSON.defaultLocale); } else { try { calendar = (Calendar) clazz.newInstance(); } catch (Exception e) { throw new JSONException("can not cast to : " + clazz.getName(), e); } } calendar.setTime(date); return (T) calendar; } if (clazz.getName().equals("javax.xml.datatype.XMLGregorianCalendar")) { Date date = castToDate(obj); Calendar calendar = Calendar.getInstance(JSON.defaultTimeZone, JSON.defaultLocale); calendar.setTime(date); return (T) CalendarCodec.instance.createXMLGregorianCalendar(calendar); } if (obj instanceof String) { String strVal = (String) obj; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } if (clazz == java.util.Currency.class) { return (T) java.util.Currency.getInstance(strVal); } if (clazz == java.util.Locale.class) { return (T) toLocale(strVal); } } throw new JSONException("can not cast to : " + clazz.getName()); } public static Locale toLocale(String strVal) { String[] items = strVal.split("_"); if (items.length == 1) { return new Locale(items[0]); } if (items.length == 2) { return new Locale(items[0], items[1]); } return new Locale(items[0], items[1], items[2]); } @SuppressWarnings({ "unchecked", "rawtypes" }) public static <T> T castToEnum(Object obj, Class<T> clazz, ParserConfig mapping) { try { if (obj instanceof String) { String name = (String) obj; if (name.length() == 0) { return null; } return (T) Enum.valueOf((Class<? extends Enum>) clazz, name); } if (obj instanceof Number) { int ordinal = ((Number) obj).intValue(); Object[] values = clazz.getEnumConstants(); if (ordinal < values.length) { return (T) values[ordinal]; } } } catch (Exception ex) { throw new JSONException("can not cast to : " + clazz.getName(), ex); } throw new JSONException("can not cast to : " + clazz.getName()); } @SuppressWarnings("unchecked") public static <T> T cast(Object obj, Type type, ParserConfig mapping) { if (obj == null) { return null; } if (type instanceof Class) { return (T) cast(obj, (Class<T>) type, mapping); } if (type instanceof ParameterizedType) { return (T) cast(obj, (ParameterizedType) type, mapping); } if (obj instanceof String) { String strVal = (String) obj; if (strVal.length() == 0 // || "null".equals(strVal) // || "NULL".equals(strVal)) { return null; } } if (type instanceof TypeVariable) { return (T) obj; } throw new JSONException("can not cast to : " + type); } @SuppressWarnings({ "rawtypes", "unchecked" }) public static <T> T cast(Object obj, ParameterizedType type, ParserConfig mapping) { Type rawTye = type.getRawType(); if (rawTye == Set.class || rawTye == HashSet.class // || rawTye == TreeSet.class // || rawTye == List.class // || rawTye == ArrayList.class) { Type itemType = type.getActualTypeArguments()[0]; if (obj instanceof Iterable) { Collection collection; if (rawTye == Set.class || rawTye == HashSet.class) { collection = new HashSet(); } else if (rawTye == TreeSet.class) { collection = new TreeSet(); } else { collection = new ArrayList(); } for (Iterator it = ((Iterable) obj).iterator(); it.hasNext();) { Object item = it.next(); collection.add(cast(item, itemType, mapping)); } return (T) collection; } } if (rawTye == Map.class || rawTye == HashMap.class) { Type keyType = type.getActualTypeArguments()[0]; Type valueType = type.getActualTypeArguments()[1]; if (obj instanceof Map) { Map map = new HashMap(); for (Map.Entry entry : ((Map<?, ?>) obj).entrySet()) { Object key = cast(entry.getKey(), keyType, mapping); Object value = cast(entry.getValue(), valueType, mapping); map.put(key, value); } return (T) map; } } if (obj instanceof String) { String strVal = (String) obj; if (strVal.length() == 0) { return null; } } if (type.getActualTypeArguments().length == 1) { Type argType = type.getActualTypeArguments()[0]; if (argType instanceof WildcardType) { return (T) cast(obj, rawTye, mapping); } } throw new JSONException("can not cast to : " + type); } @SuppressWarnings({ "unchecked" }) public static <T> T castToJavaBean(Map<String, Object> map, Class<T> clazz, ParserConfig config) { try { if (clazz == StackTraceElement.class) { String declaringClass = (String) map.get("className"); String methodName = (String) map.get("methodName"); String fileName = (String) map.get("fileName"); int lineNumber; { Number value = (Number) map.get("lineNumber"); if (value == null) { lineNumber = 0; } else { lineNumber = value.intValue(); } } return (T) new StackTraceElement(declaringClass, methodName, fileName, lineNumber); } { Object iClassObject = map.get(JSON.DEFAULT_TYPE_KEY); if (iClassObject instanceof String) { String className = (String) iClassObject; Class<?> loadClazz; if (config == null) { config = ParserConfig.global; } loadClazz = config.checkAutoType(className, null); if (loadClazz == null) { throw new ClassNotFoundException(className + " not found"); } if (!loadClazz.equals(clazz)) { return (T) castToJavaBean(map, loadClazz, config); } } } if (clazz.isInterface()) { JSONObject object; if (map instanceof JSONObject) { object = (JSONObject) map; } else { object = new JSONObject(map); } if (config == null) { config = ParserConfig.getGlobalInstance(); } ObjectDeserializer deserializer = config.getDeserializers().get(clazz); if (deserializer != null) { String json = JSON.toJSONString(object); return (T) JSON.parseObject(json, clazz); } return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[] { clazz }, object); } if (clazz == Locale.class) { Object arg0 = map.get("language"); Object arg1 = map.get("country"); if (arg0 instanceof String) { String language = (String) arg0; if (arg1 instanceof String) { String country = (String) arg1; return (T) new Locale(language, country); } else if (arg1 == null) { return (T) new Locale(language); } } } if (clazz == String.class && map instanceof JSONObject) { return (T) map.toString(); } if (config == null) { config = ParserConfig.getGlobalInstance(); } JavaBeanDeserializer javaBeanDeser = null; ObjectDeserializer deserizer = config.getDeserializer(clazz); if (deserizer instanceof JavaBeanDeserializer) { javaBeanDeser = (JavaBeanDeserializer) deserizer; } if (javaBeanDeser == null) { throw new JSONException("can not get javaBeanDeserializer. " + clazz.getName()); } return (T) javaBeanDeser.createInstance(map, config); } catch (Exception e) { throw new JSONException(e.getMessage(), e); } } private static ConcurrentMap<String, Class<?>> mappings = new ConcurrentHashMap<String, Class<?>>(16, 0.75f, 1); static { addBaseClassMappings(); } private static void addBaseClassMappings() { mappings.put("byte", byte.class); mappings.put("short", short.class); mappings.put("int", int.class); mappings.put("long", long.class); mappings.put("float", float.class); mappings.put("double", double.class); mappings.put("boolean", boolean.class); mappings.put("char", char.class); mappings.put("[byte", byte[].class); mappings.put("[short", short[].class); mappings.put("[int", int[].class); mappings.put("[long", long[].class); mappings.put("[float", float[].class); mappings.put("[double", double[].class); mappings.put("[boolean", boolean[].class); mappings.put("[char", char[].class); mappings.put("[B", byte[].class); mappings.put("[S", short[].class); mappings.put("[I", int[].class); mappings.put("[J", long[].class); mappings.put("[F", float[].class); mappings.put("[D", double[].class); mappings.put("[C", char[].class); mappings.put("[Z", boolean[].class); Class<?>[] classes = new Class[] { Object.class, java.lang.Cloneable.class, loadClass("java.lang.AutoCloseable"), java.lang.Exception.class, java.lang.RuntimeException.class, java.lang.IllegalAccessError.class, java.lang.IllegalAccessException.class, java.lang.IllegalArgumentException.class, java.lang.IllegalMonitorStateException.class, java.lang.IllegalStateException.class, java.lang.IllegalThreadStateException.class, java.lang.IndexOutOfBoundsException.class, java.lang.InstantiationError.class, java.lang.InstantiationException.class, java.lang.InternalError.class, java.lang.InterruptedException.class, java.lang.LinkageError.class, java.lang.NegativeArraySizeException.class, java.lang.NoClassDefFoundError.class, java.lang.NoSuchFieldError.class, java.lang.NoSuchFieldException.class, java.lang.NoSuchMethodError.class, java.lang.NoSuchMethodException.class, java.lang.NullPointerException.class, java.lang.NumberFormatException.class, java.lang.OutOfMemoryError.class, java.lang.SecurityException.class, java.lang.StackOverflowError.class, java.lang.StringIndexOutOfBoundsException.class, java.lang.TypeNotPresentException.class, java.lang.VerifyError.class, java.lang.StackTraceElement.class, java.util.HashMap.class, java.util.Hashtable.class, java.util.TreeMap.class, java.util.IdentityHashMap.class, java.util.WeakHashMap.class, java.util.LinkedHashMap.class, java.util.HashSet.class, java.util.LinkedHashSet.class, java.util.TreeSet.class, java.util.concurrent.TimeUnit.class, java.util.concurrent.ConcurrentHashMap.class, loadClass("java.util.concurrent.ConcurrentSkipListMap"), loadClass("java.util.concurrent.ConcurrentSkipListSet"), java.util.concurrent.atomic.AtomicInteger.class, java.util.concurrent.atomic.AtomicLong.class, java.util.Collections.EMPTY_MAP.getClass(), java.util.BitSet.class, java.util.Calendar.class, java.util.Date.class, java.util.Locale.class, java.util.UUID.class, java.sql.Time.class, java.sql.Date.class, java.sql.Timestamp.class, java.text.SimpleDateFormat.class, com.alibaba.fastjson.JSONObject.class, loadClass("java.awt.Rectangle"), loadClass("java.awt.Point"), loadClass("java.awt.Font"), loadClass("java.awt.Color"), loadClass("org.springframework.remoting.support.RemoteInvocation"), loadClass("org.springframework.remoting.support.RemoteInvocationResult"), }; for (Class clazz : classes) { if (clazz == null) { continue; } mappings.put(clazz.getName(), clazz); } } public static void clearClassMapping() { mappings.clear(); addBaseClassMappings(); } public static Class<?> loadClass(String className) { return loadClass(className, null); } private static Class<?> pathClass; private static boolean pathClass_error = false; public static boolean isPath(Class<?> clazz) { if (pathClass == null && !pathClass_error) { try { pathClass = Class.forName("java.nio.file.Path"); } catch (Throwable ex) { pathClass_error = true; } } if (pathClass != null) { return pathClass.isAssignableFrom(clazz); } return false; } public static Class<?> getClassFromMapping(String className) { return mappings.get(className); } public static Class<?> loadClass(String className, ClassLoader classLoader) { if (className == null || className.length() == 0) { return null; } Class<?> clazz = mappings.get(className); if (clazz != null) { return clazz; } if (className.charAt(0) == '[') { Class<?> componentType = loadClass(className.substring(1), classLoader); return Array.newInstance(componentType, 0).getClass(); } if (className.startsWith("L") && className.endsWith(";")) { String newClassName = className.substring(1, className.length() - 1); return loadClass(newClassName, classLoader); } try { if (classLoader != null) { clazz = classLoader.loadClass(className); mappings.put(className, clazz); return clazz; } } catch (Throwable e) { e.printStackTrace(); // skip } try { ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null && contextClassLoader != classLoader) { clazz = contextClassLoader.loadClass(className); mappings.put(className, clazz); return clazz; } } catch (Throwable e) { // skip } try { clazz = Class.forName(className); mappings.put(className, clazz); return clazz; } catch (Throwable e) { // skip } return clazz; } public static SerializeBeanInfo buildBeanInfo(Class<?> beanType // , Map<String, String> aliasMap // , PropertyNamingStrategy propertyNamingStrategy) { return buildBeanInfo(beanType, aliasMap, propertyNamingStrategy, false); } public static SerializeBeanInfo buildBeanInfo(Class<?> beanType // , Map<String, String> aliasMap // , PropertyNamingStrategy propertyNamingStrategy // , boolean fieldBased // ) { JSONType jsonType = beanType.getAnnotation(JSONType.class); // fieldName,field ,先生成fieldName的快照,减少之后的findField的轮询 Map<String, Field> fieldCacheMap = new HashMap<String, Field>(); ParserConfig.parserAllFieldToCache(beanType, fieldCacheMap); List<FieldInfo> fieldInfoList = fieldBased ? computeGettersWithFieldBase(beanType, aliasMap, false, propertyNamingStrategy) // : computeGetters(beanType, jsonType, aliasMap, fieldCacheMap, false, propertyNamingStrategy); FieldInfo[] fields = new FieldInfo[fieldInfoList.size()]; fieldInfoList.toArray(fields); String[] orders = null; final int features; String typeName = null; if (jsonType != null) { orders = jsonType.orders(); typeName = jsonType.typeName(); if (typeName.length() == 0) { typeName = null; } features = SerializerFeature.of(jsonType.serialzeFeatures()); } else { features = 0; } FieldInfo[] sortedFields; List<FieldInfo> sortedFieldList; if (orders != null && orders.length != 0) { sortedFieldList = fieldBased ? computeGettersWithFieldBase(beanType, aliasMap, true, propertyNamingStrategy) // : computeGetters(beanType, jsonType, aliasMap,fieldCacheMap, true, propertyNamingStrategy); } else { sortedFieldList = new ArrayList<FieldInfo>(fieldInfoList); Collections.sort(sortedFieldList); } sortedFields = new FieldInfo[sortedFieldList.size()]; sortedFieldList.toArray(sortedFields); if (Arrays.equals(sortedFields, fields)) { sortedFields = fields; } return new SerializeBeanInfo(beanType, jsonType, typeName, features, fields, sortedFields); } public static List<FieldInfo> computeGettersWithFieldBase( Class<?> clazz, // Map<String, String> aliasMap, // boolean sorted, // PropertyNamingStrategy propertyNamingStrategy) { Map<String, FieldInfo> fieldInfoMap = new LinkedHashMap<String, FieldInfo>(); for (Class<?> currentClass = clazz; currentClass != null; currentClass = currentClass.getSuperclass()) { Field[] fields = currentClass.getDeclaredFields(); computeFields(currentClass, aliasMap, propertyNamingStrategy, fieldInfoMap, fields); } return getFieldInfos(clazz, sorted, fieldInfoMap); } public static List<FieldInfo> computeGetters(Class<?> clazz, Map<String, String> aliasMap) { return computeGetters(clazz, aliasMap, true); } public static List<FieldInfo> computeGetters(Class<?> clazz, Map<String, String> aliasMap, boolean sorted) { JSONType jsonType = clazz.getAnnotation(JSONType.class); Map<String, Field> fieldCacheMap = new HashMap<String, Field>(); ParserConfig.parserAllFieldToCache(clazz, fieldCacheMap); return computeGetters(clazz, jsonType, aliasMap, fieldCacheMap, sorted, PropertyNamingStrategy.CamelCase); } public static List<FieldInfo> computeGetters(Class<?> clazz, // JSONType jsonType, // Map<String, String> aliasMap, // Map<String, Field> fieldCacheMap, // boolean sorted, // PropertyNamingStrategy propertyNamingStrategy // ) { Map<String, FieldInfo> fieldInfoMap = new LinkedHashMap<String, FieldInfo>(); for (Method method : clazz.getMethods()) { String methodName = method.getName(); int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0; String label = null; if (Modifier.isStatic(method.getModifiers())) { continue; } if (method.getReturnType().equals(Void.TYPE)) { continue; } if (method.getParameterTypes().length != 0) { continue; } if (method.getReturnType() == ClassLoader.class) { continue; } if (method.getName().equals("getMetaClass") && method.getReturnType().getName().equals("groovy.lang.MetaClass")) { continue; } JSONField annotation = method.getAnnotation(JSONField.class); if (annotation == null) { annotation = getSuperMethodAnnotation(clazz, method); } if (annotation != null) { if (!annotation.serialize()) { continue; } ordinal = annotation.ordinal(); serialzeFeatures = SerializerFeature.of(annotation.serialzeFeatures()); parserFeatures = Feature.of(annotation.parseFeatures()); if (annotation.name().length() != 0) { String propertyName = annotation.name(); if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } FieldInfo fieldInfo = new FieldInfo(propertyName, method, null, clazz, null, ordinal, serialzeFeatures, parserFeatures, annotation, null, label); fieldInfoMap.put(propertyName, fieldInfo); continue; } if (annotation.label().length() != 0) { label = annotation.label(); } } if (methodName.startsWith("get")) { if (methodName.length() < 4) { continue; } if (methodName.equals("getClass")) { continue; } if (methodName.equals("getDeclaringClass") && clazz.isEnum()) { continue; } char c3 = methodName.charAt(3); String propertyName; if (Character.isUpperCase(c3) // || c3 > 512 // for unicode method name ) { if (compatibleWithJavaBean) { propertyName = decapitalize(methodName.substring(3)); } else { propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); } propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName,3); } else if (c3 == '_') { propertyName = methodName.substring(4); } else if (c3 == 'f') { propertyName = methodName.substring(3); } else if (methodName.length() >= 5 && Character.isUpperCase(methodName.charAt(4))) { propertyName = decapitalize(methodName.substring(3)); } else { continue; } boolean ignore = isJSONTypeIgnore(clazz, propertyName); if (ignore) { continue; } //假如bean的field很多的情况一下,轮询时将大大降低效率 Field field = ParserConfig.getFieldFromCache(propertyName, fieldCacheMap); if (field == null && propertyName.length() > 1) { char ch = propertyName.charAt(1); if (ch >= 'A' && ch <= 'Z') { String javaBeanCompatiblePropertyName = decapitalize(methodName.substring(3)); field = ParserConfig.getFieldFromCache(javaBeanCompatiblePropertyName, fieldCacheMap); } } JSONField fieldAnnotation = null; if (field != null) { fieldAnnotation = field.getAnnotation(JSONField.class); if (fieldAnnotation != null) { if (!fieldAnnotation.serialize()) { continue; } ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } } if (fieldAnnotation.label().length() != 0) { label = fieldAnnotation.label(); } } } if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } if (propertyNamingStrategy != null) { propertyName = propertyNamingStrategy.translate(propertyName); } FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures, annotation, fieldAnnotation, label); fieldInfoMap.put(propertyName, fieldInfo); } if (methodName.startsWith("is")) { if (methodName.length() < 3) { continue; } if (method.getReturnType() != Boolean.TYPE && method.getReturnType() != Boolean.class) { continue; } char c2 = methodName.charAt(2); String propertyName; if (Character.isUpperCase(c2)) { if (compatibleWithJavaBean) { propertyName = decapitalize(methodName.substring(2)); } else { propertyName = Character.toLowerCase(methodName.charAt(2)) + methodName.substring(3); } propertyName = getPropertyNameByCompatibleFieldName(fieldCacheMap, methodName, propertyName,2); } else if (c2 == '_') { propertyName = methodName.substring(3); } else if (c2 == 'f') { propertyName = methodName.substring(2); } else { continue; } boolean ignore = isJSONTypeIgnore(clazz, propertyName); if (ignore) { continue; } Field field = ParserConfig.getFieldFromCache(propertyName,fieldCacheMap); if (field == null) { field = ParserConfig.getFieldFromCache(methodName,fieldCacheMap); } JSONField fieldAnnotation = null; if (field != null) { fieldAnnotation = field.getAnnotation(JSONField.class); if (fieldAnnotation != null) { if (!fieldAnnotation.serialize()) { continue; } ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } } if (fieldAnnotation.label().length() != 0) { label = fieldAnnotation.label(); } } } if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } if (propertyNamingStrategy != null) { propertyName = propertyNamingStrategy.translate(propertyName); } //优先选择get if (fieldInfoMap.containsKey(propertyName)) { continue; } FieldInfo fieldInfo = new FieldInfo(propertyName, method, field, clazz, null, ordinal, serialzeFeatures, parserFeatures, annotation, fieldAnnotation, label); fieldInfoMap.put(propertyName, fieldInfo); } } Field[] fields = clazz.getFields(); computeFields(clazz, aliasMap, propertyNamingStrategy, fieldInfoMap, fields); return getFieldInfos(clazz, sorted, fieldInfoMap); } private static List<FieldInfo> getFieldInfos(Class<?> clazz, boolean sorted, Map<String, FieldInfo> fieldInfoMap) { List<FieldInfo> fieldInfoList = new ArrayList<FieldInfo>(); boolean containsAll = false; String[] orders = null; JSONType annotation = clazz.getAnnotation(JSONType.class); if (annotation != null) { orders = annotation.orders(); if (orders != null && orders.length == fieldInfoMap.size()) { containsAll = true; for (String item : orders) { if (!fieldInfoMap.containsKey(item)) { containsAll = false; break; } } } else { containsAll = false; } } if (containsAll) { for (String item : orders) { FieldInfo fieldInfo = fieldInfoMap.get(item); fieldInfoList.add(fieldInfo); } } else { for (FieldInfo fieldInfo : fieldInfoMap.values()) { fieldInfoList.add(fieldInfo); } if (sorted) { Collections.sort(fieldInfoList); } } return fieldInfoList; } private static void computeFields( Class<?> clazz, // Map<String, String> aliasMap, // PropertyNamingStrategy propertyNamingStrategy, // Map<String, FieldInfo> fieldInfoMap, // Field[] fields) { for (Field field : fields) { if (Modifier.isStatic(field.getModifiers())) { continue; } JSONField fieldAnnotation = field.getAnnotation(JSONField.class); int ordinal = 0, serialzeFeatures = 0, parserFeatures = 0; String propertyName = field.getName(); String label = null; if (fieldAnnotation != null) { if (!fieldAnnotation.serialize()) { continue; } ordinal = fieldAnnotation.ordinal(); serialzeFeatures = SerializerFeature.of(fieldAnnotation.serialzeFeatures()); parserFeatures = Feature.of(fieldAnnotation.parseFeatures()); if (fieldAnnotation.name().length() != 0) { propertyName = fieldAnnotation.name(); } if (fieldAnnotation.label().length() != 0) { label = fieldAnnotation.label(); } } if (aliasMap != null) { propertyName = aliasMap.get(propertyName); if (propertyName == null) { continue; } } if (propertyNamingStrategy != null) { propertyName = propertyNamingStrategy.translate(propertyName); } if (!fieldInfoMap.containsKey(propertyName)) { FieldInfo fieldInfo = new FieldInfo(propertyName, null, field, clazz, null, ordinal, serialzeFeatures, parserFeatures, null, fieldAnnotation, label); fieldInfoMap.put(propertyName, fieldInfo); } } } private static String getPropertyNameByCompatibleFieldName(Map<String, Field> fieldCacheMap, String methodName, String propertyName,int fromIdx) { if (compatibleWithFieldName){ if (!fieldCacheMap.containsKey(propertyName)){ String tempPropertyName=methodName.substring(fromIdx); return fieldCacheMap.containsKey(tempPropertyName)?tempPropertyName:propertyName; } } return propertyName; } public static JSONField getSuperMethodAnnotation(final Class<?> clazz, final Method method) { Class<?>[] interfaces = clazz.getInterfaces(); if (interfaces.length > 0) { Class<?>[] types = method.getParameterTypes(); for (Class<?> interfaceClass : interfaces) { for (Method interfaceMethod : interfaceClass.getMethods()) { Class<?>[] interfaceTypes = interfaceMethod.getParameterTypes(); if (interfaceTypes.length != types.length) { continue; } if (!interfaceMethod.getName().equals(method.getName())) { continue; } boolean match = true; for (int i = 0; i < types.length; ++i) { if (!interfaceTypes[i].equals(types[i])) { match = false; break; } } if (!match) { continue; } JSONField annotation = interfaceMethod.getAnnotation(JSONField.class); if (annotation != null) { return annotation; } } } } Class<?> superClass = clazz.getSuperclass(); if (superClass == null) { return null; } if (Modifier.isAbstract(superClass.getModifiers())) { Class<?>[] types = method.getParameterTypes(); for (Method interfaceMethod : superClass.getMethods()) { Class<?>[] interfaceTypes = interfaceMethod.getParameterTypes(); if (interfaceTypes.length != types.length) { continue; } if (!interfaceMethod.getName().equals(method.getName())) { continue; } boolean match = true; for (int i = 0; i < types.length; ++i) { if (!interfaceTypes[i].equals(types[i])) { match = false; break; } } if (!match) { continue; } JSONField annotation = interfaceMethod.getAnnotation(JSONField.class); if (annotation != null) { return annotation; } } } return null; } private static boolean isJSONTypeIgnore(Class<?> clazz, String propertyName) { JSONType jsonType = clazz.getAnnotation(JSONType.class); if (jsonType != null) { // 1、新增 includes 支持,如果 JSONType 同时设置了includes 和 ignores 属性,则以includes为准。 // 2、个人认为对于大小写敏感的Java和JS而言,使用 equals() 比 equalsIgnoreCase() 更好,改动的唯一风险就是向后兼容性的问题 // 不过,相信开发者应该都是严格按照大小写敏感的方式进行属性设置的 String[] fields = jsonType.includes(); if (fields.length > 0) { for (int i = 0; i < fields.length; i++) { if (propertyName.equals(fields[i])) { return false; } } return true; } else { fields = jsonType.ignores(); for (int i = 0; i < fields.length; i++) { if (propertyName.equals(fields[i])) { return true; } } } } if (clazz.getSuperclass() != Object.class && clazz.getSuperclass() != null) { if (isJSONTypeIgnore(clazz.getSuperclass(), propertyName)) { return true; } } return false; } public static boolean isGenericParamType(Type type) { if (type instanceof ParameterizedType) { return true; } if (type instanceof Class) { Type superType = ((Class<?>) type).getGenericSuperclass(); if (superType == Object.class) { return false; } return isGenericParamType(superType); } return false; } public static Type getGenericParamType(Type type) { if (type instanceof ParameterizedType) { return type; } if (type instanceof Class) { return getGenericParamType(((Class<?>) type).getGenericSuperclass()); } return type; } public static Type unwrapOptional(Type type) { if (!optionalClassInited) { try { optionalClass = Class.forName("java.util.Optional"); } catch (Exception e) { // skip } finally { optionalClassInited = true; } } if (type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType) type; if (parameterizedType.getRawType() == optionalClass) { return parameterizedType.getActualTypeArguments()[0]; } } return type; } public static Class<?> getClass(Type type) { if (type.getClass() == Class.class) { return (Class<?>) type; } if (type instanceof ParameterizedType) { return getClass(((ParameterizedType) type).getRawType()); } if (type instanceof TypeVariable) { Type boundType = ((TypeVariable<?>) type).getBounds()[0]; return (Class<?>) boundType; } return Object.class; } public static Field getField(Class<?> clazz, String fieldName, Field[] declaredFields) { for (Field field : declaredFields) { if (fieldName.equals(field.getName())) { return field; } } Class<?> superClass = clazz.getSuperclass(); if (superClass != null && superClass != Object.class) { return getField(superClass, fieldName, superClass.getDeclaredFields()); } return null; } public static int getSerializeFeatures(Class<?> clazz) { JSONType annotation = clazz.getAnnotation(JSONType.class); if (annotation == null) { return 0; } return SerializerFeature.of(annotation.serialzeFeatures()); } public static int getParserFeatures(Class<?> clazz) { JSONType annotation = clazz.getAnnotation(JSONType.class); if (annotation == null) { return 0; } return Feature.of(annotation.parseFeatures()); } public static String decapitalize(String name) { if (name == null || name.length() == 0) { return name; } if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) && Character.isUpperCase(name.charAt(0))) { return name; } char chars[] = name.toCharArray(); chars[0] = Character.toLowerCase(chars[0]); return new String(chars); } static void setAccessible(AccessibleObject obj) { if (!setAccessibleEnable) { return; } if (obj.isAccessible()) { return; } try { obj.setAccessible(true); } catch (AccessControlException error) { setAccessibleEnable = false; } } public static Type getCollectionItemType(Type fieldType) { Type itemType = null; Class<?> clazz = null; if (fieldType instanceof ParameterizedType) { Type actualTypeArgument = ((ParameterizedType) fieldType).getActualTypeArguments()[0]; if (actualTypeArgument instanceof WildcardType) { WildcardType wildcardType = (WildcardType) actualTypeArgument; Type[] upperBounds = wildcardType.getUpperBounds(); if (upperBounds.length == 1) { actualTypeArgument = upperBounds[0]; } } itemType = actualTypeArgument; } else if (fieldType instanceof Class<?> // && !(clazz = (Class<?>) fieldType).getName().startsWith("java.")) { Type superClass = clazz.getGenericSuperclass(); itemType = TypeUtils.getCollectionItemType(superClass); } if (itemType == null) { itemType = Object.class; } return itemType; } public static Class<?> getCollectionItemClass(Type fieldType) { if (fieldType instanceof ParameterizedType) { Class<?> itemClass; Type actualTypeArgument = ((ParameterizedType) fieldType).getActualTypeArguments()[0]; if (actualTypeArgument instanceof WildcardType) { WildcardType wildcardType = (WildcardType) actualTypeArgument; Type[] upperBounds = wildcardType.getUpperBounds(); if (upperBounds.length == 1) { actualTypeArgument = upperBounds[0]; } } if (actualTypeArgument instanceof Class) { itemClass = (Class<?>) actualTypeArgument; if (!Modifier.isPublic(itemClass.getModifiers())) { throw new JSONException("can not create ASMParser"); } } else { throw new JSONException("can not create ASMParser"); } return itemClass; } return Object.class; } @SuppressWarnings({ "rawtypes", "unchecked" }) public static Collection createCollection(Type type) { Class<?> rawClass = getRawClass(type); Collection list; if (rawClass == AbstractCollection.class // || rawClass == Collection.class) { list = new ArrayList(); } else if (rawClass.isAssignableFrom(HashSet.class)) { list = new HashSet(); } else if (rawClass.isAssignableFrom(LinkedHashSet.class)) { list = new LinkedHashSet(); } else if (rawClass.isAssignableFrom(TreeSet.class)) { list = new TreeSet(); } else if (rawClass.isAssignableFrom(ArrayList.class)) { list = new ArrayList(); } else if (rawClass.isAssignableFrom(EnumSet.class)) { Type itemType; if (type instanceof ParameterizedType) { itemType = ((ParameterizedType) type).getActualTypeArguments()[0]; } else { itemType = Object.class; } list = EnumSet.noneOf((Class<Enum>) itemType); } else { try { list = (Collection) rawClass.newInstance(); } catch (Exception e) { throw new JSONException("create instance error, class " + rawClass.getName()); } } return list; } public static Class<?> getRawClass(Type type) { if (type instanceof Class<?>) { return (Class<?>) type; } else if (type instanceof ParameterizedType) { return getRawClass(((ParameterizedType) type).getRawType()); } else { throw new JSONException("TODO"); } } public static boolean isProxy(Class<?> clazz) { for (Class<?> item : clazz.getInterfaces()) { String interfaceName = item.getName(); if (interfaceName.equals("net.sf.cglib.proxy.Factory") // || interfaceName.equals("org.springframework.cglib.proxy.Factory")) { return true; } if (interfaceName.equals("javassist.util.proxy.ProxyObject") // || interfaceName.equals("org.apache.ibatis.javassist.util.proxy.ProxyObject") ) { return true; } } return false; } public static boolean isTransient(Method method) { if (method == null) { return false; } if (!transientClassInited) { try { transientClass = (Class<? extends Annotation>) Class.forName("java.beans.Transient"); } catch (Exception e) { // skip } finally { transientClassInited = true; } } if (transientClass != null) { Annotation annotation = method.getAnnotation(transientClass); return annotation != null; } return false; } public static boolean isAnnotationPresentOneToMany(Method method) { if (method == null) { return false; } if (class_OneToMany == null && !class_OneToMany_error) { try { class_OneToMany = (Class<? extends Annotation>) Class.forName("javax.persistence.OneToMany"); } catch (Throwable e) { // skip class_OneToMany_error = true; } } if (class_OneToMany == null) { return false; } return method.isAnnotationPresent(class_OneToMany); } public static boolean isHibernateInitialized(Object object) { if (object == null) { return false; } if (method_HibernateIsInitialized == null && !method_HibernateIsInitialized_error) { try { Class<?> class_Hibernate = (Class<? extends Annotation>) Class.forName("org.hibernate.Hibernate"); method_HibernateIsInitialized = class_Hibernate.getMethod("isInitialized", Object.class); } catch (Throwable e) { // skip method_HibernateIsInitialized_error = true; } } if (method_HibernateIsInitialized != null) { try { Boolean initialized = (Boolean) method_HibernateIsInitialized.invoke(null, object); return initialized.booleanValue(); } catch (Throwable e) { // skip } } return true; } }