/** * <pre> * This program is free software; you can redistribute it and/or modify it under the terms of * the GNU AFFERO GENERAL PUBLIC LICENSE as published by the Free Software Foundation; either version 3 of the License, * or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU AFFERO GENERAL PUBLIC LICENSE for more details. * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE along with this program; * if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * </pre> */ package com.meidusa.amoeba.config; import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.File; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import com.meidusa.amoeba.util.StringUtil; /** * @author <a href=mailto:piratebase@sina.com>Struct chen</a> * @version $Id: ParameterMapping.java 4004 2007-05-31 03:27:21Z struct $ */ public class ParameterMapping { private static Logger logger = Logger.getLogger(ParameterMapping.class); private static Map<Class<?>, PropertyDescriptor[]> propertyDescriptorMap = new HashMap<Class<?>, PropertyDescriptor[]>(); private static Map<Class<?>,PropertyTransfer<?>> stringTransferMap = new HashMap<Class<?>,PropertyTransfer<?>>(); public static void registerTransfer(Class<?> type,PropertyTransfer<?> transfer){ stringTransferMap.put(type,transfer); } public static PropertyTransfer<?> lookup(Class fieldType){ for(Map.Entry<Class<?>,PropertyTransfer<?>> entry :stringTransferMap.entrySet()){ try{ Class clazz = entry.getKey(); if(clazz.equals(fieldType) || clazz.asSubclass(fieldType) != null){ return entry.getValue(); } }catch(ClassCastException e){ } } return null; } private static PropertyDescriptor[] getDescriptors(Class<?> clazz) { PropertyDescriptor[] descriptors; List<PropertyDescriptor> list; PropertyDescriptor[] mDescriptors = (PropertyDescriptor[]) propertyDescriptorMap.get(clazz); if (null == mDescriptors) { try { descriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); list = new ArrayList<PropertyDescriptor>(); for (int i = 0; i < descriptors.length; i++) { if (null != descriptors[i].getPropertyType()) { list.add(descriptors[i]); } } mDescriptors = new PropertyDescriptor[list.size()]; list.toArray(mDescriptors); } catch (IntrospectionException ie) { ie.printStackTrace(); mDescriptors = new PropertyDescriptor[0]; } } propertyDescriptorMap.put(clazz, mDescriptors); return (mDescriptors); } public static void mappingObject(Object object, Map<String, Object> parameter,Map<String,Object> context) { PropertyDescriptor[] descriptors = getDescriptors(object.getClass()); for (int i = 0; i < descriptors.length; i++) { Object obj = parameter.get(descriptors[i].getName()); Object value = obj; Class<?> cls = descriptors[i].getPropertyType(); if (obj instanceof String) { if (isPrimitiveType(cls)) { String string = (String) obj; if (!StringUtil.isEmpty(string)) { string = ConfigUtil.filter(string); } value = deStringize(cls, string); }else if(cls.equals(File.class)){ String string = (String) obj; if (!StringUtil.isEmpty(string)) { string = ConfigUtil.filter(string); } value = new File(string); }else { if(context != null){ if(obj != null){ String key = StringUtil.split(((String)obj).trim(), "${}")[0]; value = context.get(key); if(value == null){ if (logger.isInfoEnabled()) { logger.info(object.getClass() + "@" + descriptors[i].getName() + ", bean name="+key+" not found! "); } } } } } } else if (obj instanceof BeanObjectEntityConfig) { value = newBean((BeanObjectEntityConfig) obj,context); } else if (obj instanceof BeanObjectEntityConfig[]) { List<Object> list = new ArrayList<Object>(); for (BeanObjectEntityConfig beanconfig : (BeanObjectEntityConfig[]) obj) { list.add(newBean(beanconfig,context)); } value = list.toArray(); } if (cls != null) { try { if (value != null) { Method method = descriptors[i].getWriteMethod(); if (method != null) { method.invoke(object, new Object[] { value }); } else { /* * object.getClass().getMethod(name, parameterTypes) if() */ if (logger.isInfoEnabled()) { logger.info(object.getClass() + "@" + descriptors[i].getName() + " can not write able"); } } } } catch (Throwable t) { // ignore } } } } //TODO @SuppressWarnings("unchecked") public static Object newBean(BeanObjectEntityConfig beanConfig,Map<String,Object> context) { Object beanvalue = beanConfig.createBeanObject(true,context); // Map bean if (beanvalue instanceof Map) { Map map = (Map) beanvalue; for (Map.Entry<String, Object> entry : beanConfig.getParams().entrySet()) { String key = entry.getKey(); Object mapValue = entry.getValue(); if (mapValue instanceof BeanObjectEntityConfig) { BeanObjectEntityConfig mapBeanConfig = (BeanObjectEntityConfig) entry.getValue(); mapValue = mapBeanConfig.createBeanObject(true); mappingObject(mapValue, mapBeanConfig.getParams(),context); } map.put(key, mapValue); } } else if (beanvalue instanceof List) { } /* // other bean else { mappingObject(beanvalue, beanConfig.getParams(),context); }*/ return beanvalue; } /** * Convert the given string into an acceptable object for the property setter. * * @param cls The class determined from the bean information. * @param string The value to be assigned to the property (as a <code>String</code>). * @return An object suitable for assignment that has the implied value of the string, or <code>null</code> if no * conversion was possible. */ public static Object deStringize(Class<?> cls, String string) { Method method; Object value = null; if (cls.equals(String.class)) { value = string; } else if (cls.equals(Boolean.TYPE)) { value = Boolean.valueOf(string); } else if (cls.equals(Byte.TYPE)) { value = Byte.valueOf(string); } else if (cls.equals(Short.TYPE)) { value = Short.valueOf(string); } else if (cls.equals(Integer.TYPE)) { value = Integer.valueOf(string); } else if (cls.equals(Long.TYPE)) { value = Long.valueOf(string); } else if (cls.equals(Double.TYPE)) { value = Double.valueOf(string); } else if (cls.equals(Float.TYPE)) { value = Float.valueOf(string); } else if ((cls.equals(Boolean.class)) || (cls.equals(Byte.class)) || (cls.equals(Short.class)) || (cls.equals(Integer.class)) || (cls.equals(Long.class)) || (cls.equals(Float.class)) || (cls.equals(Double.class))) { try { method = cls.getMethod("valueOf", new Class[] { String.class }); value = method.invoke(null, new Object[] { string }); } catch (Throwable t) { value = null; // oh well, we tried } } else if (cls.equals(Class.class)) { try { value = Class.forName(string); } catch (ClassNotFoundException e) { logger.error(string + " class not found", e); } } else { value = null; } return (value); } public static boolean isPrimitiveType(Class<?> cls) { if (cls.equals(String.class) || cls.equals(Boolean.TYPE) || cls.equals(Byte.TYPE) || cls.equals(Short.TYPE) || cls.equals(Integer.TYPE) || cls.equals(Long.TYPE) || cls.equals(Double.TYPE) || cls.equals(Float.TYPE) || cls.equals(Boolean.class) || cls.equals(Byte.class) || cls.equals(Short.class) || cls.equals(Integer.class) || cls.equals(Long.class) || cls.equals(Float.class) || cls.equals(Double.class) || cls.equals(Class.class)) { return true; } else { return false; } } public static void mappingObjectField(Object object, Map parameter,Class stopClass){ Class clazz = object.getClass(); while(clazz != stopClass && clazz != null){ Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ Object obj = parameter.get(field.getName()); Object value = obj; Class<?> cls = field.getType(); if (obj instanceof String) { String string = (String) obj; if (!StringUtil.isEmpty(string)) { string = ConfigUtil.filter(string); } if (isPrimitiveType(cls)) { value = deStringize(cls, string); }else{ PropertyTransfer transfer = lookup(cls); if(transfer != null){ value = transfer.transfer(string); } } if (value != null) { if(Modifier.isPublic(field.getModifiers())){ try { field.set(object, value); } catch (Exception e) { e.printStackTrace(); } } } } } clazz = clazz.getSuperclass(); } } /** * mapping object public field with ognlContext * * @param object to be mapping * @param parameter field key/value map * @param context ognl context * @param stopClass */ public static void mappingObjectField(Object object, Map parameter,Map context,Object root,Class stopClass){ Class clazz = object.getClass(); while(clazz != stopClass && clazz != null){ Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ Object obj = parameter.get(field.getName()); Object value = obj; Class<?> cls = field.getType(); if (obj instanceof String) { String string = (String) obj; if (!StringUtil.isEmpty(string)) { string = ConfigUtil.filterWtihOGNL(string, context, root); } if (isPrimitiveType(cls)) { value = deStringize(cls, string); }else{ PropertyTransfer transfer = lookup(cls); if(transfer != null){ value = transfer.transfer(string); } } if (value != null) { if(!Modifier.isPublic(field.getModifiers())){ field.setAccessible(true); } try { field.set(object, value); } catch (Exception e) { e.printStackTrace(); } } } } clazz = clazz.getSuperclass(); } } }