001    /**
002     * 
003     */
004    package org.wdssii.core;
005    
006    import java.beans.BeanInfo;
007    import java.beans.Introspector;
008    import java.beans.PropertyDescriptor;
009    import java.lang.reflect.Method;
010    import java.util.Enumeration;
011    import java.util.HashSet;
012    import java.util.List;
013    import java.util.Properties;
014    import java.util.Set;
015    
016    import org.apache.commons.logging.Log;
017    import org.apache.commons.logging.LogFactory;
018    
019    /**
020     * A generic property setter that uses a Properties file to set properties on an
021     * object. Built on top of java.beans
022     * 
023     * @author lakshman
024     * 
025     */
026    public class PropertyGetterSetter {
027            private static Log log = LogFactory.getLog(PropertyGetterSetter.class);
028    
029            /**
030             * Invoke any setter method on object if the corresponding property is found
031             * in props. If any properties are not set, explanation of why is sent to
032             * the debug log.
033             * 
034             * @param object
035             *            whose setter methods should be invoked
036             * @param props
037             *            contains name=value pairs with the corresponding properties
038             */
039            @SuppressWarnings("unchecked")
040            public static void setProperties(Object object, Properties props) {
041                    try {
042                            BeanInfo p = Introspector.getBeanInfo(object.getClass(),
043                                            Object.class);
044    
045                            // Get the list of all keys, including those in defaults backing
046                            // props
047                            Enumeration keyIter = props.propertyNames();
048                            Set<String> keys = new HashSet<String>();
049                            while (keyIter.hasMoreElements()) {
050                                    keys.add((String) keyIter.nextElement());
051                            }
052    
053                            PropertyDescriptor[] propDescriptors = p.getPropertyDescriptors();
054                            for (PropertyDescriptor propDescriptor : propDescriptors) {
055                                    // get name of property
056                                    String name = propDescriptor.getName();
057    
058                                    if (keys.contains(name) == false) {
059                                            if (log.isDebugEnabled()) {
060                                                    log
061                                                                    .debug("Property "
062                                                                                    + name
063                                                                                    + " not set as the key was not found in properties passed in");
064                                            }
065                                            continue;
066                                    }
067                                    // find setter method and expected param type
068                                    Method setter = propDescriptor.getWriteMethod();
069    
070                                    // set the property
071                                    String value = props.getProperty(name);
072                                    setProperty(object, setter, name, value);
073                            }
074                    } catch (Exception e) {
075                            log.warn("Properties not set: ", e);
076                    }
077            }
078    
079            /**
080             * Invoke all getter methods on object
081             * 
082             * @param object
083             *            whose getter methods should be invoked
084             * @return properties object that contains name=value pairs with the
085             *         corresponding properties
086             */
087            public static Properties getProperties(Object object) {
088                    Properties result = new Properties();
089                    try {
090                            BeanInfo p = Introspector.getBeanInfo(object.getClass(),
091                                            Object.class);
092    
093                            PropertyDescriptor[] propDescriptors = p.getPropertyDescriptors();
094                            for (PropertyDescriptor propDescriptor : propDescriptors) {
095                                    try {
096                                            String name = propDescriptor.getName();
097                                            Method getter = propDescriptor.getReadMethod();
098                                            String value = getter.invoke(object, (Object[]) null)
099                                                            .toString();
100                                            result.setProperty(name, value);
101                                            if (log.isDebugEnabled()) {
102                                                    log.debug(name + "=" + value);
103                                            }
104                                    } catch (Exception e) {
105                                            if (log.isDebugEnabled()) {
106                                                    log.debug("Skipping " + propDescriptor + ": " + e);
107                                            }
108                                    }
109                            }
110                    } catch (Exception e) {
111                            log.error("Could not get properties: ", e);
112                    }
113                    return result;
114            }
115    
116            /**
117             * Invoke setter on object with the provided value.
118             * 
119             * @param object
120             * @param setter
121             * @param name
122             *            name of property (used only for logging)
123             * @param value
124             *            value to call setter method with
125             * @return whether the setter method succeeded. On failure, see debug log.
126             */
127            @SuppressWarnings("unchecked")
128            public static boolean setProperty(Object object, Method setter,
129                            String name, String value) {
130                    Object settableValue = null;
131                    try {
132                            // Find paramType
133                            Class[] paramTypes = setter.getParameterTypes();
134                            if (paramTypes.length != 1) {
135                                    if (log.isDebugEnabled()) {
136                                            log
137                                                            .debug("Not setting "
138                                                                            + name
139                                                                            + " since the number of parameters in setter method is not 1");
140                                    }
141                                    return false;
142                            }
143                            Class paramType = paramTypes[0];
144    
145                            // convert the value to the appropriate type
146                            if (value != null) {
147                                    if (String.class.isAssignableFrom(paramType)) {
148                                            settableValue = value;
149                                    } else if (Boolean.TYPE.isAssignableFrom(paramType)) {
150                                            if (value.equals("true")) {
151                                                    settableValue = Boolean.TRUE;
152                                            } else {
153                                                    settableValue = Boolean.FALSE;
154                                            }
155                                    } else if (Short.TYPE.isAssignableFrom(paramType)) {
156                                            settableValue = Short.parseShort(value);
157                                    } else if (Integer.TYPE.isAssignableFrom(paramType)) {
158                                            settableValue = Integer.parseInt(value);
159                                    } else if (Long.TYPE.isAssignableFrom(paramType)) {
160                                            settableValue = Long.parseLong(value);
161                                    } else if (Float.TYPE.isAssignableFrom(paramType)) {
162                                            settableValue = Float.parseFloat(value);
163                                    } else if (Double.TYPE.isAssignableFrom(paramType)) {
164                                            settableValue = Double.parseDouble(value);
165                                    } else if (double[].class.isAssignableFrom(paramType)){
166                                            List<String> pieces = StringUtil.split(value);
167                                            double[] values = new double[pieces.size()];
168                                            for (int i=0; i < values.length; ++i){
169                                                    values[i] = Double.parseDouble(pieces.get(i));
170                                            }
171                                            settableValue = values;
172                                    } else if (float[].class.isAssignableFrom(paramType)){
173                                            List<String> pieces = StringUtil.split(value);
174                                            float[] values = new float[pieces.size()];
175                                            for (int i=0; i < values.length; ++i){
176                                                    values[i] = Float.parseFloat(pieces.get(i));
177                                            }
178                                            settableValue = values;
179                                    } else if (int[].class.isAssignableFrom(paramType)){
180                                            List<String> pieces = StringUtil.split(value);
181                                            int[] values = new int[pieces.size()];
182                                            for (int i=0; i < values.length; ++i){
183                                                    values[i] = Integer.parseInt(pieces.get(i));
184                                            }
185                                            settableValue = values;
186                                    }
187                                    else {
188                                            log.debug("Unsupported type: " + paramType);
189                                            return false;
190                                    }
191                            }
192    
193                            // invoke method
194                            setter.invoke(object, new Object[] { settableValue });
195                            if (log.isInfoEnabled()) {
196                                    log.info("Set " + name + "=" + settableValue);
197                            }
198                            return true;
199                    } catch (Exception e) {
200                            log.debug(
201                                            "Unable to set name= " + name + " value=" + settableValue,
202                                            e);
203                            return false;
204                    }
205            }
206    }