Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.alibaba.dubbo.common.beanutil.JavaBeanSerializeUtil Maven / Gradle / Ivy
/*
* Copyright 1999-2012 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.dubbo.common.beanutil;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Map;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.LogHelper;
import com.alibaba.dubbo.common.utils.ReflectUtils;
/**
* @author kimi
*/
public final class JavaBeanSerializeUtil {
private static final Logger logger = LoggerFactory.getLogger(JavaBeanSerializeUtil.class);
public static JavaBeanDescriptor serialize(Object obj) {
JavaBeanDescriptor result = serialize(obj, JavaBeanAccessor.FIELD);
return result;
}
public static JavaBeanDescriptor serialize(Object obj, JavaBeanAccessor accessor) {
if (obj == null) {
return null;
}
if (obj instanceof JavaBeanDescriptor) {
return (JavaBeanDescriptor)obj;
}
IdentityHashMap cache = new IdentityHashMap();
JavaBeanDescriptor result = createDescriptorIfAbsent(obj, accessor, cache);
return result;
}
private static JavaBeanDescriptor createDescriptorForSerialize(Class> cl) {
if (cl.isEnum()) {
return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_ENUM);
} else if (cl.isArray()) {
return new JavaBeanDescriptor(cl.getComponentType().getName(), JavaBeanDescriptor.TYPE_ARRAY);
} else if (ReflectUtils.isPrimitive(cl)) {
return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_PRIMITIVE);
} else if (Class.class.equals(cl)) {
return new JavaBeanDescriptor(Class.class.getName(), JavaBeanDescriptor.TYPE_CLASS);
} else if (Collection.class.isAssignableFrom(cl)) {
return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_COLLECTION);
} else if (Map.class.isAssignableFrom(cl)) {
return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_MAP);
} else {
return new JavaBeanDescriptor(cl.getName(), JavaBeanDescriptor.TYPE_BEAN);
}
}
private static JavaBeanDescriptor createDescriptorIfAbsent(Object obj, JavaBeanAccessor accessor, IdentityHashMap cache) {
if (cache.containsKey(obj)) {
return cache.get(obj);
} else if (obj instanceof JavaBeanDescriptor) {
return (JavaBeanDescriptor)obj;
} else {
JavaBeanDescriptor result = createDescriptorForSerialize(obj.getClass());
cache.put(obj, result);
serializeInternal(result, obj, accessor, cache);
return result;
}
}
private static void serializeInternal(JavaBeanDescriptor descriptor, Object obj, JavaBeanAccessor accessor, IdentityHashMap cache) {
if (obj == null || descriptor == null) {
return;
}
if (obj.getClass().isEnum()) {
descriptor.setEnumNameProperty(((Enum>) obj).name());
} else if (ReflectUtils.isPrimitive(obj.getClass())) {
descriptor.setPrimitiveProperty(obj);
} else if (Class.class.equals(obj.getClass())) {
descriptor.setClassNameProperty(((Class>) obj).getName());
} else if (obj.getClass().isArray()) {
int len = Array.getLength(obj);
for (int i = 0; i < len; i++) {
Object item = Array.get(obj, i);
if (item == null) {
descriptor.setProperty(i, null);
} else {
JavaBeanDescriptor itemDescriptor = createDescriptorIfAbsent(item, accessor, cache);
descriptor.setProperty(i, itemDescriptor);
}
}
} else if (obj instanceof Collection) {
Collection collection = (Collection) obj;
int index = 0;
for (Object item : collection) {
if (item == null) {
descriptor.setProperty(index++, null);
} else {
JavaBeanDescriptor itemDescriptor = createDescriptorIfAbsent(item, accessor, cache);
descriptor.setProperty(index++, itemDescriptor);
}
}
} else if (obj instanceof Map) {
Map map = (Map) obj;
for (Object key : map.keySet()) {
Object value = map.get(key);
Object keyDescriptor = key == null ? null : createDescriptorIfAbsent(key, accessor, cache);
Object valueDescriptor = value == null ? null : createDescriptorIfAbsent(value, accessor, cache);
descriptor.setProperty(keyDescriptor, valueDescriptor);
} // ~ end of loop map
} else {
if (JavaBeanAccessor.isAccessByMethod(accessor)) {
Map methods = ReflectUtils.getBeanPropertyReadMethods(obj.getClass());
for (Map.Entry entry : methods.entrySet()) {
try {
Object value = entry.getValue().invoke(obj);
if (value == null) {
continue;
}
JavaBeanDescriptor valueDescriptor = createDescriptorIfAbsent(value, accessor, cache);
descriptor.setProperty(entry.getKey(), valueDescriptor);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
} // ~ end of loop method map
} // ~ end of if (JavaBeanAccessor.isAccessByMethod(accessor))
if (JavaBeanAccessor.isAccessByField(accessor)) {
Map fields = ReflectUtils.getBeanPropertyFields(obj.getClass());
for (Map.Entry entry : fields.entrySet()) {
if (!descriptor.containsProperty(entry.getKey())) {
try {
Object value = entry.getValue().get(obj);
if (value == null) {
continue;
}
JavaBeanDescriptor valueDescriptor = createDescriptorIfAbsent(value, accessor, cache);
descriptor.setProperty(entry.getKey(), valueDescriptor);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
} // ~ end of loop field map
} // ~ end of if (JavaBeanAccessor.isAccessByField(accessor))
} // ~ end of else
} // ~ end of method serializeInternal
public static Object deserialize(JavaBeanDescriptor beanDescriptor) {
Object result = deserialize(
beanDescriptor,
Thread.currentThread().getContextClassLoader());
return result;
}
public static Object deserialize(JavaBeanDescriptor beanDescriptor, ClassLoader loader) {
if (beanDescriptor == null) {
return null;
}
IdentityHashMap cache = new IdentityHashMap();
Object result = instantiateForDeserialize(beanDescriptor, loader, cache);
deserializeInternal(result, beanDescriptor, loader, cache);
return result;
}
private static void deserializeInternal(Object result, JavaBeanDescriptor beanDescriptor, ClassLoader loader, IdentityHashMap cache) {
if (beanDescriptor.isEnumType() || beanDescriptor.isClassType() || beanDescriptor.isPrimitiveType()) {
return;
}
if (beanDescriptor.isArrayType()) {
int index = 0;
for (Map.Entry entry : beanDescriptor) {
Object item = entry.getValue();
if (item instanceof JavaBeanDescriptor) {
JavaBeanDescriptor itemDescriptor = (JavaBeanDescriptor) entry.getValue();
item = instantiateForDeserialize(itemDescriptor, loader, cache);
deserializeInternal(item, itemDescriptor, loader, cache);
}
Array.set(result, index++, item);
}
} else if (beanDescriptor.isCollectionType()) {
Collection collection = (Collection) result;
for (Map.Entry entry : beanDescriptor) {
Object item = entry.getValue();
if (item instanceof JavaBeanDescriptor) {
JavaBeanDescriptor itemDescriptor = (JavaBeanDescriptor) entry.getValue();
item = instantiateForDeserialize(itemDescriptor, loader, cache);
deserializeInternal(item, itemDescriptor, loader, cache);
}
collection.add(item);
}
} else if (beanDescriptor.isMapType()) {
Map map = (Map) result;
for (Map.Entry entry : beanDescriptor) {
Object key = entry.getKey();
Object value = entry.getValue();
if (key != null && key instanceof JavaBeanDescriptor) {
JavaBeanDescriptor keyDescriptor = (JavaBeanDescriptor) entry.getKey();
key = instantiateForDeserialize(keyDescriptor, loader, cache);
deserializeInternal(key, keyDescriptor, loader, cache);
}
if (value != null && value instanceof JavaBeanDescriptor) {
JavaBeanDescriptor valueDescriptor = (JavaBeanDescriptor) entry.getValue();
value = instantiateForDeserialize(valueDescriptor, loader, cache);
deserializeInternal(value, valueDescriptor, loader, cache);
}
map.put(key, value);
}
} else if (beanDescriptor.isBeanType()) {
for (Map.Entry entry : beanDescriptor) {
String property = entry.getKey().toString();
Object value = entry.getValue();
if (value == null) {
continue;
}
if (value instanceof JavaBeanDescriptor) {
JavaBeanDescriptor valueDescriptor = (JavaBeanDescriptor) entry.getValue();
value = instantiateForDeserialize(valueDescriptor, loader, cache);
deserializeInternal(value, valueDescriptor, loader, cache);
}
Method method = getSetterMethod(result.getClass(), property, value.getClass());
boolean setByMethod = false;
try {
if (method != null) {
method.invoke(result, value);
setByMethod = true;
}
} catch (Exception e) {
LogHelper.warn(logger, "Failed to set property through method " + method, e);
}
if (!setByMethod) {
try {
Field field = result.getClass().getField(property);
if (field != null) {
field.set(result, value);
}
} catch (NoSuchFieldException e1) {
LogHelper.warn(logger, "Failed to set field value", e1);
} catch (IllegalAccessException e1) {
LogHelper.warn(logger, "Failed to set field value", e1);
}
}
}
} else {
throw new IllegalArgumentException("Unsupported type " + beanDescriptor.getClassName() + ":" + beanDescriptor.getType());
}
}
private static Method getSetterMethod(Class> cls, String property, Class> valueCls) {
String name = "set" + property.substring(0, 1).toUpperCase() + property.substring(1);
Method method = null;
try {
method = cls.getMethod(name, valueCls);
} catch (NoSuchMethodException e) {
for (Method m : cls.getMethods()) {
if (ReflectUtils.isBeanPropertyWriteMethod(m)
&& m.getName().equals(name)) {
method = m;
}
}
}
if (method != null) {
method.setAccessible(true);
}
return method;
}
private static Object instantiate(Class> cl) throws Exception {
Constructor>[] constructors = cl.getDeclaredConstructors();
Constructor> constructor = null;
int argc = Integer.MAX_VALUE;
for (Constructor> c : constructors) {
if (c.getParameterTypes().length < argc) {
argc = c.getParameterTypes().length;
constructor = c;
}
}
if (constructor != null) {
Class>[] paramTypes = constructor.getParameterTypes();
Object[] constructorArgs = new Object[paramTypes.length];
for (int i = 0; i < constructorArgs.length; i++) {
constructorArgs[i] = getConstructorArg(paramTypes[i]);
}
try {
constructor.setAccessible(true);
return constructor.newInstance(constructorArgs);
} catch (InstantiationException e) {
LogHelper.warn(logger, e.getMessage(), e);
} catch (IllegalAccessException e) {
LogHelper.warn(logger, e.getMessage(), e);
} catch (InvocationTargetException e) {
LogHelper.warn(logger, e.getMessage(), e);
}
}
return cl.newInstance();
}
private static Object getConstructorArg(Class> cl) {
if (boolean.class.equals(cl) || Boolean.class.equals(cl)) {
return Boolean.FALSE;
} else if (byte.class.equals(cl) || Byte.class.equals(cl)) {
return Byte.valueOf((byte) 0);
} else if (short.class.equals(cl) || Short.class.equals(cl)) {
return Short.valueOf((short) 0);
} else if (int.class.equals(cl) || Integer.class.equals(cl)) {
return Integer.valueOf(0);
} else if (long.class.equals(cl) || Long.class.equals(cl)) {
return Long.valueOf(0L);
} else if (float.class.equals(cl) || Float.class.equals(cl)) {
return Float.valueOf((float) 0);
} else if (double.class.equals(cl) || Double.class.equals(cl)) {
return Double.valueOf((double) 0);
} else if (char.class.equals(cl) || Character.class.equals(cl)) {
return new Character((char) 0);
} else {
return null;
}
}
private static Object instantiateForDeserialize(JavaBeanDescriptor beanDescriptor, ClassLoader loader, IdentityHashMap cache) {
if (cache.containsKey(beanDescriptor)) {
return cache.get(beanDescriptor);
}
Object result = null;
if (beanDescriptor.isClassType()) {
try {
result = name2Class(loader, beanDescriptor.getClassNameProperty());
return result;
} catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
} else if (beanDescriptor.isEnumType()) {
try {
Class> enumType = name2Class(loader, beanDescriptor.getClassName());
Method method = getEnumValueOfMethod(enumType);
result = method.invoke(null, enumType, beanDescriptor.getEnumPropertyName());
return result;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
} else if (beanDescriptor.isPrimitiveType()) {
result = beanDescriptor.getPrimitiveProperty();
return result;
} else if (beanDescriptor.isArrayType()) {
Class> componentType;
try {
componentType = name2Class(loader, beanDescriptor.getClassName());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
result = Array.newInstance(componentType, beanDescriptor.propertySize());
cache.put(beanDescriptor, result);
} else try {
Class> cl = name2Class(loader, beanDescriptor.getClassName());
result = instantiate(cl);
cache.put(beanDescriptor, result);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
return result;
}
private static final Map> TYPES = new HashMap>();
static {
TYPES.put(boolean.class.getName(), boolean.class);
TYPES.put(byte.class.getName(), byte.class);
TYPES.put(short.class.getName(), short.class);
TYPES.put(int.class.getName(), int.class);
TYPES.put(long.class.getName(), long.class);
TYPES.put(float.class.getName(), float.class);
TYPES.put(double.class.getName(), double.class);
TYPES.put(void.class.getName(), void.class);
TYPES.put("Z", boolean.class);
TYPES.put("B", byte.class);
TYPES.put("C", char.class);
TYPES.put("D", double.class);
TYPES.put("F", float.class);
TYPES.put("I", int.class);
TYPES.put("J", long.class);
TYPES.put("S", short.class);
}
private static final String ARRAY_PREFIX = "[";
private static final String REFERENCE_TYPE_PREFIX = "L";
private static final String REFERENCE_TYPE_SUFFIX = ";";
/**
* 把 Class.forName 的返回值转换为 Class.
*
* @param name Class.getName()
*
* @return Class
*
* @throws ClassNotFoundException Class.forName
*/
public static Class> name2Class(ClassLoader loader, String name) throws ClassNotFoundException {
if (TYPES.containsKey(name)) {
return TYPES.get(name);
}
if (isArray(name)) {
int dimension = 0;
while (isArray(name)) {
++dimension;
name = name.substring(1);
}
Class type = name2Class(loader, name);
int[] dimensions = new int[dimension];
for (int i = 0; i < dimension; i++) {
dimensions[i] = 0;
}
return Array.newInstance(type, dimensions).getClass();
}
if (isReferenceType(name)) {
name = name.substring(1, name.length() - 1);
}
return Class.forName(name, false, loader);
}
private static boolean isArray(String type) {
return type != null && type.startsWith(ARRAY_PREFIX);
}
private static boolean isReferenceType(String type) {
return type != null
&& type.startsWith(REFERENCE_TYPE_PREFIX)
&& type.endsWith(REFERENCE_TYPE_SUFFIX);
}
private static Method getEnumValueOfMethod(Class cl) throws NoSuchMethodException {
return cl.getMethod("valueOf", Class.class, String.class);
}
private JavaBeanSerializeUtil() {
}
}